Ejemplo n.º 1
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);
            }
        }
Ejemplo n.º 2
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);
            }
        }
Ejemplo n.º 3
0
        public bool TryDecryptSessionInfo(ReadOnlySpan <byte> encryptedSessionData, Span <byte> sessionData, out int bytesWritten)
        {
            var pEnc = MPInteger.ReadInteger(encryptedSessionData, out int pointBytesRead);

            encryptedSessionData = encryptedSessionData.Slice(pointBytesRead);
            int keyLen = encryptedSessionData[0];
            var keyEnc = encryptedSessionData.Slice(1, keyLen);

            var publicParams = ecdh.PublicKey.ExportParameters();

            var publicPoint = DecodePoint(pEnc);
            var otherEcdh   = CreateECDiffieHellman(new ECParameters {
                Curve = publicParams.Curve, Q = publicPoint
            });
            var derivedKey = ecdh.DeriveKeyFromHash(
                otherEcdh.PublicKey,
                PgpUtilities.GetHashAlgorithmName(this.hashAlgorithm),
                new byte[] { 0, 0, 0, 1 },
                CreateUserKeyingMaterial(publicParams.Curve.Oid));

            derivedKey = derivedKey.AsSpan(0, PgpUtilities.GetKeySize(this.symmetricAlgorithm) / 8).ToArray();

            var C    = SymmetricKeyWrap.AESKeyWrapDecrypt(derivedKey, keyEnc.ToArray());
            var data = UnpadSessionData(C);

            if (sessionData.Length >= data.Length)
            {
                data.CopyTo(sessionData);
                bytesWritten = data.Length;
                return(true);
            }
            bytesWritten = 0;
            return(false);
        }
Ejemplo n.º 4
0
        public byte[] EncryptSessionInfo(ReadOnlySpan <byte> sessionInfo)
        {
            var publicKeyParams = ecdh.PublicKey.ExportParameters();

            // Generate the ephemeral key pair
            var ephemeralEcDh = CreateECDiffieHellman(publicKeyParams.Curve);
            var derivedKey    = ephemeralEcDh.DeriveKeyFromHash(
                ecdh.PublicKey,
                PgpUtilities.GetHashAlgorithmName(this.hashAlgorithm),
                new byte[] { 0, 0, 0, 1 },
                CreateUserKeyingMaterial(publicKeyParams.Curve.Oid));

            derivedKey = derivedKey.AsSpan(0, PgpUtilities.GetKeySize(symmetricAlgorithm) / 8).ToArray();

            byte[] paddedSessionData = PadSessionData(sessionInfo);
            byte[] C  = SymmetricKeyWrap.AESKeyWrapEncrypt(derivedKey, paddedSessionData);
            var    ep = ephemeralEcDh.PublicKey.ExportParameters();

            byte[] VB = EncodePoint(ep.Q, publicKeyParams.Curve.Oid);
            byte[] rv = new byte[VB.Length + 2 + 1 + C.Length];
            MPInteger.TryWriteInteger(VB, rv, out _);
            //Array.Copy(VB, 0, rv, 0, VB.Length);
            rv[VB.Length + 2] = (byte)C.Length;
            Array.Copy(C, 0, rv, VB.Length + 3, C.Length);

            return(rv);
        }
Ejemplo n.º 5
0
 private static void WriteOpenPgpPublicKey(DSAParameters dsaParameters, Span <byte> destination)
 {
     MPInteger.TryWriteInteger(dsaParameters.P, destination, out int pWritten);
     MPInteger.TryWriteInteger(dsaParameters.Q, destination.Slice(pWritten), out int qWritten);
     MPInteger.TryWriteInteger(dsaParameters.G, destination.Slice(pWritten + qWritten), out int gWritten);
     MPInteger.TryWriteInteger(dsaParameters.Y, destination.Slice(pWritten + qWritten + gWritten), out int yWritten);
 }
Ejemplo n.º 6
0
        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);
            }
        }
