public unsafe void DeriveSecret(IHashProvider hashProvider, HashType hashType, void *salt, int saltSize, void *output, int outputSize) { SafeBCryptSecretHandle returnPtr; ExceptionHelper.CheckReturnCode(BCryptSecretAgreement(_key, _peerKey, out returnPtr, 0)); var buffDescription = new BCryptBufferDesc(); var bufferArray = stackalloc BCryptBuffer[2]; var algId = System.Text.Encoding.Unicode.GetBytes(hashType.ToString().ToUpper() + "\0"); buffDescription.pBuffers = (IntPtr)bufferArray; buffDescription.cBuffers = 2; fixed(byte *algPtr = algId) { bufferArray[0] = new BCryptBuffer() { BufferType = NCryptBufferDescriptors.KDF_HASH_ALGORITHM, cbBuffer = algId.Length, pvBuffer = algPtr }; bufferArray[1] = new BCryptBuffer() { BufferType = NCryptBufferDescriptors.KDF_HMAC_KEY, cbBuffer = saltSize, pvBuffer = salt }; int sizeOfResult; ExceptionHelper.CheckReturnCode(BCryptDeriveKey(returnPtr, BCRYPT_KDF_HMAC, &buffDescription, (IntPtr)output, outputSize, out sizeOfResult, 0)); returnPtr.Dispose(); Dispose(); } }
public static extern NTStatus BCryptDeriveKey( SafeSecretHandle sharedSecret, string keyDerivationFunction, [In] ref BCryptBufferDesc kdfParameters, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] derivedKey, int derivedKeySize, [Out] out int resultSize, BCryptDeriveKeyFlags flags);
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"); } }
public unsafe void DeriveMasterSecretTls12(IHashProvider hashProvider, HashType hashType, void *seed, int seedLength, void *output, int outputLength) { uint version = 0x0303; var buffDescription = new BCryptBufferDesc(); var bufferArray = stackalloc BCryptBuffer[4]; var algId = Encoding.Unicode.GetBytes(hashType.ToString() + "\0"); fixed(void *algPtr = algId) { bufferArray[0] = new BCryptBuffer() { BufferType = NCryptBufferDescriptors.KDF_HASH_ALGORITHM, cbBuffer = algId.Length, pvBuffer = algPtr }; bufferArray[1] = new BCryptBuffer() { BufferType = NCryptBufferDescriptors.KDF_TLS_PRF_LABEL, cbBuffer = Tls13.Internal.Tls1_2Consts.MasterSecretLabelSize, pvBuffer = (void *)Tls13.Internal.Tls1_2Consts.MasterSecretLabelPointer }; bufferArray[2] = new BCryptBuffer() { BufferType = NCryptBufferDescriptors.KDF_TLS_PRF_SEED, cbBuffer = seedLength, pvBuffer = seed }; bufferArray[3] = new BCryptBuffer() { BufferType = NCryptBufferDescriptors.KDF_TLS_PRF_PROTOCOL, cbBuffer = 4, pvBuffer = &version }; buffDescription.cBuffers = 4; buffDescription.pBuffers = (IntPtr)bufferArray; int sizeOfResult; SafeBCryptSecretHandle secretPointer; ExceptionHelper.CheckReturnCode(BCryptSecretAgreement(_key, _peerKey, out secretPointer, 0)); ExceptionHelper.CheckReturnCode( BCryptDeriveKey(secretPointer, BCRYPT_KDF_TLS_PRF, &buffDescription, (IntPtr)output, outputLength, out sizeOfResult, 0)); secretPointer.Dispose(); Dispose(); } }
/// <inheritdoc /> public byte[] DeriveKeyMaterial(IECDiffieHellmanPublicKey otherParty) { Requires.NotNull(otherParty, nameof(otherParty)); var publicKey = (ECDiffieHellmanPublicKey)otherParty; using (var secret = BCryptSecretAgreement(this.PlatformKey, publicKey.Key)) { IntPtr hashAlgorithmPtr = IntPtr.Zero; try { string hashAlgorithmString = HashAlgorithmProviderFactory.GetHashAlgorithmName(this.HashAlgorithm); try { } finally { // Do this in a finally so that ThreadAbortException doesn't interrupt the // assignment of a successfully allocated pointer. hashAlgorithmPtr = Marshal.StringToHGlobalUni(hashAlgorithmString); } var parameters = new List<BCryptBuffer>(); parameters.Add(new BCryptBuffer { cbBuffer = (hashAlgorithmString.Length + 1) * sizeof(char), BufferType = BufferType.KDF_HASH_ALGORITHM, pvBuffer_IntPtr = hashAlgorithmPtr, }); const string kdf = KeyDerivationFunctions.HASH; unsafe { fixed (BCryptBuffer* pParameters = parameters.ToArray()) { var parameterDesc = new BCryptBufferDesc { ulVersion = 0, cBuffers = parameters.Count, pBuffers = pParameters, }; int secretLength; BCryptDeriveKey( secret, kdf, ref parameterDesc, null, 0, out secretLength, BCryptDeriveKeyFlags.KDF_USE_SECRET_AS_HMAC_KEY_FLAG).ThrowOnError(); byte[] derivedKey = new byte[secretLength]; BCryptDeriveKey( secret, kdf, ref parameterDesc, derivedKey, derivedKey.Length, out secretLength, 0).ThrowOnError(); Assumes.True(secretLength == derivedKey.Length); return derivedKey; } } } finally { if (hashAlgorithmPtr != IntPtr.Zero) { Marshal.FreeHGlobal(hashAlgorithmPtr); } } } }
/// <inheritdoc /> public byte[] DeriveKeyMaterial(IECDiffieHellmanPublicKey otherParty) { Requires.NotNull(otherParty, nameof(otherParty)); var publicKey = (ECDiffieHellmanPublicKey)otherParty; using (var secret = BCryptSecretAgreement(this.PlatformKey, publicKey.Key)) { IntPtr hashAlgorithmPtr = IntPtr.Zero; try { string hashAlgorithmString = HashAlgorithmProviderFactory.GetHashAlgorithmName(this.HashAlgorithm); try { } finally { // Do this in a finally so that ThreadAbortException doesn't interrupt the // assignment of a successfully allocated pointer. hashAlgorithmPtr = Marshal.StringToHGlobalUni(hashAlgorithmString); } var parameters = new List <BCryptBuffer>(); parameters.Add(new BCryptBuffer { cbBuffer = (hashAlgorithmString.Length + 1) * sizeof(char), BufferType = BufferType.KDF_HASH_ALGORITHM, pvBuffer_IntPtr = hashAlgorithmPtr, }); const string kdf = KeyDerivationFunctions.BCRYPT_KDF_HASH; unsafe { fixed(BCryptBuffer *pParameters = parameters.ToArray()) { var parameterDesc = new BCryptBufferDesc { ulVersion = 0, cBuffers = parameters.Count, pBuffers = pParameters, }; int secretLength; BCryptDeriveKey( secret, kdf, ref parameterDesc, null, 0, out secretLength, BCryptDeriveKeyFlags.KDF_USE_SECRET_AS_HMAC_KEY_FLAG).ThrowOnError(); byte[] derivedKey = new byte[secretLength]; BCryptDeriveKey( secret, kdf, ref parameterDesc, derivedKey, derivedKey.Length, out secretLength, 0).ThrowOnError(); Assumes.True(secretLength == derivedKey.Length); return(derivedKey); } } } finally { if (hashAlgorithmPtr != IntPtr.Zero) { Marshal.FreeHGlobal(hashAlgorithmPtr); } } } }
public static void Initialize(ref BCryptBufferDesc bufferDesc) { bufferDesc.ulVersion = BCRYPTBUFFER_VERSION; }
public unsafe static void Main(string[] args) { var thumb = "48026c976caaf7f3a72d38c17d16ce69d04a6053".ToUpper(); var cert = LoadCertificateFromStore(thumb, false, StoreLocation.CurrentUser, StoreName.My); var privKey = cert.GetECDsaPrivateKey(); var curve = privKey.ExportParameters(true); List <byte> currentSection = null; var lines = ecdsaKeyPEM.Split('\n'); for (int i = 0; i < lines.Length; i++) { if (lines[i].StartsWith("-----BEGIN")) { //Starting a block string blockName = lines[i].Substring("-----BEGIN ".Length, lines[i].LastIndexOf("-----") - "-----BEGIN ".Length); currentSection = new List <byte>(); _sections.Add(blockName, currentSection); continue; } else if (lines[i].StartsWith("-----END")) { //ending block currentSection = null; } currentSection?.AddRange(Convert.FromBase64String(lines[i].Trim())); } IntPtr prov, key; var res = NCryptOpenStorageProvider(out prov, "Microsoft Software Key Storage Provider", 0); //ECDSA_P521 var size = sizeof(BCRYPT_ECCKEY_BLOB); var blobHeader = new BCRYPT_ECCKEY_BLOB() { Magic = KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_GENERIC_MAGIC, cbKey = _sections["EC PRIVATE KEY"].Count }; var desc = new BCryptBufferDesc() { cBuffers = 1 }; var buff = new BCryptBuffer() { BufferType = NCryptBufferDescriptors.NCRYPTBUFFER_ECC_CURVE_NAME, cbBuffer = "ECDSA_P521\0".Length * 2, pvBuffer = Marshal.StringToHGlobalUni("ECDSA_P521\0") }; var buffPtr = Marshal.AllocHGlobal(sizeof(BCryptBuffer)); Marshal.StructureToPtr(buff, buffPtr, true); desc.pBuffers = buffPtr; var descPtr = Marshal.AllocHGlobal(sizeof(BCryptBufferDesc)); Marshal.StructureToPtr(desc, descPtr, true); var bytes = new byte[size + blobHeader.cbKey]; _sections["EC PRIVATE KEY"].ToArray().CopyTo(bytes, size); fixed(void *blobPtr = bytes) { Unsafe.Copy(blobPtr, ref blobHeader); res = NCryptImportKey(prov, IntPtr.Zero, "ECCPRIVATEBLOB", descPtr, out key, (IntPtr)blobPtr, (uint)bytes.Length, 0); } }