Пример #1
0
        public static DsaKey CreatePrivate(
            ReadOnlySpan <byte> password,
            ReadOnlySpan <byte> source,
            out int publicKeySize)
        {
            var dsaParameters = ReadOpenPgpPublicKey(source, out publicKeySize);

            byte[] xArray = new byte[source.Length - publicKeySize];

            try
            {
                S2kBasedEncryption.DecryptSecretKey(password, source.Slice(publicKeySize), xArray, out int bytesWritten);

                dsaParameters.X = MPInteger.ReadInteger(xArray, out int xConsumed).ToArray();

                // Make sure Q, X have the same length (DSA implementation on Windows requires it)
                int qxLength = Math.Max(dsaParameters.X.Length, dsaParameters.Q !.Length);
                ResizeArrayIfNeeded(ref dsaParameters.Q, qxLength);
                ResizeArrayIfNeeded(ref dsaParameters.X, qxLength);
                return(new DsaKey(DSA.Create(dsaParameters)));
            }
            finally
            {
                CryptographicOperations.ZeroMemory(xArray);
                CryptographicOperations.ZeroMemory(dsaParameters.X);
            }
        }
Пример #2
0
        public static ECDiffieHellmanKey CreatePrivate(
            ReadOnlySpan <byte> fingerprint,
            ReadOnlySpan <byte> password,
            ReadOnlySpan <byte> source,
            out int publicKeySize)
        {
            var ecParameters = ReadOpenPgpECParameters(source, out publicKeySize);
            // TODO: Validation
            byte kdfSize       = source[publicKeySize];
            var  kdfParameters = source.Slice(publicKeySize + 1, kdfSize).ToArray();

            byte[] paramsArray = new byte[source.Length - publicKeySize];
            try
            {
                S2kBasedEncryption.DecryptSecretKey(password, source.Slice(publicKeySize + kdfSize + 1), paramsArray, out int bytesWritten);
                Debug.Assert(bytesWritten != 0);
                ecParameters.D = MPInteger.ReadInteger(paramsArray, out int dConsumed).ToArray();
                return(new ECDiffieHellmanKey(CreateECDiffieHellman(ecParameters), kdfParameters, fingerprint.ToArray()));
            }
            finally
            {
                CryptographicOperations.ZeroMemory(paramsArray);
                CryptographicOperations.ZeroMemory(ecParameters.D);
            }
        }
Пример #3
0
        public new static EdDsaKey CreatePrivate(
            ReadOnlySpan <byte> password,
            ReadOnlySpan <byte> source,
            out int publicKeySize)
        {
            var ecParameters = ReadOpenPgpECParameters(source, out publicKeySize);

            byte[] paramsArray = new byte[source.Length - publicKeySize];

            try
            {
                S2kBasedEncryption.DecryptSecretKey(password, source.Slice(publicKeySize), paramsArray, out int bytesWritten);
                Debug.Assert(bytesWritten != 0);
                ecParameters.D = MPInteger.ReadInteger(paramsArray, out int dConsumed).ToArray();
                return(new EdDsaKey(CreateEdDsa(ecParameters)));
            }
            finally
            {
                CryptographicOperations.ZeroMemory(paramsArray);
                CryptographicOperations.ZeroMemory(ecParameters.D);
            }
        }
Пример #4
0
        public static ElGamalKey CreatePrivate(
            ReadOnlySpan <byte> password,
            ReadOnlySpan <byte> source,
            out int bytesRead)
        {
            var elgamalParameters = ReadOpenPgpPublicKey(source, out bytesRead);

            byte[] xArray = new byte[source.Length - bytesRead];

            try
            {
                S2kBasedEncryption.DecryptSecretKey(password, source.Slice(bytesRead), xArray, out int bytesWritten);
                elgamalParameters.X = MPInteger.ReadInteger(xArray, out int xConsumed).ToArray();
                bytesRead           = source.Length;
                return(new ElGamalKey(ElGamal.Create(elgamalParameters)));
            }
            finally
            {
                CryptographicOperations.ZeroMemory(xArray);
                CryptographicOperations.ZeroMemory(elgamalParameters.X);
            }
        }