Ejemplo n.º 7
0
        public byte[] EncryptSessionInfo(ReadOnlySpan <byte> sessionInfo)
        {
            var encryptedSessionInfo = rsa.Encrypt(sessionInfo.ToArray(), RSAEncryptionPadding.Pkcs1);
            var mp = new byte[MPInteger.GetMPEncodedLength(encryptedSessionInfo)];

            MPInteger.TryWriteInteger(encryptedSessionInfo, mp, out var _);
            return(mp);
        }
Ejemplo n.º 8
0
 public byte[] CreateSignature(ReadOnlySpan <byte> rgbHash, PgpHashAlgorithm hashAlgorithm)
 {
     byte[] ieeeSignature = ecdsa.SignHash(rgbHash.ToArray(), DSASignatureFormat.IeeeP1363FixedFieldConcatenation);
     byte[] pgpSignature  = new byte[ieeeSignature.Length + 4]; // Maximum possible length
     MPInteger.TryWriteInteger(ieeeSignature.AsSpan(0, ieeeSignature.Length / 2), pgpSignature, out int rWritten);
     MPInteger.TryWriteInteger(ieeeSignature.AsSpan(ieeeSignature.Length / 2), pgpSignature.AsSpan(rWritten), out int sWritten);
     return(pgpSignature.AsSpan(0, rWritten + sWritten).ToArray());
 }
Ejemplo n.º 9
0
        public bool VerifySignature(
            ReadOnlySpan <byte> rgbHash,
            ReadOnlySpan <byte> rgbSignature,
            PgpHashAlgorithm hashAlgorithm)
        {
            var signature = MPInteger.ReadInteger(rgbSignature, out var _);

            return(rsa.VerifyHash(rgbHash, signature, PgpUtilities.GetHashAlgorithmName(hashAlgorithm), RSASignaturePadding.Pkcs1));
        }
Ejemplo n.º 10
0
        public static RSAParameters ReadOpenPgpPublicKey(ReadOnlySpan <byte> source, out int bytesRead)
        {
            var rsaParameters = new RSAParameters();

            rsaParameters.Modulus = MPInteger.ReadInteger(source, out int modulusConsumed).ToArray();
            source = source.Slice(modulusConsumed);
            rsaParameters.Exponent = MPInteger.ReadInteger(source, out int exponentConsumed).ToArray();
            bytesRead = modulusConsumed + exponentConsumed;
            return(rsaParameters);
        }
Ejemplo n.º 11
0
        public byte[] CreateSignature(
            ReadOnlySpan <byte> rgbHash,
            PgpHashAlgorithm hashAlgorithm)
        {
            var signature      = rsa.SignHash(rgbHash.ToArray(), PgpUtilities.GetHashAlgorithmName(hashAlgorithm), RSASignaturePadding.Pkcs1);
            var signatureBytes = new byte[MPInteger.GetMPEncodedLength(signature)];

            MPInteger.TryWriteInteger(signature, signatureBytes, out var _);
            return(signatureBytes);
        }
Ejemplo n.º 12
0
        public byte[] ExportPublicKey()
        {
            var rsaParameters  = rsa.ExportParameters(false);
            int expectedLength = MPInteger.GetMPEncodedLength(rsaParameters.Modulus !, rsaParameters.Exponent !);
            var destination    = new byte[expectedLength];

            MPInteger.TryWriteInteger(rsaParameters.Modulus, destination, out int modulusWritten);
            MPInteger.TryWriteInteger(rsaParameters.Exponent, destination.AsSpan(modulusWritten), out int exponentWritten);
            return(destination.AsSpan(0, modulusWritten + exponentWritten).ToArray());
        }
Ejemplo n.º 13
0
        public byte[] EncryptSessionInfo(ReadOnlySpan <byte> sessionInfo)
        {
            var encryptedData = elGamal.Encrypt(sessionInfo, RSAEncryptionPadding.Pkcs1);
            var g             = encryptedData.Slice(0, encryptedData.Length / 2);
            var p             = encryptedData.Slice(encryptedData.Length / 2);
            var mp            = new byte[MPInteger.GetMPEncodedLength(g) + MPInteger.GetMPEncodedLength(p)];

            MPInteger.TryWriteInteger(g, mp, out var gWritten);
            MPInteger.TryWriteInteger(p, mp.AsSpan(gWritten), out var _);
            return(mp);
        }
