/// <summary>
        /// Return an output stream which will encrypt the data as it is written to it.
        /// </summary>
        protected override IPacketWriter Open()
        {
            var writer = base.Open();

            if (cOut != null)
            {
                throw new InvalidOperationException("generator already in open state");
            }
            // TODO: Do we want compatibility with old PGP? (IDEA + no password iirc)
            if (methods.Count == 0)
            {
                throw new InvalidOperationException("No encryption methods specified");
            }

            var c = PgpUtilities.GetSymmetricAlgorithm(defAlgorithm);

            if (methods.Count == 1 && methods[0] is PbeMethod)
            {
                PbeMethod m = (PbeMethod)methods[0];
                c.Key = m.GetKey();
                writer.WritePacket(m.GetSessionInfoPacket());
            }
            else
            {
                c.GenerateKey();
                byte[] sessionInfo = CreateSessionInfo(defAlgorithm, c.Key);

                foreach (EncMethod m in methods)
                {
                    writer.WritePacket(m.GetSessionInfoPacket(sessionInfo));
                }
            }

            try
            {
                if (withIntegrityPacket)
                {
                    pOut = writer.GetPacketStream(new SymmetricEncIntegrityPacket());
                }
                else
                {
                    pOut = writer.GetPacketStream(new SymmetricEncDataPacket());
                }

                int    blockSize = (c.BlockSize + 7) / 8;
                byte[] inLineIv  = new byte[blockSize * 2]; // Aligned to block size
                RandomNumberGenerator.Fill(inLineIv.AsSpan(0, blockSize));
                inLineIv[blockSize]     = inLineIv[blockSize - 2];
                inLineIv[blockSize + 1] = inLineIv[blockSize - 1];

                ICryptoTransform encryptor;
                c.IV = new byte[blockSize];
                if (withIntegrityPacket)
                {
                    encryptor = c.CreateEncryptor();
                }
                else
                {
                    encryptor = c.CreateEncryptor();
                    var encryptedInlineIv = encryptor.TransformFinalBlock(inLineIv, 0, inLineIv.Length);
                    pOut.Write(encryptedInlineIv.AsSpan(0, blockSize + 2));
                    c.IV      = encryptedInlineIv.AsSpan(2, blockSize).ToArray();
                    encryptor = c.CreateEncryptor();
                }

                Stream myOut = cOut = new CryptoStream(pOut, new ZeroPaddedCryptoTransform(encryptor), CryptoStreamMode.Write);

                if (withIntegrityPacket)
                {
                    digest = SHA1.Create();
                    myOut  = digestOut = new CryptoStream(new FilterStream(myOut), digest, CryptoStreamMode.Write);
                    myOut.Write(inLineIv, 0, blockSize + 2);
                }

                return(writer.CreateNestedWriter(new WrappedGeneratorStream(myOut, _ => Close())));
            }
            catch (Exception e)
            {
                throw new PgpException("Exception creating cipher", e);
            }
        }
