private unsafe DiffieHellmanKey ExportKey(string keyType, DateTimeOffset?expiry) { int status = 0; status = BCryptExportKey(hPrivateKey, IntPtr.Zero, keyType, null, 0, out int pcbResult, 0); ThrowIfNotNtSuccess(status); DiffieHellmanKey key; using (var rental = CryptoPool.Rent <byte>(pcbResult)) { var output = rental.Memory; fixed(byte *pbOutput = &MemoryMarshal.GetReference(output.Span)) { status = BCryptExportKey(hPrivateKey, IntPtr.Zero, keyType, pbOutput, pcbResult, out pcbResult, 0); ThrowIfNotNtSuccess(status); BCRYPT_DH_KEY_BLOB *param = (BCRYPT_DH_KEY_BLOB *)pbOutput; key = new DiffieHellmanKey() { KeyLength = param->header.cbKey, Algorithm = param->header.cbKey < 256 ? KeyAgreementAlgorithm.DiffieHellmanModp2 : KeyAgreementAlgorithm.DiffieHellmanModp14, Type = param->header.dwMagic == BCRYPT_DH_PRIVATE_MAGIC ? AsymmetricKeyType.Private : AsymmetricKeyType.Public, CacheExpiry = expiry }; } var export = output.Span.Slice(sizeof(BCRYPT_DH_KEY_BLOB_HEADER)); key.Modulus = Copy(export.Slice(0, key.KeyLength)); key.Generator = Copy(export.Slice(key.KeyLength, key.KeyLength)); key.Public = Copy(export.Slice(key.KeyLength + key.KeyLength, key.KeyLength)); if (key.Type == AsymmetricKeyType.Private) { key.Private = Copy(export.Slice(key.KeyLength + key.KeyLength + key.KeyLength, key.KeyLength)); } key.Factor = Copy(Factor); } return(key); }
private unsafe void ImportKey(DiffieHellmanKey incoming, ref IntPtr hKey) { DiffieHellmanKey key; string keyType; int dwMagic; int structSize; if (incoming.Type == AsymmetricKeyType.Private) { key = incoming; keyType = BCRYPT_DH_PRIVATE_BLOB; dwMagic = BCRYPT_DH_PRIVATE_MAGIC; structSize = sizeof(BCRYPT_DH_KEY_BLOB_HEADER) + (key.KeyLength * 4); } else { key = (DiffieHellmanKey)PublicKey; keyType = BCRYPT_DH_PUBLIC_BLOB; dwMagic = BCRYPT_DH_PUBLIC_MAGIC; structSize = sizeof(BCRYPT_DH_KEY_BLOB_HEADER) + (key.KeyLength * 3); } Factor = incoming.Factor.ToArray(); using (var rented = CryptoPool.Rent <byte>(structSize)) { rented.Memory.Span.Fill(0); fixed(byte *pbInput = &MemoryMarshal.GetReference(rented.Memory.Span)) { BCRYPT_DH_KEY_BLOB *param = (BCRYPT_DH_KEY_BLOB *)pbInput; param->header.dwMagic = dwMagic; param->header.cbKey = key.KeyLength; key.Modulus.CopyTo( rented.Memory.Slice(sizeof(BCRYPT_DH_KEY_BLOB_HEADER)) ); key.Generator.CopyTo( rented.Memory.Slice(sizeof(BCRYPT_DH_KEY_BLOB_HEADER) + key.Modulus.Length) ); incoming.Public.CopyTo( rented.Memory.Slice(sizeof(BCRYPT_DH_KEY_BLOB_HEADER) + key.Modulus.Length + key.Generator.Length) ); if (incoming.Type == AsymmetricKeyType.Private && incoming.Private.Length > 0) { incoming.Private.CopyTo( rented.Memory.Slice(sizeof(BCRYPT_DH_KEY_BLOB_HEADER) + key.Modulus.Length + key.Generator.Length + key.Public.Length) ); } var status = BCryptImportKeyPair( hAlgorithm, IntPtr.Zero, keyType, ref hKey, pbInput, structSize, 0 ); ThrowIfNotNtSuccess(status); } } }