Ejemplo n.º 14
0
        public byte[] CreateSignature(ReadOnlySpan <byte> rgbHash, PgpHashAlgorithm hashAlgorithm)
        {
            byte[] ieeeSignature = dsa.CreateSignature(rgbHash.ToArray(), DSASignatureFormat.IeeeP1363FixedFieldConcatenation);
            var    r             = ieeeSignature.AsSpan(0, ieeeSignature.Length / 2);
            var    s             = ieeeSignature.AsSpan(ieeeSignature.Length / 2);

            byte[] pgpSignature = new byte[MPInteger.GetMPEncodedLength(r) + MPInteger.GetMPEncodedLength(s)];
            MPInteger.TryWriteInteger(r, pgpSignature, out int rWritten);
            MPInteger.TryWriteInteger(s, pgpSignature.AsSpan(rWritten), out int _);
            return(pgpSignature);
        }
Ejemplo n.º 15
0
        private static ElGamalParameters ReadOpenPgpPublicKey(ReadOnlySpan <byte> source, out int bytesRead)
        {
            var elgamalParameters = new ElGamalParameters();

            elgamalParameters.P = MPInteger.ReadInteger(source, out int pConsumed).ToArray();
            source = source.Slice(pConsumed);
            elgamalParameters.G = MPInteger.ReadInteger(source, out int gConsumed).ToArray();
            source = source.Slice(gConsumed);
            elgamalParameters.Y = MPInteger.ReadInteger(source, out int yConsumed).ToArray();
            bytesRead           = pConsumed + gConsumed + yConsumed;
            return(elgamalParameters);
        }
Ejemplo n.º 16
0
        protected void WriteOpenPgpECParameters(ECParameters ecParameters, Span <byte> destination, out int bytesWritten)
        {
            var writer = new AsnWriter(AsnEncodingRules.DER);

            writer.WriteObjectIdentifier(ecParameters.Curve.Oid.Value !);
            var encodedPoint = EncodePoint(ecParameters.Q, ecParameters.Curve.Oid);
            var encodedOid   = writer.Encode();

            encodedOid.AsSpan(1).CopyTo(destination);
            MPInteger.TryWriteInteger(encodedPoint, destination.Slice(encodedOid.Length - 1), out bytesWritten);
            bytesWritten += encodedOid.Length - 1;
        }
Ejemplo n.º 17
0
        public bool TryDecryptSessionInfo(ReadOnlySpan <byte> encryptedSessionData, Span <byte> sessionData, out int bytesWritten)
        {
            var mp   = MPInteger.ReadInteger(encryptedSessionData, out var _);
            var data = rsa.Decrypt(mp.ToArray(), RSAEncryptionPadding.Pkcs1);

            if (sessionData.Length >= data.Length)
            {
                data.CopyTo(sessionData);
                bytesWritten = data.Length;
                return(true);
            }
            bytesWritten = 0;
            return(false);
        }
Ejemplo n.º 18
0
        public bool VerifySignature(
            ReadOnlySpan <byte> rgbHash,
            ReadOnlySpan <byte> rgbSignature,
            PgpHashAlgorithm hashAlgorithm)
        {
            var asnWriter = new AsnWriter(AsnEncodingRules.DER);

            using (var scope = asnWriter.PushSequence())
            {
                asnWriter.WriteIntegerUnsigned(MPInteger.ReadInteger(rgbSignature, out int rConsumed));
                asnWriter.WriteIntegerUnsigned(MPInteger.ReadInteger(rgbSignature.Slice(rConsumed), out var _));
            }
            return(dsa.VerifySignature(rgbHash, asnWriter.Encode(), DSASignatureFormat.Rfc3279DerSequence));
        }
Ejemplo n.º 19
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);
            }
        }
Ejemplo n.º 20
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);
                }
            }
        }