Beispiel #2
0
        private Stream Open(Stream outStr, long length, byte[] buffer)
        {
            //IL_000d: Unknown result type (might be due to invalid IL or missing references)
            //IL_0025: Unknown result type (might be due to invalid IL or missing references)
            //IL_0033: Unknown result type (might be due to invalid IL or missing references)
            if (cOut != null)
            {
                throw new InvalidOperationException("generator already in open state");
            }
            if (((global::System.Collections.ICollection)methods).get_Count() == 0)
            {
                throw new InvalidOperationException("No encryption methods specified");
            }
            if (outStr == null)
            {
                throw new ArgumentNullException("outStr");
            }
            pOut = new BcpgOutputStream(outStr);
            KeyParameter keyParameter;

            if (((global::System.Collections.ICollection)methods).get_Count() == 1)
            {
                if (methods.get_Item(0) is PbeMethod)
                {
                    PbeMethod pbeMethod = (PbeMethod)methods.get_Item(0);
                    keyParameter = pbeMethod.GetKey();
                }
                else
                {
                    keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
                    byte[]    si        = CreateSessionInfo(defAlgorithm, keyParameter);
                    PubMethod pubMethod = (PubMethod)methods.get_Item(0);
                    try
                    {
                        pubMethod.AddSessionInfo(si, rand);
                    }
                    catch (global::System.Exception exception)
                    {
                        throw new PgpException("exception encrypting session key", exception);
                    }
                }
                pOut.WritePacket((ContainedPacket)methods.get_Item(0));
            }
            else
            {
                keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
                byte[] si2 = CreateSessionInfo(defAlgorithm, keyParameter);
                for (int i = 0; i != ((global::System.Collections.ICollection)methods).get_Count(); i++)
                {
                    EncMethod encMethod = (EncMethod)methods.get_Item(i);
                    try
                    {
                        encMethod.AddSessionInfo(si2, rand);
                    }
                    catch (global::System.Exception exception2)
                    {
                        throw new PgpException("exception encrypting session key", exception2);
                    }
                    pOut.WritePacket(encMethod);
                }
            }
            string symmetricCipherName = PgpUtilities.GetSymmetricCipherName(defAlgorithm);

            if (symmetricCipherName == null)
            {
                throw new PgpException("null cipher specified");
            }
            try
            {
                symmetricCipherName = ((!withIntegrityPacket) ? (symmetricCipherName + "/OpenPGPCFB/NoPadding") : (symmetricCipherName + "/CFB/NoPadding"));
                c = CipherUtilities.GetCipher(symmetricCipherName);
                byte[] iv = new byte[c.GetBlockSize()];
                c.Init(forEncryption: true, new ParametersWithRandom(new ParametersWithIV(keyParameter, iv), rand));
                if (buffer == null)
                {
                    if (withIntegrityPacket)
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22);
                        ((Stream)pOut).WriteByte((byte)1);
                    }
                    else
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat);
                    }
                }
                else if (withIntegrityPacket)
                {
                    pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer);
                    ((Stream)pOut).WriteByte((byte)1);
                }
                else
                {
                    pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer);
                }
                int    blockSize = c.GetBlockSize();
                byte[] array     = new byte[blockSize + 2];
                rand.NextBytes(array, 0, blockSize);
                global::System.Array.Copy((global::System.Array)array, array.Length - 4, (global::System.Array)array, array.Length - 2, 2);
                Stream val = (Stream)(object)(cOut = new CipherStream((Stream)(object)pOut, null, c));
                if (withIntegrityPacket)
                {
                    string  digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
                    IDigest digest     = DigestUtilities.GetDigest(digestName);
                    val = (Stream)(object)(digestOut = new DigestStream(val, null, digest));
                }
                val.Write(array, 0, array.Length);
                return((Stream)(object)new WrappedGeneratorStream(this, val));
            }
            catch (global::System.Exception exception3)
            {
                throw new PgpException("Exception creating cipher", exception3);
            }
        }
Beispiel #3
0
        /// <summary>
        /// <p>
        /// If buffer is non null stream assumed to be partial, otherwise the length will be used
        /// to output a fixed length packet.
        /// </p>
        /// <p>
        /// The stream created can be closed off by either calling Close()
        /// on the stream or Close() on the generator. Closing the returned
        /// stream does not close off the Stream parameter <c>outStr</c>.
        /// </p>
        /// </summary>
        private Stream Open(
            Stream outStr,
            long length,
            byte[]      buffer)
        {
            if (cOut != null)
            {
                throw new InvalidOperationException("generator already in open state");
            }
            if (methods.Count == 0)
            {
                throw new InvalidOperationException("No encryption methods specified");
            }
            if (outStr == null)
            {
                throw new ArgumentNullException("outStr");
            }

            pOut = new BcpgOutputStream(outStr);

            KeyParameter key;

            if (methods.Count == 1)
            {
                if (methods[0] is PbeMethod)
                {
                    PbeMethod m = (PbeMethod)methods[0];

                    key = m.GetKey();
                }
                else
                {
                    key = PgpUtilities.MakeRandomKey(defAlgorithm, rand);

                    byte[]    sessionInfo = CreateSessionInfo(defAlgorithm, key);
                    PubMethod m           = (PubMethod)methods[0];

                    try
                    {
                        m.AddSessionInfo(sessionInfo, rand);
                    }
                    catch (Exception e)
                    {
                        throw new PgpException("exception encrypting session key", e);
                    }
                }

                pOut.WritePacket((ContainedPacket)methods[0]);
            }
            else // multiple methods
            {
                key = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
                byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key);

                for (int i = 0; i != methods.Count; i++)
                {
                    EncMethod m = (EncMethod)methods[i];

                    try
                    {
                        m.AddSessionInfo(sessionInfo, rand);
                    }
                    catch (Exception e)
                    {
                        throw new PgpException("exception encrypting session key", e);
                    }

                    pOut.WritePacket(m);
                }
            }

            string cName = PgpUtilities.GetSymmetricCipherName(defAlgorithm);

            if (cName == null)
            {
                throw new PgpException("null cipher specified");
            }

            try
            {
                if (withIntegrityPacket)
                {
                    cName += "/CFB/NoPadding";
                }
                else
                {
                    cName += "/OpenPGPCFB/NoPadding";
                }

                c = CipherUtilities.GetCipher(cName);

                // TODO Confirm the IV should be all zero bytes (not inLineIv - see below)
                byte[] iv = new byte[c.GetBlockSize()];
                c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), rand));

                if (buffer == null)
                {
                    //
                    // we have to Add block size + 2 for the Generated IV and + 1 + 22 if integrity protected
                    //
                    if (withIntegrityPacket)
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22);
                        pOut.WriteByte(1);        // version number
                    }
                    else
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat);
                    }
                }
                else
                {
                    if (withIntegrityPacket)
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer);
                        pOut.WriteByte(1);        // version number
                    }
                    else
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer);
                    }
                }

                int    blockSize = c.GetBlockSize();
                byte[] inLineIv  = new byte[blockSize + 2];
                rand.NextBytes(inLineIv, 0, blockSize);
                Array.Copy(inLineIv, inLineIv.Length - 4, inLineIv, inLineIv.Length - 2, 2);

                Stream myOut = cOut = new CipherStream(pOut, null, c);

                if (withIntegrityPacket)
                {
                    string  digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
                    IDigest digest     = DigestUtilities.GetDigest(digestName);
                    myOut = digestOut = new DigestStream(myOut, null, digest);
                }

                myOut.Write(inLineIv, 0, inLineIv.Length);

                return(new WrappedGeneratorStream(this, myOut));
            }
            catch (Exception e)
            {
                throw new PgpException("Exception creating cipher", e);
            }
        }
