Exemplo n.º 1
0
        public void DeriveKey(byte *pbLabel, uint cbLabel, byte *pbContext, uint cbContext, byte *pbDerivedKey, uint cbDerivedKey)
        {
            const int SHA512_ALG_CHAR_COUNT = 7;
            char *    pszHashAlgorithm      = stackalloc char[SHA512_ALG_CHAR_COUNT /* includes terminating null */];

            pszHashAlgorithm[0] = 'S';
            pszHashAlgorithm[1] = 'H';
            pszHashAlgorithm[2] = 'A';
            pszHashAlgorithm[3] = '5';
            pszHashAlgorithm[4] = '1';
            pszHashAlgorithm[5] = '2';
            pszHashAlgorithm[6] = (char)0;

            // First, build the buffers necessary to pass (label, context, PRF algorithm) into the KDF
            BCryptBuffer *pBuffers = stackalloc BCryptBuffer[3];

            pBuffers[0].BufferType = BCryptKeyDerivationBufferType.KDF_LABEL;
            pBuffers[0].pvBuffer   = (IntPtr)pbLabel;
            pBuffers[0].cbBuffer   = cbLabel;

            pBuffers[1].BufferType = BCryptKeyDerivationBufferType.KDF_CONTEXT;
            pBuffers[1].pvBuffer   = (IntPtr)pbContext;
            pBuffers[1].cbBuffer   = cbContext;

            pBuffers[2].BufferType = BCryptKeyDerivationBufferType.KDF_HASH_ALGORITHM;
            pBuffers[2].pvBuffer   = (IntPtr)pszHashAlgorithm;
            pBuffers[2].cbBuffer   = checked (SHA512_ALG_CHAR_COUNT * sizeof(char));

            // Add the header which points to the buffers
            var bufferDesc = default(BCryptBufferDesc);

            BCryptBufferDesc.Initialize(ref bufferDesc);
            bufferDesc.cBuffers = 3;
            bufferDesc.pBuffers = pBuffers;

            // Finally, invoke the KDF
            uint numBytesDerived;
            var  ntstatus = UnsafeNativeMethods.BCryptKeyDerivation(
                hKey: _keyHandle,
                pParameterList: &bufferDesc,
                pbDerivedKey: pbDerivedKey,
                cbDerivedKey: cbDerivedKey,
                pcbResult: out numBytesDerived,
                dwFlags: 0);

            UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);

            // Final sanity checks before returning control to caller.
            CryptoUtil.Assert(numBytesDerived == cbDerivedKey, "numBytesDerived == cbDerivedKey");
        }
        private static void Pbkdf2Win8ImplStep2(BCryptKeyHandle pbkdf2KeyHandle, string hashAlgorithm, byte *pbSalt, uint cbSalt, ulong iterCount, byte *pbDerivedBytes, uint cbDerivedBytes)
        {
            // First, build the buffers necessary to pass (hash alg, salt, iter count) into the KDF
            BCryptBuffer *pBuffers = stackalloc BCryptBuffer[3];

            pBuffers[0].BufferType = BCryptKeyDerivationBufferType.KDF_ITERATION_COUNT;
            pBuffers[0].pvBuffer   = (IntPtr)(&iterCount);
            pBuffers[0].cbBuffer   = sizeof(ulong);

            pBuffers[1].BufferType = BCryptKeyDerivationBufferType.KDF_SALT;
            pBuffers[1].pvBuffer   = (IntPtr)pbSalt;
            pBuffers[1].cbBuffer   = cbSalt;

            fixed(char *pszHashAlgorithm = hashAlgorithm)
            {
                pBuffers[2].BufferType = BCryptKeyDerivationBufferType.KDF_HASH_ALGORITHM;
                pBuffers[2].pvBuffer   = (IntPtr)pszHashAlgorithm;
                pBuffers[2].cbBuffer   = hashAlgorithm.GetTotalByteLengthIncludingNullTerminator();

                // Add the header which points to the buffers
                BCryptBufferDesc bufferDesc = default(BCryptBufferDesc);

                BCryptBufferDesc.Initialize(ref bufferDesc);
                bufferDesc.cBuffers = 3;
                bufferDesc.pBuffers = pBuffers;

                // Finally, import the KDK into the KDF algorithm, then invoke the KDF
                uint numBytesDerived;
                int  ntstatus = UnsafeNativeMethods.BCryptKeyDerivation(
                    hKey: pbkdf2KeyHandle,
                    pParameterList: &bufferDesc,
                    pbDerivedKey: pbDerivedBytes,
                    cbDerivedKey: cbDerivedBytes,
                    pcbResult: out numBytesDerived,
                    dwFlags: 0);

                UnsafeNativeMethods.ThrowExceptionForBCryptStatus(ntstatus);

                // Final sanity checks before returning control to caller.
                CryptoUtil.Assert(numBytesDerived == cbDerivedBytes, "numBytesDerived == cbDerivedBytes");
            }
        }