示例#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);
            }
        }
示例#2
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);
            }
        }
示例#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);
        }
示例#4
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));
        }
示例#5
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);
        }
示例#6
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);
        }
示例#7
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);
        }
示例#8
0
文件: DsaKey.cs 项目: 1hub/springburg
        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));
        }
示例#9
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);
        }
示例#10
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);
            }
        }
示例#11
0
文件: DsaKey.cs 项目: 1hub/springburg
        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);
        }
示例#12
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);
            }
        }
示例#13
0
文件: ECKey.cs 项目: 1hub/springburg
        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);
        }
示例#14
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);
            }
        }
示例#15
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);
            }
        }