Ejemplo n.º 21
0
        public bool TryDecryptSessionInfo(ReadOnlySpan <byte> encryptedSessionData, Span <byte> sessionData, out int bytesWritten)
        {
            var g          = MPInteger.ReadInteger(encryptedSessionData, out var gBytesRead);
            var p          = MPInteger.ReadInteger(encryptedSessionData.Slice(gBytesRead), out var _);
            var halfLength = Math.Max(g.Length, p.Length);
            var inputData  = new byte[halfLength * 2];

            g.CopyTo(inputData.AsSpan(halfLength - g.Length));
            p.CopyTo(inputData.AsSpan(inputData.Length - p.Length));
            var data = elGamal.Decrypt(inputData, RSAEncryptionPadding.Pkcs1);

            if (sessionData.Length >= data.Length)
            {
                data.CopyTo(sessionData);
                bytesWritten = data.Length;
                return(true);
            }
            bytesWritten = 0;
            return(false);
        }
Ejemplo n.º 22
0
        private static DSAParameters ReadOpenPgpPublicKey(ReadOnlySpan <byte> source, out int bytesRead)
        {
            var dsaParameters = new DSAParameters();

            dsaParameters.P = MPInteger.ReadInteger(source, out int pConsumed).ToArray();
            source          = source.Slice(pConsumed);
            dsaParameters.Q = MPInteger.ReadInteger(source, out int qConsumed).ToArray();
            source          = source.Slice(qConsumed);
            dsaParameters.G = MPInteger.ReadInteger(source, out int gConsumed).ToArray();
            source          = source.Slice(gConsumed);
            dsaParameters.Y = MPInteger.ReadInteger(source, out int yConsumed).ToArray();
            bytesRead       = pConsumed + qConsumed + gConsumed + yConsumed;

            // Make sure P, G, Y have the same length (DSA implementation on Windows requires it)
            int pgyLength = Math.Max(Math.Max(dsaParameters.P !.Length, dsaParameters.G !.Length), dsaParameters.Y !.Length);

            ResizeArrayIfNeeded(ref dsaParameters.P, pgyLength);
            ResizeArrayIfNeeded(ref dsaParameters.G, pgyLength);
            ResizeArrayIfNeeded(ref dsaParameters.Y, pgyLength);

            return(dsaParameters);
        }
Ejemplo n.º 23
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);
            }
        }
Ejemplo n.º 24
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);
            }
        }
Ejemplo n.º 25
0
        protected static ECParameters ReadOpenPgpECParameters(ReadOnlySpan <byte> source, out int bytesRead)
        {
            ECParameters ecParameters = new ECParameters();

            int oidLength = source[0];
            // TODO: Validate oidLength
            var oidBytes = new byte[oidLength + 2];

            oidBytes[0] = 6;
            oidBytes[1] = (byte)oidLength;
            source.Slice(1, oidLength).CopyTo(oidBytes.AsSpan(2));
            var oid = new Oid(AsnDecoder.ReadObjectIdentifier(oidBytes, AsnEncodingRules.DER, out _));

            ecParameters.Curve = ECCurve.CreateFromOid(oid);

            var pointBytes = MPInteger.ReadInteger(source.Slice(oidLength + 1), out bytesRead);

            bytesRead += oidLength + 1;

            ecParameters.Q = DecodePoint(pointBytes);

            return(ecParameters);
        }
Ejemplo n.º 26
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);
            }
        }
Ejemplo n.º 27
0
 private static void WriteOpenPgpPublicKey(ElGamalParameters elgamalParameters, Span <byte> destination)
 {
     MPInteger.TryWriteInteger(elgamalParameters.P, destination, out int pWritten);
     MPInteger.TryWriteInteger(elgamalParameters.G, destination.Slice(pWritten), out int gWritten);
     MPInteger.TryWriteInteger(elgamalParameters.Y, destination.Slice(pWritten + gWritten), out int yWritten);
 }
