예제 #1
0
        private Stream GetDataStream(ReadOnlySpan <byte> sessionData, bool verifyIntegrity)
        {
            PgpSymmetricKeyAlgorithm keyAlgorithm = (PgpSymmetricKeyAlgorithm)sessionData[0];

            if (keyAlgorithm == PgpSymmetricKeyAlgorithm.Null)
            {
                return(inputStream);
            }

            var key = sessionData.Slice(1);
            SymmetricAlgorithm encryptionAlgorithm = PgpUtilities.GetSymmetricAlgorithm(keyAlgorithm);
            var iv = new byte[(encryptionAlgorithm.BlockSize + 7) / 8];

            byte[]           keyArray = Array.Empty <byte>();
            ICryptoTransform decryptor;
            var inlineIv = new byte[iv.Length * 2]; // Aligned to block size

            try
            {
                keyArray  = key.ToArray();
                decryptor = encryptionAlgorithm.CreateDecryptor(keyArray, iv);
                if (encryptedPacket is SymmetricEncDataPacket)
                {
                    if (inputStream.ReadFully(inlineIv.AsSpan(0, iv.Length + 2)) < iv.Length + 2)
                    {
                        throw new EndOfStreamException();
                    }

                    var decryptedInlineIv = decryptor.TransformFinalBlock(inlineIv, 0, inlineIv.Length);
                    if (verifyIntegrity)
                    {
                        VerifyInlineIV(decryptedInlineIv.AsSpan(0, iv.Length), decryptedInlineIv.AsSpan(iv.Length, 2));
                    }

                    // Perform reset according to the OpenPGP CFB rules
                    decryptor = encryptionAlgorithm.CreateDecryptor(keyArray, inlineIv.AsSpan(2, iv.Length).ToArray());
                }
            }
            finally
            {
                CryptographicOperations.ZeroMemory(keyArray.AsSpan());
            }

            encStream = new CryptoStream(
                inputStream,
                new ZeroPaddedCryptoTransform(decryptor),
                CryptoStreamMode.Read);
            if (encryptedPacket is SymmetricEncIntegrityPacket)
            {
                hashAlgorithm          = SHA1.Create();
                tailEndCryptoTransform = new TailEndCryptoTransform(hashAlgorithm, hashAlgorithm.HashSize / 8);
                encStream = new CryptoStream(encStream, tailEndCryptoTransform, CryptoStreamMode.Read);

                if (encStream.ReadFully(inlineIv.AsSpan(0, iv.Length + 2)) < iv.Length + 2)
                {
                    throw new EndOfStreamException();
                }

                if (verifyIntegrity)
                {
                    VerifyInlineIV(inlineIv.AsSpan(0, iv.Length), inlineIv.AsSpan(iv.Length, 2));
                }
            }

            return(encStream);
        }
예제 #2
0
        private static byte[] GetDValue(SXprReader reader, KeyPacket publicKey, byte[] rawPassPhrase, string curveName)
        {
            string type;

            reader.SkipOpenParenthesis();

            string protection;
            string?protectedAt = null;
            S2k    s2k;

            byte[] iv;
            byte[] secKeyData;

            type = reader.ReadString();
            if (type.Equals("protected", StringComparison.Ordinal))
            {
                protection = reader.ReadString();

                reader.SkipOpenParenthesis();

                s2k = reader.ParseS2k();

                iv = reader.ReadBytes();

                reader.SkipCloseParenthesis();

                secKeyData = reader.ReadBytes();

                reader.SkipCloseParenthesis();

                reader.SkipOpenParenthesis();

                if (reader.ReadString().Equals("protected-at", StringComparison.Ordinal))
                {
                    protectedAt = reader.ReadString();
                }
            }
            else
            {
                throw new PgpException("protected block not found");
            }

            byte[] data;

            switch (protection)
            {
            case "openpgp-s2k3-sha1-aes256-cbc":
            case "openpgp-s2k3-sha1-aes-cbc":
                PgpSymmetricKeyAlgorithm symmAlg =
                    protection.Equals("openpgp-s2k3-sha1-aes256-cbc", StringComparison.Ordinal) ?
                    PgpSymmetricKeyAlgorithm.Aes256 :
                    PgpSymmetricKeyAlgorithm.Aes128;
                using (var c = PgpUtilities.GetSymmetricAlgorithm(symmAlg))
                {
                    var keyBytes = new byte[c.KeySize / 8];
                    S2kBasedEncryption.MakeKey(rawPassPhrase, PgpHashAlgorithm.Sha1, s2k.GetIV(), s2k.IterationCount, keyBytes);
                    c.Key  = keyBytes;
                    c.IV   = iv;
                    c.Mode = CipherMode.CBC;
                    using var decryptor = new ZeroPaddedCryptoTransform(c.CreateDecryptor());
                    data = decryptor.TransformFinalBlock(secKeyData, 0, secKeyData.Length);
                    // TODO: check SHA-1 hash.
                }
                break;

            case "openpgp-s2k3-ocb-aes":
            {
                MemoryStream aad = new MemoryStream();
                WriteSExprPublicKey(new SXprWriter(aad), publicKey, curveName, protectedAt);
                var keyBytes = new byte[16];
                S2kBasedEncryption.MakeKey(rawPassPhrase, PgpHashAlgorithm.Sha1, s2k.GetIV(), s2k.IterationCount, keyBytes);
                using var aesOcb = new AesOcb(keyBytes);
                data             = new byte[secKeyData.Length - 16];
                aesOcb.Decrypt(iv, secKeyData.AsSpan(0, secKeyData.Length - 16), secKeyData.AsSpan(secKeyData.Length - 16), data, aad.ToArray());
            }
            break;

            case "openpgp-native":
            default:
                throw new PgpException(protection + " key format is not supported yet");
            }

            //
            // parse the secret key S-expr
            //
            Stream keyIn = new MemoryStream(data, false);

            reader = new SXprReader(keyIn);
            reader.SkipOpenParenthesis();
            reader.SkipOpenParenthesis();
            reader.SkipOpenParenthesis();
            String name = reader.ReadString();

            return(reader.ReadBytes());
        }