コード例 #1
0
        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);
        }
コード例 #2
0
        public ProtectedMemory ComputeHashProtected(ProtectedMemory protectedMemory, int n, int r, int p, int desiredKeyLength, byte[] salt)
        {
            IntPtr          hash            = Digest(protectedMemory, salt, n, r, p, desiredKeyLength);
            ProtectedMemory protectedResult = ProtectedMemory.Allocate(desiredKeyLength);

            using (ProtectedMemoryAccess access = new ProtectedMemoryAccess(protectedResult))
            {
                MarshalExtensions.Copy(hash, 0, access.Handle, 0, desiredKeyLength);
            }
            MarshalExtensions.ZeroFree(hash, desiredKeyLength);
            return(protectedResult);
        }
コード例 #3
0
        public unsafe (IntPtr, int) ComputeHmacUnsafe(byte *key, int keyLength, byte *message, int messageLength, bool freeKey = false)
        {
            if (keyLength > blockSize)
            {
                (IntPtr reducedKey, _) = ComputeHashUnsafe(key, keyLength);
                return(ComputeHmacUnsafe((byte *)reducedKey, digestLength, message, messageLength, freeKey = true));
            }
            IntPtr hPaddedKey = Marshal.AllocHGlobal(blockSize);

            MarshalExtensions.ZeroMemory(hPaddedKey, blockSize);
            Unsafe.CopyBlock((byte *)hPaddedKey, key, (uint)keyLength);
            if (freeKey)
            {
                MarshalExtensions.ZeroFree((IntPtr)key, keyLength);
            }
            IntPtr hOuterKeyPadded = Marshal.AllocHGlobal(blockSize);
            IntPtr hInnerKeyPadded = Marshal.AllocHGlobal(blockSize);
            byte * outerKeyPadded  = (byte *)hOuterKeyPadded;
            byte * innerKeyPadded  = (byte *)hInnerKeyPadded;

            Unsafe.CopyBlock(outerKeyPadded, (void *)hPaddedKey, blockSize);
            Unsafe.CopyBlock(innerKeyPadded, (void *)hPaddedKey, blockSize);
            MarshalExtensions.ZeroFree(hPaddedKey, blockSize);
            for (int i = 0; i < blockSize; i++)
            {
                outerKeyPadded[i] ^= 0x5c;
            }
            for (int i = 0; i < blockSize; i++)
            {
                innerKeyPadded[i] ^= 0x36;
            }
            int    innerInputLength = blockSize + messageLength;
            IntPtr hInnerInput      = Marshal.AllocHGlobal(innerInputLength);
            byte * innerInput       = (byte *)hInnerInput;

            Unsafe.CopyBlock(innerInput, innerKeyPadded, blockSize);
            MarshalExtensions.ZeroFree(hInnerKeyPadded, blockSize);
            Unsafe.CopyBlock(innerInput + blockSize, message, (uint)messageLength);
            (IntPtr hInnerHash, _) = ComputeHashUnsafe(innerInput, innerInputLength);
            MarshalExtensions.ZeroFree(hInnerInput, innerInputLength);
            const int inputLength = blockSize + digestLength;
            IntPtr    hInput      = Marshal.AllocHGlobal(inputLength);
            byte *    input       = (byte *)hInput;

            Unsafe.CopyBlock(input, outerKeyPadded, blockSize);
            Unsafe.CopyBlock(input + blockSize, (void *)hInnerHash, digestLength);
            (IntPtr hResult, int resultLength) = ComputeHashUnsafe(input, inputLength);
            MarshalExtensions.ZeroFree(hOuterKeyPadded, blockSize);
            MarshalExtensions.ZeroFree(hInnerHash, digestLength);
            MarshalExtensions.ZeroFree(hInput, inputLength);
            return(hResult, resultLength);
        }