Пример #5
0
        public static RsaKey CreatePrivate(
            ReadOnlySpan <byte> password,
            ReadOnlySpan <byte> source,
            out int publicKeyBytes,
            int version = 4)
        {
            var rsaParameters = ReadOpenPgpPublicKey(source, out publicKeyBytes);

            byte[] paramsArray = new byte[source.Length - publicKeyBytes];

            try
            {
                S2kBasedEncryption.DecryptSecretKey(password, source.Slice(publicKeyBytes), paramsArray, out int bytesWritten, version);
                Debug.Assert(bytesWritten != 0);

                int halfModulusLength = (rsaParameters.Modulus !.Length + 1) / 2;
                rsaParameters.D        = new byte[rsaParameters.Modulus.Length];
                rsaParameters.P        = new byte[halfModulusLength];
                rsaParameters.Q        = new byte[halfModulusLength];
                rsaParameters.DP       = new byte[halfModulusLength];
                rsaParameters.DQ       = new byte[halfModulusLength];
                rsaParameters.InverseQ = new byte[halfModulusLength];

                var privateSource = new ReadOnlySpan <byte>(paramsArray);
                var d             = MPInteger.ReadInteger(privateSource, out int dConsumed);
                privateSource = privateSource.Slice(dConsumed);
                var p = MPInteger.ReadInteger(privateSource, out int pConsumed);
                privateSource = privateSource.Slice(pConsumed);
                var q = MPInteger.ReadInteger(privateSource, out int qConsumed);
                //source = source.Slice(qConsumed);
                // Technically InverseQ follows but it's often incorrect

                // FIXME: These BigIntegers cannot be cleared from memory
                var D  = new BigInteger(d, isBigEndian: true, isUnsigned: true);
                var P  = new BigInteger(p, isBigEndian: true, isUnsigned: true);
                var Q  = new BigInteger(q, isBigEndian: true, isUnsigned: true);
                var DP = BigInteger.Remainder(D, P - BigInteger.One);
                var DQ = BigInteger.Remainder(D, Q - BigInteger.One);
                // Lot of the public keys in the test suite have this wrong (switched P/Q)
                var InverseQ = BigInteger.ModPow(Q, P - BigInteger.One - BigInteger.One, P);

                d.CopyTo(rsaParameters.D.AsSpan(rsaParameters.D.Length - d.Length));
                p.CopyTo(rsaParameters.P.AsSpan(rsaParameters.P.Length - p.Length));
                q.CopyTo(rsaParameters.Q.AsSpan(rsaParameters.Q.Length - q.Length));

                DP.TryWriteBytes(rsaParameters.DP.AsSpan(rsaParameters.DP.Length - DP.GetByteCount(isUnsigned: true)), out var _, isBigEndian: true, isUnsigned: true);
                DQ.TryWriteBytes(rsaParameters.DQ.AsSpan(rsaParameters.DQ.Length - DQ.GetByteCount(isUnsigned: true)), out var _, isBigEndian: true, isUnsigned: true);
                InverseQ.TryWriteBytes(rsaParameters.InverseQ.AsSpan(rsaParameters.InverseQ.Length - InverseQ.GetByteCount(isUnsigned: true)), out var _, isBigEndian: true, isUnsigned: true);

                return(new RsaKey(RSA.Create(rsaParameters)));
            }
            finally
            {
                CryptographicOperations.ZeroMemory(paramsArray);
                CryptographicOperations.ZeroMemory(rsaParameters.D);
                CryptographicOperations.ZeroMemory(rsaParameters.P);
                CryptographicOperations.ZeroMemory(rsaParameters.Q);
                CryptographicOperations.ZeroMemory(rsaParameters.DP);
                CryptographicOperations.ZeroMemory(rsaParameters.DQ);
                CryptographicOperations.ZeroMemory(rsaParameters.InverseQ);
            }
        }