예제 #1
0
파일: DsaKey.cs 프로젝트: 1hub/springburg
        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
파일: DsaKey.cs 프로젝트: 1hub/springburg
        public byte[] ExportPrivateKey(
            ReadOnlySpan <byte> passwordBytes,
            S2kParameters s2kParameters)
        {
            DSAParameters dsaParameters = new DSAParameters();

            byte[] secretPart = Array.Empty <byte>();

            try
            {
                dsaParameters = dsa.ExportParameters(true);
                secretPart    = CryptoPool.Rent(MPInteger.GetMPEncodedLength(dsaParameters.X !));
                MPInteger.TryWriteInteger(dsaParameters.X, secretPart, out var secretSize);
                int publicKeySize       = MPInteger.GetMPEncodedLength(dsaParameters.P !, dsaParameters.Q !, dsaParameters.G !, dsaParameters.Y !);
                int encryptedSecretSize = S2kBasedEncryption.GetEncryptedLength(s2kParameters, secretSize);
                int expectedLength      = publicKeySize + encryptedSecretSize;
                var destination         = new byte[expectedLength];
                WriteOpenPgpPublicKey(dsaParameters, destination);
                S2kBasedEncryption.EncryptSecretKey(passwordBytes, s2kParameters, secretPart.AsSpan(0, secretSize), destination.AsSpan(publicKeySize));
                return(destination);
            }
            finally
            {
                CryptoPool.Return(secretPart);
                CryptographicOperations.ZeroMemory(dsaParameters.X);
            }
        }
예제 #3
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);
            }
        }
예제 #4
0
        public byte[] ExportPrivateKey(
            ReadOnlySpan <byte> passwordBytes,
            S2kParameters s2kParameters)
        {
            RSAParameters rsaParameters = new RSAParameters();

            byte[] secretPart = Array.Empty <byte>();

            try
            {
                rsaParameters = rsa.ExportParameters(true);

                secretPart = CryptoPool.Rent(MPInteger.GetMPEncodedLength(rsaParameters.D !, rsaParameters.P !, rsaParameters.Q !, rsaParameters.InverseQ !));
                MPInteger.TryWriteInteger(rsaParameters.D, secretPart, out var dBytesWritten);
                MPInteger.TryWriteInteger(rsaParameters.P, secretPart.AsSpan(dBytesWritten), out var pBytesWritten);
                MPInteger.TryWriteInteger(rsaParameters.Q, secretPart.AsSpan(dBytesWritten + pBytesWritten), out var qBytesWritten);
                MPInteger.TryWriteInteger(rsaParameters.InverseQ, secretPart.AsSpan(dBytesWritten + pBytesWritten + qBytesWritten), out var iqBytesWritten);
                int secretSize = dBytesWritten + pBytesWritten + qBytesWritten + iqBytesWritten;

                int encryptedSecretSize = S2kBasedEncryption.GetEncryptedLength(s2kParameters, secretSize);
                int expectedLength      =
                    MPInteger.GetMPEncodedLength(rsaParameters.Modulus !, rsaParameters.Exponent !) +
                    encryptedSecretSize;
                var destination = new byte[expectedLength];

                MPInteger.TryWriteInteger(rsaParameters.Modulus, destination, out int modulusWritten);
                MPInteger.TryWriteInteger(rsaParameters.Exponent, destination.AsSpan(modulusWritten), out int exponentWritten);

                S2kBasedEncryption.EncryptSecretKey(passwordBytes, s2kParameters, secretPart.AsSpan(0, secretSize), destination.AsSpan(modulusWritten + exponentWritten));

                return(destination.AsSpan(0, modulusWritten + exponentWritten + encryptedSecretSize).ToArray());
            }
            finally
            {
                CryptoPool.Return(secretPart);
                CryptographicOperations.ZeroMemory(rsaParameters.D);
                CryptographicOperations.ZeroMemory(rsaParameters.P);
                CryptographicOperations.ZeroMemory(rsaParameters.Q);
                CryptographicOperations.ZeroMemory(rsaParameters.InverseQ);
                CryptographicOperations.ZeroMemory(rsaParameters.DP);
                CryptographicOperations.ZeroMemory(rsaParameters.DQ);
            }
        }
예제 #5
0
        public byte[] ExportPrivateKey(
            ReadOnlySpan <byte> passwordBytes,
            S2kParameters s2kParameters)
        {
            ECParameters ecParameters = new ECParameters();

            byte[] secretPart = Array.Empty <byte>();

            try
            {
                ecParameters = ecdh.ExportParameters(true);
                if (ecdh is X25519)
                {
                    Array.Reverse(ecParameters.D !);
                }

                int secretSize = MPInteger.GetMPEncodedLength(ecParameters.D !);
                secretPart = CryptoPool.Rent(secretSize);
                MPInteger.TryWriteInteger(ecParameters.D, secretPart, out var _);

                int encryptedSecretLength = S2kBasedEncryption.GetEncryptedLength(s2kParameters, secretSize);
                int estimatedLength       =
                    32 /* OID */ +
                    MPInteger.GetMPEncodedLength(ecParameters.Q.X !, ecParameters.Q.Y !) + 1 /* EC Point type */ +
                    4 /* KDF Parameters */ +
                    encryptedSecretLength;
                var destination = new byte[estimatedLength];
                WriteOpenPgpECParameters(ecParameters, destination, out int bytesWritten);
                WriteKDFParameters(destination.AsSpan(bytesWritten));

                S2kBasedEncryption.EncryptSecretKey(passwordBytes, s2kParameters, secretPart.AsSpan(0, secretSize), destination.AsSpan(bytesWritten + 4));
                return(destination.AsSpan(0, bytesWritten + 4 + encryptedSecretLength).ToArray());
            }
            finally
            {
                CryptoPool.Return(secretPart);
                if (ecParameters.D != null)
                {
                    CryptographicOperations.ZeroMemory(ecParameters.D);
                }
            }
        }
예제 #6
0
파일: EdDsaKey.cs 프로젝트: 1hub/springburg
        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);
            }
        }
예제 #7
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);
            }
        }
예제 #8
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);
            }
        }