3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // <OWNER>Microsoft</OWNER>
13 namespace System.Security.Cryptography {
15 using System.Security;
16 using System.Diagnostics.Contracts;
18 [System.Runtime.InteropServices.ComVisible(true)]
19 public class SHA1Managed : SHA1
21 private byte[] _buffer;
22 private long _count; // Number of bytes in the hashed message
23 private uint[] _stateSHA1;
24 private uint[] _expandedBuffer;
27 // public constructors
33 if (CryptoConfig.AllowOnlyFipsAlgorithms)
34 throw new InvalidOperationException(Environment.GetResourceString("Cryptography_NonCompliantFIPSAlgorithm"));
35 Contract.EndContractBlock();
36 #endif // FEATURE_CRYPTO
38 _stateSHA1 = new uint[5];
39 _buffer = new byte[64];
40 _expandedBuffer = new uint[80];
49 public override void Initialize() {
52 // Zeroize potentially sensitive information.
53 Array.Clear(_buffer, 0, _buffer.Length);
54 Array.Clear(_expandedBuffer, 0, _expandedBuffer.Length);
57 protected override void HashCore(byte[] rgb, int ibStart, int cbSize) {
58 _HashData(rgb, ibStart, cbSize);
61 protected override byte[] HashFinal() {
69 private void InitializeState() {
72 _stateSHA1[0] = 0x67452301;
73 _stateSHA1[1] = 0xefcdab89;
74 _stateSHA1[2] = 0x98badcfe;
75 _stateSHA1[3] = 0x10325476;
76 _stateSHA1[4] = 0xc3d2e1f0;
79 /* Copyright (C) RSA Data Security, Inc. created 1993. This is an
80 unpublished work protected as such under copyright law. This work
81 contains proprietary, confidential, and trade secret information of
82 RSA Data Security, Inc. Use, disclosure or reproduction without the
83 express written authorization of RSA Data Security, Inc. is
87 /* SHA block update operation. Continues an SHA message-digest
88 operation, processing another message block, and updating the
91 [System.Security.SecuritySafeCritical] // auto-generated
92 private unsafe void _HashData(byte[] partIn, int ibStart, int cbSize)
95 int partInLen = cbSize;
96 int partInBase = ibStart;
98 /* Compute length of buffer */
99 bufferLen = (int) (_count & 0x3f);
101 /* Update number of bytes */
104 fixed (uint* stateSHA1 = _stateSHA1) {
105 fixed (byte* buffer = _buffer) {
106 fixed (uint* expandedBuffer = _expandedBuffer) {
107 if ((bufferLen > 0) && (bufferLen + partInLen >= 64)) {
108 Buffer.InternalBlockCopy(partIn, partInBase, _buffer, bufferLen, 64 - bufferLen);
109 partInBase += (64 - bufferLen);
110 partInLen -= (64 - bufferLen);
111 SHATransform(expandedBuffer, stateSHA1, buffer);
115 /* Copy input to temporary buffer and hash */
116 while (partInLen >= 64) {
117 Buffer.InternalBlockCopy(partIn, partInBase, _buffer, 0, 64);
120 SHATransform(expandedBuffer, stateSHA1, buffer);
124 Buffer.InternalBlockCopy(partIn, partInBase, _buffer, bufferLen, partInLen);
131 /* SHA finalization. Ends an SHA message-digest operation, writing
135 private byte[] _EndHash()
140 byte[] hash = new byte[20];
142 /* Compute padding: 80 00 00 ... 00 00 <bit count>
145 padLen = 64 - (int)(_count & 0x3f);
149 pad = new byte[padLen];
152 // Convert count to bit count
153 bitCount = _count * 8;
155 pad[padLen-8] = (byte) ((bitCount >> 56) & 0xff);
156 pad[padLen-7] = (byte) ((bitCount >> 48) & 0xff);
157 pad[padLen-6] = (byte) ((bitCount >> 40) & 0xff);
158 pad[padLen-5] = (byte) ((bitCount >> 32) & 0xff);
159 pad[padLen-4] = (byte) ((bitCount >> 24) & 0xff);
160 pad[padLen-3] = (byte) ((bitCount >> 16) & 0xff);
161 pad[padLen-2] = (byte) ((bitCount >> 8) & 0xff);
162 pad[padLen-1] = (byte) ((bitCount >> 0) & 0xff);
165 _HashData(pad, 0, pad.Length);
168 Utils.DWORDToBigEndian (hash, _stateSHA1, 5);
174 [System.Security.SecurityCritical] // auto-generated
175 private static unsafe void SHATransform (uint* expandedBuffer, uint* state, byte* block)
185 Utils.DWORDFromBigEndian(expandedBuffer, 16, block);
186 SHAExpand(expandedBuffer);
189 for (i=0; i<20; i+= 5) {
190 { (e) += (((((a)) << (5)) | (((a)) >> (32-(5)))) + ( (d) ^ ( (b) & ( (c) ^ (d) ) ) ) + (expandedBuffer[i]) + 0x5a827999); (b) = ((((b)) << (30)) | (((b)) >> (32-(30)))); }
191 { (d) += (((((e)) << (5)) | (((e)) >> (32-(5)))) + ( (c) ^ ( (a) & ( (b) ^ (c) ) ) ) + (expandedBuffer[i+1]) + 0x5a827999); (a) = ((((a)) << (30)) | (((a)) >> (32-(30)))); }
192 { (c) += (((((d)) << (5)) | (((d)) >> (32-(5)))) + ( (b) ^ ( (e) & ( (a) ^ (b) ) ) ) + (expandedBuffer[i+2]) + 0x5a827999); (e) = ((((e)) << (30)) | (((e)) >> (32-(30)))); };;
193 { (b) += (((((c)) << (5)) | (((c)) >> (32-(5)))) + ( (a) ^ ( (d) & ( (e) ^ (a) ) ) ) + (expandedBuffer[i+3]) + 0x5a827999); (d) = ((((d)) << (30)) | (((d)) >> (32-(30)))); };;
194 { (a) += (((((b)) << (5)) | (((b)) >> (32-(5)))) + ( (e) ^ ( (c) & ( (d) ^ (e) ) ) ) + (expandedBuffer[i+4]) + 0x5a827999); (c) = ((((c)) << (30)) | (((c)) >> (32-(30)))); };;
198 for (; i<40; i+= 5) {
199 { (e) += (((((a)) << (5)) | (((a)) >> (32-(5)))) + ((b) ^ (c) ^ (d)) + (expandedBuffer[i]) + 0x6ed9eba1); (b) = ((((b)) << (30)) | (((b)) >> (32-(30)))); };;
200 { (d) += (((((e)) << (5)) | (((e)) >> (32-(5)))) + ((a) ^ (b) ^ (c)) + (expandedBuffer[i+1]) + 0x6ed9eba1); (a) = ((((a)) << (30)) | (((a)) >> (32-(30)))); };;
201 { (c) += (((((d)) << (5)) | (((d)) >> (32-(5)))) + ((e) ^ (a) ^ (b)) + (expandedBuffer[i+2]) + 0x6ed9eba1); (e) = ((((e)) << (30)) | (((e)) >> (32-(30)))); };;
202 { (b) += (((((c)) << (5)) | (((c)) >> (32-(5)))) + ((d) ^ (e) ^ (a)) + (expandedBuffer[i+3]) + 0x6ed9eba1); (d) = ((((d)) << (30)) | (((d)) >> (32-(30)))); };;
203 { (a) += (((((b)) << (5)) | (((b)) >> (32-(5)))) + ((c) ^ (d) ^ (e)) + (expandedBuffer[i+4]) + 0x6ed9eba1); (c) = ((((c)) << (30)) | (((c)) >> (32-(30)))); };;
208 { (e) += (((((a)) << (5)) | (((a)) >> (32-(5)))) + ( ( (b) & (c) ) | ( (d) & ( (b) | (c) ) ) ) + (expandedBuffer[i]) + 0x8f1bbcdc); (b) = ((((b)) << (30)) | (((b)) >> (32-(30)))); };;
209 { (d) += (((((e)) << (5)) | (((e)) >> (32-(5)))) + ( ( (a) & (b) ) | ( (c) & ( (a) | (b) ) ) ) + (expandedBuffer[i+1]) + 0x8f1bbcdc); (a) = ((((a)) << (30)) | (((a)) >> (32-(30)))); };;
210 { (c) += (((((d)) << (5)) | (((d)) >> (32-(5)))) + ( ( (e) & (a) ) | ( (b) & ( (e) | (a) ) ) ) + (expandedBuffer[i+2]) + 0x8f1bbcdc); (e) = ((((e)) << (30)) | (((e)) >> (32-(30)))); };;
211 { (b) += (((((c)) << (5)) | (((c)) >> (32-(5)))) + ( ( (d) & (e) ) | ( (a) & ( (d) | (e) ) ) ) + (expandedBuffer[i+3]) + 0x8f1bbcdc); (d) = ((((d)) << (30)) | (((d)) >> (32-(30)))); };;
212 { (a) += (((((b)) << (5)) | (((b)) >> (32-(5)))) + ( ( (c) & (d) ) | ( (e) & ( (c) | (d) ) ) ) + (expandedBuffer[i+4]) + 0x8f1bbcdc); (c) = ((((c)) << (30)) | (((c)) >> (32-(30)))); };;
217 { (e) += (((((a)) << (5)) | (((a)) >> (32-(5)))) + ((b) ^ (c) ^ (d)) + (expandedBuffer[i]) + 0xca62c1d6); (b) = ((((b)) << (30)) | (((b)) >> (32-(30)))); };;
218 { (d) += (((((e)) << (5)) | (((e)) >> (32-(5)))) + ((a) ^ (b) ^ (c)) + (expandedBuffer[i+1]) + 0xca62c1d6); (a) = ((((a)) << (30)) | (((a)) >> (32-(30)))); };;
219 { (c) += (((((d)) << (5)) | (((d)) >> (32-(5)))) + ((e) ^ (a) ^ (b)) + (expandedBuffer[i+2]) + 0xca62c1d6); (e) = ((((e)) << (30)) | (((e)) >> (32-(30)))); };;
220 { (b) += (((((c)) << (5)) | (((c)) >> (32-(5)))) + ((d) ^ (e) ^ (a)) + (expandedBuffer[i+3]) + 0xca62c1d6); (d) = ((((d)) << (30)) | (((d)) >> (32-(30)))); };;
221 { (a) += (((((b)) << (5)) | (((b)) >> (32-(5)))) + ((c) ^ (d) ^ (e)) + (expandedBuffer[i+4]) + 0xca62c1d6); (c) = ((((c)) << (30)) | (((c)) >> (32-(30)))); };;
231 /* Expands x[0..15] into x[16..79], according to the recurrence
232 x[i] = x[i-3] ^ x[i-8] ^ x[i-14] ^ x[i-16].
235 [System.Security.SecurityCritical] // auto-generated
236 private static unsafe void SHAExpand (uint* x)
241 for (i = 16; i < 80; i++) {
242 tmp = (x[i-3] ^ x[i-8] ^ x[i-14] ^ x[i-16]);
243 x[i] = ((tmp << 1) | (tmp >> 31));