Beispiel #4
0
    private Stream Open(Stream outStr, long length, byte[] buffer)
    {
        if (cOut != null)
        {
            throw new InvalidOperationException("generator already in open state");
        }
        if (methods.Count == 0)
        {
            throw new InvalidOperationException("No encryption methods specified");
        }
        if (outStr == null)
        {
            throw new ArgumentNullException("outStr");
        }
        pOut = new BcpgOutputStream(outStr);
        KeyParameter keyParameter;

        if (methods.Count == 1)
        {
            if (methods[0] is PbeMethod)
            {
                PbeMethod pbeMethod = (PbeMethod)methods[0];
                keyParameter = pbeMethod.GetKey();
            }
            else
            {
                keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
                byte[]    si        = CreateSessionInfo(defAlgorithm, keyParameter);
                PubMethod pubMethod = (PubMethod)methods[0];
                try
                {
                    pubMethod.AddSessionInfo(si, rand);
                }
                catch (Exception exception)
                {
                    throw new PgpException("exception encrypting session key", exception);
                }
            }
            pOut.WritePacket((ContainedPacket)methods[0]);
        }
        else
        {
            keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
            byte[] si2 = CreateSessionInfo(defAlgorithm, keyParameter);
            for (int i = 0; i != methods.Count; i++)
            {
                EncMethod encMethod = (EncMethod)methods[i];
                try
                {
                    encMethod.AddSessionInfo(si2, rand);
                }
                catch (Exception exception2)
                {
                    throw new PgpException("exception encrypting session key", exception2);
                }
                pOut.WritePacket(encMethod);
            }
        }
        string symmetricCipherName = PgpUtilities.GetSymmetricCipherName(defAlgorithm);

        if (symmetricCipherName == null)
        {
            throw new PgpException("null cipher specified");
        }
        try
        {
            symmetricCipherName = ((!withIntegrityPacket) ? (symmetricCipherName + "/OpenPGPCFB/NoPadding") : (symmetricCipherName + "/CFB/NoPadding"));
            c = CipherUtilities.GetCipher(symmetricCipherName);
            byte[] iv = new byte[c.GetBlockSize()];
            c.Init(forEncryption: true, new ParametersWithRandom(new ParametersWithIV(keyParameter, iv), rand));
            if (buffer == null)
            {
                if (withIntegrityPacket)
                {
                    pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22);
                    pOut.WriteByte(1);
                }
                else
                {
                    pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat);
                }
            }
            else if (withIntegrityPacket)
            {
                pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer);
                pOut.WriteByte(1);
            }
            else
            {
                pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer);
            }
            int    blockSize = c.GetBlockSize();
            byte[] array     = new byte[blockSize + 2];
            rand.NextBytes(array, 0, blockSize);
            Array.Copy(array, array.Length - 4, array, array.Length - 2, 2);
            Stream stream = cOut = new CipherStream(pOut, null, c);
            if (withIntegrityPacket)
            {
                string  digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
                IDigest digest     = DigestUtilities.GetDigest(digestName);
                stream = (digestOut = new DigestStream(stream, null, digest));
            }
            stream.Write(array, 0, array.Length);
            return(new WrappedGeneratorStream(this, stream));
        }
        catch (Exception exception3)
        {
            throw new PgpException("Exception creating cipher", exception3);
        }
    }