コード例 #4
0
        public string ComputeHash(ProtectedMemory protectedMemory, byte[] salt, int n, int r, int p, int desiredKeyLength)
        {
            byte[] resultBytes = new byte[desiredKeyLength];
            IntPtr hash        = Digest(protectedMemory, salt, n, r, p, desiredKeyLength);

            Marshal.Copy(hash, resultBytes, 0, desiredKeyLength);
            MarshalExtensions.ZeroFree(hash, desiredKeyLength);
            StringBuilder stringBuilder = new StringBuilder(desiredKeyLength + salt.Length + 20);

            stringBuilder.Append("$s2$");
            stringBuilder.Append(n.ToString()).Append('$');
            stringBuilder.Append(r.ToString()).Append('$');
            stringBuilder.Append(p.ToString()).Append('$');
            stringBuilder.Append(Convert.ToBase64String(salt)).Append('$');
            stringBuilder.Append(Convert.ToBase64String(resultBytes));
            return(stringBuilder.ToString());
        }
コード例 #5
0
        internal unsafe IntPtr Digest(ProtectedMemory password, byte[] salt)
        {
            if (outLength == 0)
            {
                throw new InvalidOperationException("Hash not initialized.");
            }

            fixed(byte *pSalt = salt)
            {
                Pbkdf2HmacSha256(password, pSalt, salt.Length, 1, (int)blockSize * p, B[0]);
            }

            int    iBlockSize  = (int)blockSize;
            int    vLength     = n * iBlockSize;
            IntPtr hV          = Marshal.AllocHGlobal(vLength);
            IntPtr hBuffer     = Marshal.AllocHGlobal(iBlockSize);
            IntPtr hTempBuffer = Marshal.AllocHGlobal(64);
            byte * v           = (byte *)hV;
            byte * buffer      = (byte *)hBuffer;
            byte * tempBuffer  = (byte *)hTempBuffer;

            for (int i = 0; i < p; i++)
            {
                /* https://en.wikipedia.org/wiki/Scrypt
                 * Function ROMix(Block, Iterations)
                 *
                 *  Create Iterations copies of X
                 *  X ← Block
                 *  for i ← 0 to Iterations−1 do
                 *      Vi ← X
                 *      X ← BlockMix(X)
                 *
                 *  for i ← 0 to Iterations−1 do
                 *      j ← Integerify(X) mod Iterations
                 *      X ← BlockMix(X xor Vj)
                 *
                 *  return X
                 */
                byte *source = B[i] + (((2 * r) - 1) * 64);
                for (int k = 0; k < n; k++)
                {
                    Unsafe.CopyBlock(v + (k * blockSize), B[i], blockSize);
                    Unsafe.CopyBlock(tempBuffer, source, 64u);
                    BlockMix(B[i], v + (k * blockSize), tempBuffer);
                }
                long j;
                int  len;
                for (int k = 0; k < n; k++)
                {
                    uint *temp = (uint *)(B[i] + (((blockSize >> 6) - 1) * 64));
                    // C# uses little-endian integers by default!
                    j   = (((long)temp[1] << 32) + temp[0]) & (n - 1);
                    len = iBlockSize;
                    byte *d = B[i];
                    byte *s = v + (j * blockSize);

                    while (len >= 8)
                    {
                        *(ulong *)d ^= *(ulong *)s;
                        d           += 8;
                        s           += 8;
                        len         -= 8;
                    }
                    if (len >= 4)
                    {
                        *(uint *)d ^= *(uint *)s;
                        d          += 4;
                        s          += 4;
                        len        -= 4;
                    }
                    if (len >= 2)
                    {
                        *(ushort *)d ^= *(ushort *)s;
                        d            += 2;
                        s            += 2;
                        len          -= 2;
                    }
                    if (len >= 1)
                    {
                        *d ^= *s;
                    }
                    Unsafe.CopyBlock(buffer, B[i], blockSize);
                    Unsafe.CopyBlock(tempBuffer, source, 64u);
                    BlockMix(B[i], buffer, tempBuffer);
                }
            }
            Marshal.Copy(blockSizeZeros, 0, hBuffer, iBlockSize);
            Marshal.FreeHGlobal(hBuffer);
            Marshal.Copy(zeros64, 0, hTempBuffer, 64);
            Marshal.FreeHGlobal(hTempBuffer);
            MarshalExtensions.ZeroFree(hV, vLength);
            IntPtr hOutput = Marshal.AllocHGlobal(outLength);
            byte * output  = (byte *)hOutput;

            Pbkdf2HmacSha256(password, B[0], (int)blockSize * p, 1, outLength, output);
            return(hOutput);
        }
コード例 #6
0
 public override void Free()
 {
     MarshalExtensions.ZeroFree(directHandle, Size);
 }