You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
292 lines
7.6 KiB
292 lines
7.6 KiB
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) |
|
#pragma warning disable |
|
using System; |
|
|
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities; |
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities; |
|
|
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests |
|
{ |
|
|
|
/** |
|
* implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349. |
|
* |
|
* It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5 |
|
* is the "endianness" of the word processing! |
|
*/ |
|
|
|
|
|
|
|
[BestHTTP.PlatformSupport.IL2CPP.Il2CppEagerStaticClassConstructionAttribute] |
|
public class Sha1Digest |
|
: GeneralDigest |
|
{ |
|
private const int DigestLength = 20; |
|
|
|
private uint H1, H2, H3, H4, H5; |
|
|
|
private uint[] X = new uint[80]; |
|
private int xOff; |
|
|
|
public Sha1Digest() |
|
{ |
|
Reset(); |
|
} |
|
|
|
/** |
|
* Copy constructor. This will copy the state of the provided |
|
* message digest. |
|
*/ |
|
public Sha1Digest(Sha1Digest t) |
|
: base(t) |
|
{ |
|
CopyIn(t); |
|
} |
|
|
|
private void CopyIn(Sha1Digest t) |
|
{ |
|
base.CopyIn(t); |
|
|
|
H1 = t.H1; |
|
H2 = t.H2; |
|
H3 = t.H3; |
|
H4 = t.H4; |
|
H5 = t.H5; |
|
|
|
Array.Copy(t.X, 0, X, 0, t.X.Length); |
|
xOff = t.xOff; |
|
} |
|
|
|
public override string AlgorithmName |
|
{ |
|
get { return "SHA-1"; } |
|
} |
|
|
|
public override int GetDigestSize() |
|
{ |
|
return DigestLength; |
|
} |
|
|
|
internal override void ProcessWord( |
|
byte[] input, |
|
int inOff) |
|
{ |
|
X[xOff] = Pack.BE_To_UInt32(input, inOff); |
|
|
|
if (++xOff == 16) |
|
{ |
|
ProcessBlock(); |
|
} |
|
} |
|
|
|
internal override void ProcessLength(long bitLength) |
|
{ |
|
if (xOff > 14) |
|
{ |
|
ProcessBlock(); |
|
} |
|
|
|
X[14] = (uint)((ulong)bitLength >> 32); |
|
X[15] = (uint)((ulong)bitLength); |
|
} |
|
|
|
public override int DoFinal( |
|
byte[] output, |
|
int outOff) |
|
{ |
|
Finish(); |
|
|
|
Pack.UInt32_To_BE(H1, output, outOff); |
|
Pack.UInt32_To_BE(H2, output, outOff + 4); |
|
Pack.UInt32_To_BE(H3, output, outOff + 8); |
|
Pack.UInt32_To_BE(H4, output, outOff + 12); |
|
Pack.UInt32_To_BE(H5, output, outOff + 16); |
|
|
|
Reset(); |
|
|
|
return DigestLength; |
|
} |
|
|
|
/** |
|
* reset the chaining variables |
|
*/ |
|
public override void Reset() |
|
{ |
|
base.Reset(); |
|
|
|
H1 = 0x67452301; |
|
H2 = 0xefcdab89; |
|
H3 = 0x98badcfe; |
|
H4 = 0x10325476; |
|
H5 = 0xc3d2e1f0; |
|
|
|
xOff = 0; |
|
Array.Clear(X, 0, X.Length); |
|
} |
|
|
|
// |
|
// Additive constants |
|
// |
|
private const uint Y1 = 0x5a827999; |
|
private const uint Y2 = 0x6ed9eba1; |
|
private const uint Y3 = 0x8f1bbcdc; |
|
private const uint Y4 = 0xca62c1d6; |
|
|
|
private static uint F(uint u, uint v, uint w) |
|
{ |
|
return (u & v) | (~u & w); |
|
} |
|
|
|
private static uint H(uint u, uint v, uint w) |
|
{ |
|
return u ^ v ^ w; |
|
} |
|
|
|
private static uint G(uint u, uint v, uint w) |
|
{ |
|
return (u & v) | (u & w) | (v & w); |
|
} |
|
|
|
internal override void ProcessBlock() |
|
{ |
|
// |
|
// expand 16 word block into 80 word block. |
|
// |
|
for (int i = 16; i < 80; i++) |
|
{ |
|
uint t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16]; |
|
X[i] = t << 1 | t >> 31; |
|
} |
|
|
|
// |
|
// set up working variables. |
|
// |
|
uint A = H1; |
|
uint B = H2; |
|
uint C = H3; |
|
uint D = H4; |
|
uint E = H5; |
|
|
|
// |
|
// round 1 |
|
// |
|
int idx = 0; |
|
|
|
for (int j = 0; j < 4; j++) |
|
{ |
|
// E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1 |
|
// B = rotateLeft(B, 30) |
|
E += (A << 5 | (A >> 27)) + F(B, C, D) + X[idx++] + Y1; |
|
B = B << 30 | (B >> 2); |
|
|
|
D += (E << 5 | (E >> 27)) + F(A, B, C) + X[idx++] + Y1; |
|
A = A << 30 | (A >> 2); |
|
|
|
C += (D << 5 | (D >> 27)) + F(E, A, B) + X[idx++] + Y1; |
|
E = E << 30 | (E >> 2); |
|
|
|
B += (C << 5 | (C >> 27)) + F(D, E, A) + X[idx++] + Y1; |
|
D = D << 30 | (D >> 2); |
|
|
|
A += (B << 5 | (B >> 27)) + F(C, D, E) + X[idx++] + Y1; |
|
C = C << 30 | (C >> 2); |
|
} |
|
|
|
// |
|
// round 2 |
|
// |
|
for (int j = 0; j < 4; j++) |
|
{ |
|
// E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2 |
|
// B = rotateLeft(B, 30) |
|
E += (A << 5 | (A >> 27)) + H(B, C, D) + X[idx++] + Y2; |
|
B = B << 30 | (B >> 2); |
|
|
|
D += (E << 5 | (E >> 27)) + H(A, B, C) + X[idx++] + Y2; |
|
A = A << 30 | (A >> 2); |
|
|
|
C += (D << 5 | (D >> 27)) + H(E, A, B) + X[idx++] + Y2; |
|
E = E << 30 | (E >> 2); |
|
|
|
B += (C << 5 | (C >> 27)) + H(D, E, A) + X[idx++] + Y2; |
|
D = D << 30 | (D >> 2); |
|
|
|
A += (B << 5 | (B >> 27)) + H(C, D, E) + X[idx++] + Y2; |
|
C = C << 30 | (C >> 2); |
|
} |
|
|
|
// |
|
// round 3 |
|
// |
|
for (int j = 0; j < 4; j++) |
|
{ |
|
// E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3 |
|
// B = rotateLeft(B, 30) |
|
E += (A << 5 | (A >> 27)) + G(B, C, D) + X[idx++] + Y3; |
|
B = B << 30 | (B >> 2); |
|
|
|
D += (E << 5 | (E >> 27)) + G(A, B, C) + X[idx++] + Y3; |
|
A = A << 30 | (A >> 2); |
|
|
|
C += (D << 5 | (D >> 27)) + G(E, A, B) + X[idx++] + Y3; |
|
E = E << 30 | (E >> 2); |
|
|
|
B += (C << 5 | (C >> 27)) + G(D, E, A) + X[idx++] + Y3; |
|
D = D << 30 | (D >> 2); |
|
|
|
A += (B << 5 | (B >> 27)) + G(C, D, E) + X[idx++] + Y3; |
|
C = C << 30 | (C >> 2); |
|
} |
|
|
|
// |
|
// round 4 |
|
// |
|
for (int j = 0; j < 4; j++) |
|
{ |
|
// E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4 |
|
// B = rotateLeft(B, 30) |
|
E += (A << 5 | (A >> 27)) + H(B, C, D) + X[idx++] + Y4; |
|
B = B << 30 | (B >> 2); |
|
|
|
D += (E << 5 | (E >> 27)) + H(A, B, C) + X[idx++] + Y4; |
|
A = A << 30 | (A >> 2); |
|
|
|
C += (D << 5 | (D >> 27)) + H(E, A, B) + X[idx++] + Y4; |
|
E = E << 30 | (E >> 2); |
|
|
|
B += (C << 5 | (C >> 27)) + H(D, E, A) + X[idx++] + Y4; |
|
D = D << 30 | (D >> 2); |
|
|
|
A += (B << 5 | (B >> 27)) + H(C, D, E) + X[idx++] + Y4; |
|
C = C << 30 | (C >> 2); |
|
} |
|
|
|
H1 += A; |
|
H2 += B; |
|
H3 += C; |
|
H4 += D; |
|
H5 += E; |
|
|
|
// |
|
// reset start of the buffer. |
|
// |
|
xOff = 0; |
|
Array.Clear(X, 0, 16); |
|
} |
|
|
|
public override IMemoable Copy() |
|
{ |
|
return new Sha1Digest(this); |
|
} |
|
|
|
public override void Reset(IMemoable other) |
|
{ |
|
Sha1Digest d = (Sha1Digest)other; |
|
|
|
CopyIn(d); |
|
} |
|
|
|
} |
|
} |
|
#pragma warning restore |
|
#endif
|
|
|