public ManagedDiffieHellman(ReadOnlyMemory <byte> prime, ReadOnlyMemory <byte> generator, ReadOnlyMemory <byte> factor) { this.keyLength = prime.Length; this.prime = ParseBigInteger(prime); this.generator = ParseBigInteger(generator); this.factor = ParseBigInteger(factor); this.x = GeneratePrime(); y = BigInteger.ModPow(this.generator, this.x, this.prime); PublicKey = new DiffieHellmanKey { Type = AsymmetricKeyType.Public, Generator = Depad(this.generator.ToByteArray(), true), Modulus = Depad(this.prime.ToByteArray(), true), Public = Depad(y.ToByteArray(), true), Factor = Depad(this.factor.ToByteArray(), true), KeyLength = prime.Length }; PrivateKey = new DiffieHellmanKey { Type = AsymmetricKeyType.Private, Generator = Depad(this.generator.ToByteArray(), true), Modulus = Depad(this.prime.ToByteArray(), true), Public = Depad(y.ToByteArray(), true), Factor = Depad(this.factor.ToByteArray(), true), Private = Depad(x.ToByteArray(), true), KeyLength = prime.Length }; }
protected BCryptDiffieHellman(DiffieHellmanKey importKey = null) { this.hAlgorithm = GetCachedBCryptAlgorithmProvider(BCRYPT_DH_ALGORITHM); if (importKey != null) { this.ImportKey(importKey, ref this.hPrivateKey); } else { this.GenerateKey(this.Modulus, this.Generator, ref this.hPrivateKey); } this.PublicKey = this.ExportKey(BCRYPT_DH_PUBLIC_BLOB, importKey?.CacheExpiry); this.PrivateKey = this.ExportKey(BCRYPT_DH_PRIVATE_BLOB, importKey?.CacheExpiry); }
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); }
protected BCryptDiffieHellman(DiffieHellmanKey importKey = null) { var status = BCryptOpenAlgorithmProvider(ref hAlgorithm, BCRYPT_DH_ALGORITHM, null, 0); ThrowIfNotNtSuccess(status); if (importKey != null) { ImportKey(importKey, ref hPrivateKey); } else { GenerateKey(Modulus, Generator, ref hPrivateKey); } PublicKey = ExportKey(BCRYPT_DH_PUBLIC_BLOB, importKey?.CacheExpiry); PrivateKey = ExportKey(BCRYPT_DH_PRIVATE_BLOB, importKey?.CacheExpiry); }
internal static byte[] CryptEncodeObject(DiffieHellmanKey publicKey) { fixed(byte *pM = &MemoryMarshal.GetReference(Reverse(publicKey.Modulus.Span))) fixed(byte *pG = &MemoryMarshal.GetReference(Reverse(publicKey.Generator.Span))) fixed(byte *pQ = &MemoryMarshal.GetReference(Reverse(publicKey.Factor.Span))) { return(CryptEncodeObject(new CERT_X942_DH_PARAMETERS { P = new CRYPT_UINT_BLOB { CbData = publicKey.Modulus.Length, PbData = pM }, G = new CRYPT_UINT_BLOB { CbData = publicKey.Generator.Length, PbData = pG }, Q = new CRYPT_UINT_BLOB { CbData = publicKey.Factor.Length, PbData = pQ }, })); } }
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); } } }