private static unsafe void Pbkdf2HmacSha256(ProtectedMemory password, byte *salt, int saltLength, long c, int dkLen, byte *result) { if (c < 1) { throw new ArgumentException("The count " + nameof(c) + " cannot be less than 1!"); } const int digestLength = 0x20; int blockCount = (int)Math.Ceiling((double)dkLen / digestLength); int saltBufferLength = saltLength + sizeof(int); IntPtr hSaltBuffer = Marshal.AllocHGlobal(saltBufferLength); byte * saltBuffer = (byte *)hSaltBuffer; Unsafe.CopyBlock(saltBuffer, salt, (uint)saltLength); for (int i = 1; i <= blockCount; i++) { MarshalExtensions.WriteInt32BigEndian(saltBuffer + saltLength, i); Sha256ProtectedCryptoProvider sha256 = new Sha256ProtectedCryptoProvider(); (IntPtr hU, _) = sha256.ComputeHmacUnsafe(password, saltBuffer, saltBufferLength); Unsafe.CopyBlock(result + ((i - 1) * digestLength), (void *)hU, digestLength); MarshalExtensions.ZeroFree(hU, digestLength); for (long j = 1; j < c; j++) { (IntPtr hUi, _) = sha256.ComputeHmacUnsafe(password, saltBuffer, digestLength); byte *ui = (byte *)hUi; for (int k = 0; k < digestLength; k++) { (result + ((i - 1) * digestLength))[k] ^= ui[k]; } MarshalExtensions.ZeroFree(hUi, digestLength); } } MarshalExtensions.ZeroFree(hSaltBuffer, saltBufferLength); }
private static unsafe void Sha256HmacTests2() { byte[] key = Encoding.UTF8.GetBytes("ABCD"); IntPtr hMessage = Marshal.AllocHGlobal(32 + sizeof(int)); byte[] message = new byte[] { 0x4c, 0x1e, 0x67, 0xcb, 0xa2, 0xc8, 0xf4, 0xac, 0xb0, 0x53, 0x7f, 0x93, 0xf, 0x91, 0x5d, 0xac, 0xd4, 0xac, 0xc5, 0x85, 0x76, 0x4f, 0xed, 0xea, 0xcb, 0x14, 0x70, 0x32, 0x27, 0xae, 0xef, 0x34, 0x0, 0x0, 0x0, 0x0 }; Marshal.Copy(message, 0, hMessage, message.Length); fixed(byte *pKey = key) { byte *pMessage = (byte *)hMessage; Sha256ProtectedCryptoProvider sha256 = new Sha256ProtectedCryptoProvider(); (IntPtr h, int l) = sha256.ComputeHmacUnsafe(pKey, 4, pMessage, 32 + sizeof(int)); Marshal.FreeHGlobal(h); } Marshal.FreeHGlobal(hMessage); }