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
            };
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
 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
             },
         }));
     }
 }
Exemplo n.º 6
0
        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);
                }
            }
        }