public static byte[] PBKDF2(byte[] password, byte[] salt, int iterCount, int cOctets, IDigest digest) { // PRF = HMAC- SHA (256, 384, 512) // P = passsword // S = salt // c = iteration count // dkLen = cbits in octets // l = CIEL(dkLen / hLen) // r = dkLen - (l - 1)*hLen // T_n = F ( P, S, c, n) (iterate n=1 to l) // F ( P, S, c, i) = U_1 ^ U_2 ^ ... ^ U_c // U_1 = PRF( P, S || INT (i)) // U_2 = PRF( P, U_1 ) // U_c = PRF( P, U_{c-1}) // INT = int32- big-ending HMac hmac = new HMac(digest); ICipherParameters k = new KeyParameter(password); hmac.Init(k); int hLen = hmac.GetMacSize(); int l = (cOctets + hLen - 1) / hLen; byte[] rgbStart = new byte[salt.Length + 4]; Array.Copy(salt, 0, rgbStart, 0, salt.Length); byte[] rgbOutput = new byte[l * hLen]; for (int i = 1; i <= l; i++) { byte[] rgbT = new byte[hLen]; byte[] rgbH = new byte[hLen]; hmac.Reset(); rgbStart[rgbStart.Length - 1] = (byte)i; hmac.BlockUpdate(rgbStart, 0, rgbStart.Length); hmac.DoFinal(rgbH, 0); Array.Copy(rgbH, rgbT, rgbH.Length); for (int j = 1; j < iterCount; j++) { hmac.Reset(); hmac.BlockUpdate(rgbH, 0, rgbH.Length); hmac.DoFinal(rgbH, 0); for (int k1 = 0; k1 < rgbH.Length; k1++) { rgbT[k1] ^= rgbH[k1]; } } Array.Copy(rgbT, hLen * (i - 1), rgbOutput, 0, rgbT.Length); } byte[] rgbOut = new Byte[cOctets]; Array.Copy(rgbOutput, rgbOut, cOctets); return(rgbOut); }
private Byte[] P_hash(Byte[] secret, Byte[] seed, Int32 size, IDigest digest) { var needed = size; var md = new HMac(digest); var key = new KeyParameter(secret); md.Init(key); // A_0 is initialized with seed var a0 = new Byte[seed.Length]; Array.Copy(seed, 0, a0, 0, a0.Length); // A_i is HMAC of previous A var aI = new Byte[md.GetMacSize()]; md.BlockUpdate(a0, 0, a0.Length); md.DoFinal(aI, 0); md.Reset(); var ret = new Byte[needed]; var outBuff = new Byte[md.GetMacSize()]; while (needed > 0) { md.Init(key); // Add to return value md.BlockUpdate(aI, 0, aI.Length); md.BlockUpdate(seed, 0, seed.Length); md.DoFinal(outBuff, 0); md.Reset(); var lenToCopy = needed < md.GetMacSize()? needed : md.GetMacSize(); Array.Copy(outBuff, 0, ret, size - needed, lenToCopy); // Update new A md.Init(key); md.BlockUpdate(aI, 0, aI.Length); md.DoFinal(aI, 0); md.Reset(); // Update needed field needed -= md.GetMacSize(); } return(ret); }
private void ComputeNextBlock(HMac hash) { BigEndian.CopyBytes(m_blockNumber, m_saltWithBlock, m_saltWithBlock.Length - 4); byte[] final = new byte[hash.GetMacSize()]; byte[] tmp = new byte[hash.GetMacSize()]; //InitialPass: U1 = PRF(Password, Salt || INT_32_BE(i)) hash.Reset(); hash.BlockUpdate(m_saltWithBlock, 0, m_saltWithBlock.Length); hash.DoFinal(final, 0); final.CopyTo(tmp, 0); for (int iteration = 1; iteration < m_iterations; iteration++) { //U2 = PRF(Password, U1) //hash.Reset(); hash.BlockUpdate(tmp, 0, tmp.Length); hash.DoFinal(tmp, 0); for (int x = 0; x < tmp.Length; x++) { final[x] ^= tmp[x]; } } m_blockNumber++; foreach (var b in final) { m_results.Enqueue(b); } }
public virtual byte[] CalculateMacConstantTime(ContentType type, byte[] message, int offset, int len, int fullLength, byte[] dummyData) { // Actual MAC only calculated on 'len' bytes byte[] result = CalculateMac(type, message, offset, len); //bool isTls = context.ServerVersion.FullVersion >= ProtocolVersion.TLSv10.FullVersion; bool isTls = true; // ...but ensure a constant number of complete digest blocks are processed (per 'fullLength') if (isTls) { // TODO Currently all TLS digests use a block size of 64, a suffix (length field) of 8, and padding (1+) int db = 64, ds = 8; int L1 = 13 + fullLength; int L2 = 13 + len; // How many extra full blocks do we need to calculate? int extra = ((L1 + ds) / db) - ((L2 + ds) / db); while (--extra >= 0) { mac.BlockUpdate(dummyData, 0, db); } // One more byte in case the implementation is "lazy" about processing blocks mac.Update(dummyData[0]); mac.Reset(); } return(result); }
/** * Calculate the mac for some given data. * <p/> * TlsMac will keep track of the sequence number internally. * * @param type The message type of the message. * @param message A byte-buffer containing the message. * @param offset The number of bytes to skip, before the message starts. * @param len The length of the message. * @return A new byte-buffer containing the mac value. */ internal byte[] CalculateMac( short type, byte[] message, int offset, int len) { try { MemoryStream bosMac = new MemoryStream(13 + len); TlsUtilities.WriteUint64(seqNo++, bosMac); TlsUtilities.WriteUint8(type, bosMac); TlsUtilities.WriteVersion(bosMac); TlsUtilities.WriteUint16(len, bosMac); bosMac.Write(message, offset, len); byte[] macData = bosMac.ToArray(); mac.BlockUpdate(macData, 0, macData.Length); byte[] result = new byte[mac.GetMacSize()]; mac.DoFinal(result, 0); mac.Reset(); return(result); } catch (IOException) { // This should never happen throw new InvalidOperationException("Internal error during mac calculation"); } }
byte[] HashFinal() { var value = new byte[hash.GetMacSize()]; hash.DoFinal(value, 0); hash.Reset(); return(value); }
public bool Verify(byte[] data, string tag) { byte[] output = new byte[_hmac.GetMacSize()]; _hmac.Reset(); _hmac.BlockUpdate(data, 0, data.Length); _hmac.DoFinal(output, 0); return(output.SequenceEqual(Base64.Decode(tag))); }
/// <summary> /// Releases the unmanaged resources used by the <see cref="T:System.IO.Stream"/> and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { Finish(); if (disposing) { _hmacAlg.Reset(); } _hmacAlg = null; base.Dispose(disposing); }
/// <summary> /// Releases the unmanaged resources used by the <see cref="T:System.IO.Stream"/> and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { Finish(); if (disposing) { _hmacAlg.Reset(); _hashValue.Clear(); _fullHashValue.Clear(); } _hmacAlg = null; base.Dispose(disposing); }
public virtual ITestResult Perform() { HMac hmac = new HMac(new Sha384Digest()); byte[] resBuf = new byte[hmac.GetMacSize()]; for (int i = 0; i < messages.Length; i++) { byte[] m = Encoding.ASCII.GetBytes(messages[i]); if (messages[i].StartsWith("0x")) { m = Hex.Decode(messages[i].Substring(2)); } hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); hmac.BlockUpdate(m, 0, m.Length); hmac.DoFinal(resBuf, 0); if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) { return(new SimpleTestResult(false, Name + ": Vector " + i + " failed")); } } // // test reset // int vector = 0; // vector used for test byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]); if (messages[vector].StartsWith("0x")) { m2 = Hex.Decode(messages[vector].Substring(2)); } hmac.Init(new KeyParameter(Hex.Decode(keys[vector]))); hmac.BlockUpdate(m2, 0, m2.Length); hmac.DoFinal(resBuf, 0); hmac.Reset(); hmac.BlockUpdate(m2, 0, m2.Length); hmac.DoFinal(resBuf, 0); if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector]))) { return(new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed")); } return(new SimpleTestResult(true, Name + ": Okay")); }
private static byte[] HKDF(byte[] secret, byte[] salt, byte[] info, int cbit, IDigest digest) { // Now start doing HKDF // Perform the Extract phase HMac mac = new HMac(digest); int hashLength = digest.GetDigestSize(); int c = ((cbit + 7) / 8 + hashLength - 1) / hashLength; if (salt == null) { salt = new byte[0]; } KeyParameter key = new KeyParameter(salt); mac.Init(key); mac.BlockUpdate(secret, 0, secret.Length); byte[] rgbExtract = new byte[hashLength]; mac.DoFinal(rgbExtract, 0); // Now do the Expand Phase byte[] rgbOut = new byte[cbit / 8]; byte[] rgbT = new byte[hashLength * c]; mac = new HMac(digest); key = new KeyParameter(rgbExtract); mac.Init(key); byte[] rgbLast = new byte[0]; byte[] rgbHash2 = new byte[hashLength]; for (int i = 0; i < c; i++) { mac.Reset(); mac.BlockUpdate(rgbLast, 0, rgbLast.Length); mac.BlockUpdate(info, 0, info.Length); mac.Update((byte)(i + 1)); rgbLast = rgbHash2; mac.DoFinal(rgbLast, 0); Array.Copy(rgbLast, 0, rgbT, i * hashLength, hashLength); } Array.Copy(rgbT, 0, rgbOut, 0, cbit / 8); return(rgbOut); }
public override void PerformTest() { HMac hmac = new HMac(new NonMemoableDigest(new Sha1Digest())); byte[] resBuf = new byte[hmac.GetMacSize()]; for (int i = 0; i < messages.Length; i++) { byte[] m = Strings.ToByteArray(messages[i]); if (messages[i].StartsWith("0x")) { m = Hex.Decode(messages[i].Substring(2)); } hmac.Init(new KeyParameter(Hex.Decode(keys[i]))); hmac.BlockUpdate(m, 0, m.Length); hmac.DoFinal(resBuf, 0); if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i]))) { Fail(Name + ": Vector " + i + " failed"); } } // // test reset // { int vector = 0; // vector used for test byte[] m = Strings.ToByteArray(messages[vector]); if (messages[vector].StartsWith("0x")) { m = Hex.Decode(messages[vector].Substring(2)); } hmac.Init(new KeyParameter(Hex.Decode(keys[vector]))); hmac.BlockUpdate(m, 0, m.Length); hmac.DoFinal(resBuf, 0); hmac.Reset(); hmac.BlockUpdate(m, 0, m.Length); hmac.DoFinal(resBuf, 0); if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector]))) { Fail(Name + ": Reset with vector " + vector + " failed"); } } }
public void Initialize() { Hmac.Reset(); }
/// <summary> /// Create two streched keys from the shared secret. /// </summary> /// <remarks> /// The is no spec for this. Copied https://github.com/libp2p/go-libp2p-crypto/blob/0f79fbebcb64f746a636aba79ece0635ec5919e9/key.go#L183 /// </remarks> public static void Generate(string cipherName, string hashName, byte[] secret, out StretchedKey k1, out StretchedKey k2) { int cipherKeySize; int ivSize; switch (cipherName) { case "AES-128": ivSize = 16; cipherKeySize = 16; break; case "AES-256": ivSize = 16; cipherKeySize = 32; break; case "Blowfish": ivSize = 8; cipherKeySize = 32; break; default: throw new NotSupportedException($"Cipher '{cipherName}' is not supported."); } var hmacKeySize = 20; var need = 2 * (ivSize + cipherKeySize + hmacKeySize); var hmac = new HMac(DigestUtilities.GetDigest(hashName)); var kp = new KeyParameter(secret); var seed = Encoding.ASCII.GetBytes("key expansion"); hmac.Init(kp); var a = new byte[hmac.GetMacSize()]; var b = new byte[hmac.GetMacSize()]; hmac.BlockUpdate(seed, 0, seed.Length); hmac.DoFinal(a, 0); var j = 0; var result = new byte[need]; while (j < need) { hmac.Reset(); hmac.BlockUpdate(a, 0, a.Length); hmac.BlockUpdate(seed, 0, seed.Length); hmac.DoFinal(b, 0); var todo = b.Length; if (j + todo > need) { todo = need - j; } Buffer.BlockCopy(b, 0, result, j, todo); j += todo; hmac.Reset(); hmac.BlockUpdate(a, 0, a.Length); hmac.DoFinal(a, 0); } var half = need / 2; k1 = new StretchedKey { Iv = new byte[ivSize], CipherKey = new byte[cipherKeySize], MacKey = new byte[hmacKeySize] }; Buffer.BlockCopy(result, 0, k1.Iv, 0, ivSize); Buffer.BlockCopy(result, ivSize, k1.CipherKey, 0, cipherKeySize); Buffer.BlockCopy(result, ivSize + cipherKeySize, k1.MacKey, 0, hmacKeySize); k2 = new StretchedKey { Iv = new byte[ivSize], CipherKey = new byte[cipherKeySize], MacKey = new byte[hmacKeySize] }; Buffer.BlockCopy(result, half, k2.Iv, 0, ivSize); Buffer.BlockCopy(result, half + ivSize, k2.CipherKey, 0, cipherKeySize); Buffer.BlockCopy(result, half + ivSize + cipherKeySize, k2.MacKey, 0, hmacKeySize); }
public static Tuple <StretchedKeys, StretchedKeys> Generate(string cipherType, string hashType, byte[] secret) { var cipherKeySize = 0; var ivSize = 0; switch (cipherType) { case "AES-128": ivSize = 16; cipherKeySize = 16; break; case "AES-256": ivSize = 16; cipherKeySize = 32; break; case "Blowfish": ivSize = 8; cipherKeySize = 32; break; } var hmacKeySize = 20; var seed = Encoding.UTF8.GetBytes("key expansion"); var result = new byte[2 * (ivSize + cipherKeySize + hmacKeySize)]; var m = new HMac(DigestUtilities.GetDigest(hashType)); m.Init(new KeyParameter(secret)); m.BlockUpdate(seed, 0, seed.Length); var a = new byte[m.GetMacSize()]; m.DoFinal(a, 0); var j = 0; while (j < result.Length) { m.Reset(); m.BlockUpdate(a, 0, a.Length); m.BlockUpdate(seed, 0, seed.Length); var b = new byte[m.GetMacSize()]; m.DoFinal(b, 0); var todo = b.Length; if (j + todo > result.Length) { todo = result.Length - j; } Buffer.BlockCopy(b, 0, result, j, todo); j += todo; m.Reset(); m.BlockUpdate(a, 0, a.Length); m.DoFinal(a, 0); } var half = result.Length / 2; var r1 = result.Slice(0, half); var r2 = result.Slice(half); var k1 = new StretchedKeys { IV = r1.Slice(0, ivSize), CipherKey = r1.Slice(ivSize, cipherKeySize), MacKey = r1.Slice(ivSize + cipherKeySize) }; var k2 = new StretchedKeys { IV = r2.Slice(0, ivSize), CipherKey = r2.Slice(ivSize, cipherKeySize), MacKey = r2.Slice(ivSize + cipherKeySize) }; return(Tuple.Create(k1, k2)); }