Ejemplo n.º 28
0
        public static void EncryptSecretKey(
            ReadOnlySpan <byte> password,
            S2kParameters s2kParameters,
            ReadOnlySpan <byte> source,
            Span <byte> destination,
            int version = 4)
        {
            if (password.Length == 0)
            {
                destination[0] = (byte)S2kUsageTag.None;
                source.CopyTo(destination.Slice(1));
                return;
            }

            using var c = PgpUtilities.GetSymmetricAlgorithm(s2kParameters.EncryptionAlgorithm);

            int         keySizeInBytes = (c.KeySize + 7) / 8;
            Span <byte> keyBytes       = stackalloc byte[keySizeInBytes];

            if (version <= 3)
            {
                MakeKey(password, PgpHashAlgorithm.MD5, Array.Empty <byte>(), 0, keyBytes);

                destination[0] = (byte)s2kParameters.EncryptionAlgorithm;

                c.GenerateIV();
                c.IV.CopyTo(destination.Slice(1));
                int bytesWritten = 13 + ((c.BlockSize + 7) / 8);
                destination = destination.Slice(bytesWritten);

                c.Key = keyBytes.ToArray();

                int checksum = 0;
                foreach (var b in source)
                {
                    checksum += b;
                }

                for (int i = 0; i < 4; i++)
                {
                    using var encryptor = new ZeroPaddedCryptoTransform(c.CreateEncryptor());

                    destination[0] = source[0];
                    destination[1] = source[1];

                    var mpInteger = MPInteger.ReadInteger(source, out int bytesConsumed).ToArray();
                    source = source.Slice(bytesConsumed);

                    var data = encryptor.TransformFinalBlock(mpInteger, 0, mpInteger.Length);
                    data.AsSpan().CopyTo(destination.Slice(2));
                    destination = destination.Slice(2 + data.Length);
                    CryptographicOperations.ZeroMemory(mpInteger);

                    if (i != 4)
                    {
                        c.IV = data.AsSpan(data.Length - (c.BlockSize / 8)).ToArray();
                    }
                }

                destination[0] = (byte)(checksum >> 8);
                destination[1] = (byte)(checksum);
            }
            else
            {
                var salt = new byte[8];
                RandomNumberGenerator.Fill(salt);
                byte rawIterationCount = 0x60;
                int  iterationCount    = (16 + (rawIterationCount & 15)) << ((rawIterationCount >> 4) + 6);

                MakeKey(password, s2kParameters.HashAlgorithm, salt, iterationCount, keyBytes);

                destination[0] = (byte)s2kParameters.UsageTag;
                destination[1] = (byte)s2kParameters.EncryptionAlgorithm;
                destination[2] = 3; // Salted & iterated
                destination[3] = (byte)s2kParameters.HashAlgorithm;

                salt.CopyTo(destination.Slice(4));
                destination[12] = rawIterationCount;

                c.GenerateIV();
                c.IV.CopyTo(destination.Slice(13));
                int bytesWritten = 13 + ((c.BlockSize + 7) / 8);
                destination = destination.Slice(bytesWritten);

                c.Key = keyBytes.ToArray();

                using var encryptor = new ZeroPaddedCryptoTransform(c.CreateEncryptor());
                byte[] checksumBytes;

                if (s2kParameters.UsageTag == S2kUsageTag.Sha1)
                {
                    using var sha1 = IncrementalHash.CreateHash(HashAlgorithmName.SHA1);
                    sha1.AppendData(source);
                    checksumBytes = sha1.GetHashAndReset();
                }
                else
                {
                    int checksum = 0;
                    foreach (var b in source)
                    {
                        checksum += b;
                    }
                    checksumBytes = new byte[] { (byte)(checksum >> 8), (byte)checksum };
                }

                var decSource = new byte[source.Length + checksumBytes.Length];
                source.CopyTo(decSource);
                checksumBytes.CopyTo(decSource, source.Length);

                var data = encryptor.TransformFinalBlock(decSource, 0, decSource.Length);
                data.AsSpan().CopyTo(destination);

                CryptographicOperations.ZeroMemory(data);
                CryptographicOperations.ZeroMemory(decSource);
            }
        }