/// <summary>
        /// Return a copy of the passed in secret key, encrypted using a new password
        /// and the passed in algorithm.
        /// </summary>
        /// <param name="key">The PgpSecretKey to be copied.</param>
        /// <param name="oldPassPhrase">The current password for the key.</param>
        /// <param name="newPassPhrase">The new password for the key.</param>
        /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
        /// <param name="rand">Source of randomness.</param>
        public static PgpSecretKey CopyWithNewPassword(IPgpSecretKey key, char[] oldPassPhrase, char[] newPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand)
        {
            var rawKeyData = key.ExtractKeyData(oldPassPhrase);
            var s2KUsage   = key.SecretPacket.S2KUsage;

            byte[] iv  = null;
            S2k    s2K = null;

            byte[] keyData;

            if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null)
            {
                s2KUsage = SecretKeyPacket.UsageNone;
                if (key.SecretPacket.S2KUsage == SecretKeyPacket.UsageSha1)   // SHA-1 hash, need to rewrite Checksum
                {
                    keyData = new byte[rawKeyData.Length - 18];

                    Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2);

                    var check = Checksum(false, keyData, keyData.Length - 2);

                    keyData[keyData.Length - 2] = check[0];
                    keyData[keyData.Length - 1] = check[1];
                }
                else
                {
                    keyData = rawKeyData;
                }
            }
            else
            {
                try
                {
                    keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2K, out iv);
                }
                catch (PgpException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw new PgpException("Exception encrypting key", e);
                }
            }

            SecretKeyPacket secret;

            if (key.SecretPacket is SecretSubkeyPacket)
            {
                secret = new SecretSubkeyPacket(key.SecretPacket.PublicKeyPacket,
                                                newEncAlgorithm, s2KUsage, s2K, iv, keyData);
            }
            else
            {
                secret = new SecretKeyPacket(key.SecretPacket.PublicKeyPacket,
                                             newEncAlgorithm, s2KUsage, s2K, iv, keyData);
            }

            return(new PgpSecretKey(secret, key.PublicKey));
        }
        /// <summary>Replace the passed public key on the passed in secret key.</summary>
        /// <param name="secretKey">Secret key to change.</param>
        /// <param name="publicKey">New public key.</param>
        /// <returns>A new secret key.</returns>
        /// <exception cref="ArgumentException">If KeyId's do not match.</exception>
        public static IPgpSecretKey ReplacePublicKey(IPgpSecretKey secretKey, IPgpPublicKey publicKey)
        {
            if (publicKey.KeyId != secretKey.KeyId)
            {
                throw new ArgumentException("KeyId's do not match");
            }

            return(new PgpSecretKey(secretKey.SecretPacket, publicKey));
        }
        private void generateTest(
            string message,
            string type)
        {
            IPgpSecretKey                  pgpSecKey  = ReadSecretKey(new MemoryStream(secretKey));
            IPgpPrivateKey                 pgpPrivKey = pgpSecKey.ExtractPrivateKey("".ToCharArray());
            PgpSignatureGenerator          sGen       = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, HashAlgorithmTag.Sha256);
            PgpSignatureSubpacketGenerator spGen      = new PgpSignatureSubpacketGenerator();

            sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey);

            IEnumerator it = pgpSecKey.PublicKey.GetUserIds().GetEnumerator();

            if (it.MoveNext())
            {
                spGen.SetSignerUserId(false, (string)it.Current);
                sGen.SetHashedSubpackets(spGen.Generate());
            }

            MemoryStream        bOut = new MemoryStream();
            ArmoredOutputStream aOut = new ArmoredOutputStream(bOut);
            MemoryStream        bIn  = new MemoryStream(Encoding.ASCII.GetBytes(message), false);

            aOut.BeginClearText(HashAlgorithmTag.Sha256);

            //
            // note the last \n m_in the file is ignored
            //
            MemoryStream lineOut   = new MemoryStream();
            int          lookAhead = ReadInputLine(lineOut, bIn);

            ProcessLine(aOut, sGen, lineOut.ToArray());

            if (lookAhead != -1)
            {
                do
                {
                    lookAhead = ReadInputLine(lineOut, lookAhead, bIn);

                    sGen.Update((byte)'\r');
                    sGen.Update((byte)'\n');

                    ProcessLine(aOut, sGen, lineOut.ToArray());
                }while (lookAhead != -1);
            }

            aOut.EndClearText();

            BcpgOutputStream bcpgOut = new BcpgOutputStream(aOut);

            sGen.Generate().Encode(bcpgOut);

            aOut.Close();

            byte[] bs = bOut.ToArray();
            messageTest(Encoding.ASCII.GetString(bs, 0, bs.Length), type);
        }
Esempio n. 4
0
        /**
         * Search a secret key ring collection for a secret key corresponding to keyID if it
         * exists.
         *
         * @param pgpSec a secret key ring collection.
         * @param keyID keyID we want.
         * @param pass passphrase to decrypt secret key with.
         * @return
         * @throws PGPException
         * @throws NoSuchProviderException
         */
        internal static IPgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec, long keyID, char[] pass)
        {
            IPgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyID);

            if (pgpSecKey == null)
            {
                return(null);
            }

            return(pgpSecKey.ExtractPrivateKey(pass));
        }
Esempio n. 5
0
        private static byte[] SignPublicKey(
            IPgpSecretKey secretKey,
            string secretKeyPass,
            IPgpPublicKey keyToBeSigned,
            string notationName,
            string notationValue,
            bool armor)
        {
            Stream os = new MemoryStream();

            if (armor)
            {
                os = new ArmoredOutputStream(os);
            }

            IPgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(
                secretKeyPass.ToCharArray());

            PgpSignatureGenerator sGen = new PgpSignatureGenerator(
                secretKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.DirectKey, pgpPrivKey);

            BcpgOutputStream bOut = new BcpgOutputStream(os);

            sGen.GenerateOnePassVersion(false).Encode(bOut);

            PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();

            bool isHumanReadable = true;

            spGen.SetNotationData(true, isHumanReadable, notationName, notationValue);

            PgpSignatureSubpacketVector packetVector = spGen.Generate();

            sGen.SetHashedSubpackets(packetVector);

            bOut.Flush();

            if (armor)
            {
                os.Close();
            }

            return(PgpPublicKey.AddCertification(keyToBeSigned, sGen.Generate()).GetEncoded());
        }
        /// <summary>
        /// Returns a new key ring with the secret key passed in either added or
        /// replacing an existing one with the same key ID.
        /// </summary>
        /// <param name="secRing">The secret key ring to be modified.</param>
        /// <param name="secKey">The secret key to be inserted.</param>
        /// <returns>A new <c>PgpSecretKeyRing</c></returns>
        public static PgpSecretKeyRing InsertSecretKey(IPgpSecretKeyRing secRing, IPgpSecretKey secKey)
        {
            var keys        = Platform.CreateArrayList(secRing.GetSecretKeys());
            var found       = false;
            var masterFound = false;

            for (var i = 0; i != keys.Count; i++)
            {
                var key = keys[i];

                if (key.KeyId == secKey.KeyId)
                {
                    found   = true;
                    keys[i] = secKey;
                }
                if (key.IsMasterKey)
                {
                    masterFound = true;
                }
            }

            if (!found)
            {
                if (secKey.IsMasterKey)
                {
                    if (masterFound)
                    {
                        throw new ArgumentException("cannot add a master key to a ring that already has one");
                    }

                    keys.Insert(0, secKey);
                }
                else
                {
                    keys.Add(secKey);
                }
            }

            return(new PgpSecretKeyRing(keys, secRing.GetExtraPublicKeys()));
        }
Esempio n. 7
0
        private static void CreateSignature(
            string fileName,
            Stream keyIn,
            Stream outputStream,
            char[]  pass,
            bool armor)
        {
            if (armor)
            {
                outputStream = new ArmoredOutputStream(outputStream);
            }

            IPgpSecretKey         pgpSec     = PgpExampleUtilities.ReadSecretKey(keyIn);
            IPgpPrivateKey        pgpPrivKey = pgpSec.ExtractPrivateKey(pass);
            PgpSignatureGenerator sGen       = new PgpSignatureGenerator(
                pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);

            BcpgOutputStream bOut = new BcpgOutputStream(outputStream);

            Stream fIn = File.OpenRead(fileName);

            int ch;

            while ((ch = fIn.ReadByte()) >= 0)
            {
                sGen.Update((byte)ch);
            }

            fIn.Close();

            sGen.Generate().Encode(bOut);

            if (armor)
            {
                outputStream.Close();
            }
        }
        /// <summary>Replace the passed public key on the passed in secret key.</summary>
        /// <param name="secretKey">Secret key to change.</param>
        /// <param name="publicKey">New public key.</param>
        /// <returns>A new secret key.</returns>
        /// <exception cref="ArgumentException">If KeyId's do not match.</exception>
        public static IPgpSecretKey ReplacePublicKey(IPgpSecretKey secretKey, IPgpPublicKey publicKey)
        {
            if (publicKey.KeyId != secretKey.KeyId)
                throw new ArgumentException("KeyId's do not match");

            return new PgpSecretKey(secretKey.SecretPacket, publicKey);
        }
        /// <summary>
        /// Return a copy of the passed in secret key, encrypted using a new password
        /// and the passed in algorithm.
        /// </summary>
        /// <param name="key">The PgpSecretKey to be copied.</param>
        /// <param name="oldPassPhrase">The current password for the key.</param>
        /// <param name="newPassPhrase">The new password for the key.</param>
        /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
        /// <param name="rand">Source of randomness.</param>
        public static PgpSecretKey CopyWithNewPassword(IPgpSecretKey key, char[] oldPassPhrase, char[] newPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand)
        {
            var rawKeyData = key.ExtractKeyData(oldPassPhrase);
            var s2KUsage = key.SecretPacket.S2KUsage;
            byte[] iv = null;
            S2k s2K = null;
            byte[] keyData;

            if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null)
            {
                s2KUsage = SecretKeyPacket.UsageNone;
                if (key.SecretPacket.S2KUsage == SecretKeyPacket.UsageSha1)   // SHA-1 hash, need to rewrite Checksum
                {
                    keyData = new byte[rawKeyData.Length - 18];

                    Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2);

                    var check = Checksum(false, keyData, keyData.Length - 2);

                    keyData[keyData.Length - 2] = check[0];
                    keyData[keyData.Length - 1] = check[1];
                }
                else
                {
                    keyData = rawKeyData;
                }
            }
            else
            {
                try
                {
                    keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2K, out iv);
                }
                catch (PgpException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw new PgpException("Exception encrypting key", e);
                }
            }

            SecretKeyPacket secret;
            if (key.SecretPacket is SecretSubkeyPacket)
            {
                secret = new SecretSubkeyPacket(key.SecretPacket.PublicKeyPacket,
                    newEncAlgorithm, s2KUsage, s2K, iv, keyData);
            }
            else
            {
                secret = new SecretKeyPacket(key.SecretPacket.PublicKeyPacket,
                    newEncAlgorithm, s2KUsage, s2K, iv, keyData);
            }

            return new PgpSecretKey(secret, key.PublicKey);
        }
        public override void PerformTest()
        {
            //
            // Read the public key
            //
            PgpObjectFactory pgpFact = new PgpObjectFactory(testPubKeyRing);
            PgpPublicKeyRing pgpPub  = (PgpPublicKeyRing)pgpFact.NextPgpObject();

            var pubKey = pgpPub.GetPublicKey();

            if (pubKey.BitStrength != 1024)
            {
                Fail("failed - key strength reported incorrectly.");
            }

            //
            // Read the private key
            //
            PgpSecretKeyRing sKey       = new PgpSecretKeyRing(testPrivKeyRing);
            IPgpSecretKey    secretKey  = sKey.GetSecretKey();
            IPgpPrivateKey   pgpPrivKey = secretKey.ExtractPrivateKey(pass);

            //
            // signature generation
            //
            const string data = "hello world!";

            byte[]                dataBytes = Encoding.ASCII.GetBytes(data);
            MemoryStream          bOut      = new MemoryStream();
            MemoryStream          testIn    = new MemoryStream(dataBytes, false);
            PgpSignatureGenerator sGen      = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa,
                                                                        HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);

            PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator(
                CompressionAlgorithmTag.Zip);

            BcpgOutputStream bcOut = new BcpgOutputStream(
                cGen.Open(new UncloseableStream(bOut)));

            sGen.GenerateOnePassVersion(false).Encode(bcOut);

            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();

            DateTime testDateTime = new DateTime(1973, 7, 27);
            Stream   lOut         = lGen.Open(
                new UncloseableStream(bcOut),
                PgpLiteralData.Binary,
                "_CONSOLE",
                dataBytes.Length,
                testDateTime);

            int ch;

            while ((ch = testIn.ReadByte()) >= 0)
            {
                lOut.WriteByte((byte)ch);
                sGen.Update((byte)ch);
            }

            lGen.Close();

            sGen.Generate().Encode(bcOut);

            cGen.Close();

            //
            // verify Generated signature
            //
            pgpFact = new PgpObjectFactory(bOut.ToArray());

            PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject();

            pgpFact = new PgpObjectFactory(c1.GetDataStream());

            PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();

            PgpOnePassSignature ops = p1[0];

            PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();

            if (!p2.ModificationTime.Equals(testDateTime))
            {
                Fail("Modification time not preserved");
            }

            Stream dIn = p2.GetInputStream();

            ops.InitVerify(pubKey);

            while ((ch = dIn.ReadByte()) >= 0)
            {
                ops.Update((byte)ch);
            }

            PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();

            if (!ops.Verify(p3[0]))
            {
                Fail("Failed Generated signature check");
            }

            //
            // test encryption
            //

            //
            // find a key sutiable for encryption
            //
            long pgpKeyID = 0;
            IAsymmetricKeyParameter pKey = null;

            foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys())
            {
                if (pgpKey.Algorithm == PublicKeyAlgorithmTag.ElGamalEncrypt ||
                    pgpKey.Algorithm == PublicKeyAlgorithmTag.ElGamalGeneral)
                {
                    pKey     = pgpKey.GetKey();
                    pgpKeyID = pgpKey.KeyId;
                    if (pgpKey.BitStrength != 1024)
                    {
                        Fail("failed - key strength reported incorrectly.");
                    }

                    //
                    // verify the key
                    //
                }
            }

            IBufferedCipher c = CipherUtilities.GetCipher("ElGamal/None/PKCS1Padding");

            c.Init(true, pKey);

            byte[] inBytes  = Encoding.ASCII.GetBytes("hello world");
            byte[] outBytes = c.DoFinal(inBytes);

            pgpPrivKey = sKey.GetSecretKey(pgpKeyID).ExtractPrivateKey(pass);

            c.Init(false, pgpPrivKey.Key);

            outBytes = c.DoFinal(outBytes);

            if (!Arrays.AreEqual(inBytes, outBytes))
            {
                Fail("decryption failed.");
            }

            //
            // encrypted message
            //
            byte[] text = { (byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o',
                            (byte)' ', (byte)'w', (byte)'o', (byte)'r', (byte)'l',(byte)'d',  (byte)'!', (byte)'\n' };

            PgpObjectFactory pgpF = new PgpObjectFactory(encMessage);

            PgpEncryptedDataList encList = (PgpEncryptedDataList)pgpF.NextPgpObject();

            PgpPublicKeyEncryptedData encP = (PgpPublicKeyEncryptedData)encList[0];

            Stream clear = encP.GetDataStream(pgpPrivKey);

            pgpFact = new PgpObjectFactory(clear);

            c1 = (PgpCompressedData)pgpFact.NextPgpObject();

            pgpFact = new PgpObjectFactory(c1.GetDataStream());

            PgpLiteralData ld = (PgpLiteralData)pgpFact.NextPgpObject();

            if (!ld.FileName.Equals("test.txt"))
            {
                throw new Exception("wrong filename in packet");
            }

            Stream inLd = ld.GetDataStream();

            byte[] bytes = Streams.ReadAll(inLd);

            if (!Arrays.AreEqual(bytes, text))
            {
                Fail("wrong plain text in decrypted packet");
            }

            //
            // signed and encrypted message
            //
            pgpF = new PgpObjectFactory(signedAndEncMessage);

            encList = (PgpEncryptedDataList)pgpF.NextPgpObject();

            encP = (PgpPublicKeyEncryptedData)encList[0];

            clear = encP.GetDataStream(pgpPrivKey);

            pgpFact = new PgpObjectFactory(clear);

            c1 = (PgpCompressedData)pgpFact.NextPgpObject();

            pgpFact = new PgpObjectFactory(c1.GetDataStream());

            p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();

            ops = p1[0];

            ld = (PgpLiteralData)pgpFact.NextPgpObject();

            bOut = new MemoryStream();

            if (!ld.FileName.Equals("test.txt"))
            {
                throw new Exception("wrong filename in packet");
            }

            inLd = ld.GetDataStream();

            //
            // note: we use the DSA public key here.
            //
            ops.InitVerify(pgpPub.GetPublicKey());

            while ((ch = inLd.ReadByte()) >= 0)
            {
                ops.Update((byte)ch);
                bOut.WriteByte((byte)ch);
            }

            p3 = (PgpSignatureList)pgpFact.NextPgpObject();

            if (!ops.Verify(p3[0]))
            {
                Fail("Failed signature check");
            }

            if (!Arrays.AreEqual(bOut.ToArray(), text))
            {
                Fail("wrong plain text in decrypted packet");
            }

            //
            // encrypt
            //
            MemoryStream cbOut            = new MemoryStream();
            PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(
                SymmetricKeyAlgorithmTag.TripleDes, random);
            IPgpPublicKey puK = sKey.GetSecretKey(pgpKeyID).PublicKey;

            cPk.AddMethod(puK);

            Stream cOut = cPk.Open(new UncloseableStream(cbOut), bOut.ToArray().Length);

            cOut.Write(text, 0, text.Length);

            cOut.Close();

            pgpF = new PgpObjectFactory(cbOut.ToArray());

            encList = (PgpEncryptedDataList)pgpF.NextPgpObject();

            encP = (PgpPublicKeyEncryptedData)encList[0];

            pgpPrivKey = sKey.GetSecretKey(pgpKeyID).ExtractPrivateKey(pass);

            clear    = encP.GetDataStream(pgpPrivKey);
            outBytes = Streams.ReadAll(clear);

            if (!Arrays.AreEqual(outBytes, text))
            {
                Fail("wrong plain text in Generated packet");
            }

            //
            // use of PgpKeyPair
            //
            IBigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
            IBigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);

            ElGamalParameters elParams = new ElGamalParameters(p, g);

            IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL");

            kpg.Init(new ElGamalKeyGenerationParameters(random, elParams));

            IAsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();

            PgpKeyPair pgpKp = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalGeneral,
                                              kp.Public, kp.Private, DateTime.UtcNow);

            PgpPublicKey  k1 = pgpKp.PublicKey;
            PgpPrivateKey k2 = pgpKp.PrivateKey;



            // Test bug with ElGamal P size != 0 mod 8 (don't use these sizes at home!)
            for (int pSize = 257; pSize < 264; ++pSize)
            {
                // Generate some parameters of the given size
                ElGamalParametersGenerator epg = new ElGamalParametersGenerator();
                epg.Init(pSize, 2, random);

                elParams = epg.GenerateParameters();

                kpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL");
                kpg.Init(new ElGamalKeyGenerationParameters(random, elParams));


                // Run a short encrypt/decrypt test with random key for the given parameters
                kp = kpg.GenerateKeyPair();

                PgpKeyPair elGamalKeyPair = new PgpKeyPair(
                    PublicKeyAlgorithmTag.ElGamalGeneral, kp, DateTime.UtcNow);

                cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, random);

                puK = elGamalKeyPair.PublicKey;

                cPk.AddMethod(puK);

                cbOut = new MemoryStream();

                cOut = cPk.Open(new UncloseableStream(cbOut), text.Length);

                cOut.Write(text, 0, text.Length);

                cOut.Close();

                pgpF = new PgpObjectFactory(cbOut.ToArray());

                encList = (PgpEncryptedDataList)pgpF.NextPgpObject();

                encP = (PgpPublicKeyEncryptedData)encList[0];

                pgpPrivKey = elGamalKeyPair.PrivateKey;

                // Note: This is where an exception would be expected if the P size causes problems
                clear = encP.GetDataStream(pgpPrivKey);
                byte[] decText = Streams.ReadAll(clear);

                if (!Arrays.AreEqual(text, decText))
                {
                    Fail("decrypted message incorrect");
                }
            }


            // check sub key encoding

            foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys())
            {
                if (!pgpKey.IsMasterKey)
                {
                    byte[] kEnc = pgpKey.GetEncoded();

                    PgpObjectFactory objF = new PgpObjectFactory(kEnc);

                    // TODO Make PgpPublicKey a PgpObject or return a PgpPublicKeyRing
//					PgpPublicKey k = (PgpPublicKey)objF.NextPgpObject();
//
//					pKey = k.GetKey();
//					pgpKeyID = k.KeyId;
//					if (k.BitStrength != 1024)
//					{
//						Fail("failed - key strength reported incorrectly.");
//					}
//
//					if (objF.NextPgpObject() != null)
//					{
//						Fail("failed - stream not fully parsed.");
//					}
                }
            }
        }
        /// <summary>
        /// Returns a new key ring with the secret key passed in either added or
        /// replacing an existing one with the same key ID.
        /// </summary>
        /// <param name="secRing">The secret key ring to be modified.</param>
        /// <param name="secKey">The secret key to be inserted.</param>
        /// <returns>A new <c>PgpSecretKeyRing</c></returns>
        public static PgpSecretKeyRing InsertSecretKey(IPgpSecretKeyRing secRing, IPgpSecretKey secKey)
        {
            var keys = Platform.CreateArrayList(secRing.GetSecretKeys());
            var found = false;
            var masterFound = false;

            for (var i = 0; i != keys.Count; i++)
            {
                var key = keys[i];

                if (key.KeyId == secKey.KeyId)
                {
                    found = true;
                    keys[i] = secKey;
                }
                if (key.IsMasterKey)
                {
                    masterFound = true;
                }
            }

            if (!found)
            {
                if (secKey.IsMasterKey)
                {
                    if (masterFound)
                        throw new ArgumentException("cannot add a master key to a ring that already has one");

                    keys.Insert(0, secKey);
                }
                else
                {
                    keys.Add(secKey);
                }
            }

            return new PgpSecretKeyRing(keys, secRing.GetExtraPublicKeys());
        }
Esempio n. 12
0
        public override void PerformTest()
        {
            //
            // Read the public key
            //
            PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(testPubKey);

            var pubKey = pgpPub.GetPublicKey();

            //
            // Read the private key
            //
            PgpSecretKeyRing sKey       = new PgpSecretKeyRing(testPrivKey);
            IPgpSecretKey    secretKey  = sKey.GetSecretKey();
            IPgpPrivateKey   pgpPrivKey = secretKey.ExtractPrivateKey(pass);

            //
            // test signature message
            //
            PgpObjectFactory  pgpFact = new PgpObjectFactory(sig1);
            PgpCompressedData c1      = (PgpCompressedData)pgpFact.NextPgpObject();

            pgpFact = new PgpObjectFactory(c1.GetDataStream());

            PgpOnePassSignatureList p1  = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
            PgpOnePassSignature     ops = p1[0];

            PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();

            Stream dIn = p2.GetInputStream();

            ops.InitVerify(pubKey);

            int ch;

            while ((ch = dIn.ReadByte()) >= 0)
            {
                ops.Update((byte)ch);
            }

            PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();

            if (!ops.Verify(p3[0]))
            {
                Fail("Failed signature check");
            }

            //
            // signature generation
            //
            GenerateTest(sKey, pubKey, pgpPrivKey);

            //
            // signature generation - canonical text
            //
            const string data = "hello world!";

            byte[]                dataBytes = Encoding.ASCII.GetBytes(data);
            MemoryStream          bOut      = new MemoryStream();
            MemoryStream          testIn    = new MemoryStream(dataBytes, false);
            PgpSignatureGenerator sGen      = new PgpSignatureGenerator(
                PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey);

            PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator(
                CompressionAlgorithmTag.Zip);

            BcpgOutputStream bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut)));

            sGen.GenerateOnePassVersion(false).Encode(bcOut);

            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
            DateTime testDateTime        = new DateTime(1973, 7, 27);
            Stream   lOut = lGen.Open(
                new UncloseableStream(bcOut),
                PgpLiteralData.Text,
                "_CONSOLE",
                dataBytes.Length,
                testDateTime);

            while ((ch = testIn.ReadByte()) >= 0)
            {
                lOut.WriteByte((byte)ch);
                sGen.Update((byte)ch);
            }

            lGen.Close();

            sGen.Generate().Encode(bcOut);

            cGen.Close();

            //
            // verify Generated signature - canconical text
            //
            pgpFact = new PgpObjectFactory(bOut.ToArray());

            c1 = (PgpCompressedData)pgpFact.NextPgpObject();

            pgpFact = new PgpObjectFactory(c1.GetDataStream());

            p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();

            ops = p1[0];

            p2 = (PgpLiteralData)pgpFact.NextPgpObject();
            if (!p2.ModificationTime.Equals(testDateTime))
            {
                Fail("Modification time not preserved");
            }

            dIn = p2.GetInputStream();

            ops.InitVerify(pubKey);

            while ((ch = dIn.ReadByte()) >= 0)
            {
                ops.Update((byte)ch);
            }

            p3 = (PgpSignatureList)pgpFact.NextPgpObject();

            if (!ops.Verify(p3[0]))
            {
                Fail("Failed generated signature check");
            }

            //
            // Read the public key with user attributes
            //
            pgpPub = new PgpPublicKeyRing(testPubWithUserAttr);

            pubKey = pgpPub.GetPublicKey();

            int count = 0;

            foreach (PgpUserAttributeSubpacketVector attributes in pubKey.GetUserAttributes())
            {
                int sigCount = 0;
                foreach (object sigs in pubKey.GetSignaturesForUserAttribute(attributes))
                {
                    if (sigs == null)
                    {
                        Fail("null signature found");
                    }

                    sigCount++;
                }

                if (sigCount != 1)
                {
                    Fail("Failed user attributes signature check");
                }

                count++;
            }

            if (count != 1)
            {
                Fail("Failed user attributes check");
            }

            byte[] pgpPubBytes = pgpPub.GetEncoded();
            pgpPub = new PgpPublicKeyRing(pgpPubBytes);
            pubKey = pgpPub.GetPublicKey();
            count  = 0;

            foreach (object ua in pubKey.GetUserAttributes())
            {
                if (ua == null)
                {
                    Fail("null user attribute found");
                }

                count++;
            }

            if (count != 1)
            {
                Fail("Failed user attributes reread");
            }

            //
            // reading test extra data - key with edge condition for DSA key password.
            //
            char[] passPhrase = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };

            sKey       = new PgpSecretKeyRing(testPrivKey2);
            pgpPrivKey = sKey.GetSecretKey().ExtractPrivateKey(passPhrase);

            //
            // reading test - aes256 encrypted passphrase.
            //
            sKey       = new PgpSecretKeyRing(aesSecretKey);
            pgpPrivKey = sKey.GetSecretKey().ExtractPrivateKey(pass);

            //
            // reading test - twofish encrypted passphrase.
            //
            sKey       = new PgpSecretKeyRing(twofishSecretKey);
            pgpPrivKey = sKey.GetSecretKey().ExtractPrivateKey(pass);

            //
            // use of PgpKeyPair
            //
            DsaParametersGenerator pGen = new DsaParametersGenerator();

            pGen.Init(512, 80, new SecureRandom()); // TODO Is the certainty okay?
            DsaParameters dsaParams = pGen.GenerateParameters();
            DsaKeyGenerationParameters        kgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams);
            IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("DSA");

            kpg.Init(kgp);


            IAsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();

            PgpKeyPair pgpKp = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa,
                                              kp.Public, kp.Private, DateTime.UtcNow);

            PgpPublicKey  k1 = pgpKp.PublicKey;
            PgpPrivateKey k2 = pgpKp.PrivateKey;
        }
Esempio n. 13
0
        public override void PerformTest()
        {
            //
            // RSA tests
            //
            PgpSecretKeyRing pgpPriv    = new PgpSecretKeyRing(rsaKeyRing);
            IPgpSecretKey    secretKey  = pgpPriv.GetSecretKey();
            IPgpPrivateKey   pgpPrivKey = secretKey.ExtractPrivateKey(rsaPass);

            try
            {
                doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);

                Fail("RSA wrong key test failed.");
            }
            catch (PgpException)
            {
                // expected
            }

            try
            {
                doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);

                Fail("RSA V3 wrong key test failed.");
            }
            catch (PgpException)
            {
                // expected
            }

            //
            // certifications
            //
            PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.KeyRevocation, pgpPrivKey);

            PgpSignature sig = sGen.GenerateCertification(secretKey.PublicKey);

            sig.InitVerify(secretKey.PublicKey);

            if (!sig.VerifyCertification(secretKey.PublicKey))
            {
                Fail("revocation verification failed.");
            }

            PgpSecretKeyRing pgpDSAPriv    = new PgpSecretKeyRing(dsaKeyRing);
            IPgpSecretKey    secretDSAKey  = pgpDSAPriv.GetSecretKey();
            IPgpPrivateKey   pgpPrivDSAKey = secretDSAKey.ExtractPrivateKey(dsaPass);

            sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);

            PgpSignatureSubpacketGenerator unhashedGen = new PgpSignatureSubpacketGenerator();
            PgpSignatureSubpacketGenerator hashedGen   = new PgpSignatureSubpacketGenerator();

            hashedGen.SetSignatureExpirationTime(false, TEST_EXPIRATION_TIME);
            hashedGen.SetSignerUserId(true, TEST_USER_ID);
            hashedGen.SetPreferredCompressionAlgorithms(false, PREFERRED_COMPRESSION_ALGORITHMS);
            hashedGen.SetPreferredHashAlgorithms(false, PREFERRED_HASH_ALGORITHMS);
            hashedGen.SetPreferredSymmetricAlgorithms(false, PREFERRED_SYMMETRIC_ALGORITHMS);

            sGen.SetHashedSubpackets(hashedGen.Generate());
            sGen.SetUnhashedSubpackets(unhashedGen.Generate());

            sig = sGen.GenerateCertification(secretDSAKey.PublicKey, secretKey.PublicKey);

            byte[] sigBytes = sig.GetEncoded();

            PgpObjectFactory f = new PgpObjectFactory(sigBytes);

            sig = ((PgpSignatureList)f.NextPgpObject())[0];

            sig.InitVerify(secretDSAKey.PublicKey);

            if (!sig.VerifyCertification(secretDSAKey.PublicKey, secretKey.PublicKey))
            {
                Fail("subkey binding verification failed.");
            }

            var hashedPcks   = sig.GetHashedSubPackets();
            var unhashedPcks = sig.GetUnhashedSubPackets();

            if (hashedPcks.Count != 6)
            {
                Fail("wrong number of hashed packets found.");
            }

            if (unhashedPcks.Count != 1)
            {
                Fail("wrong number of unhashed packets found.");
            }

            if (!hashedPcks.GetSignerUserId().Equals(TEST_USER_ID))
            {
                Fail("test userid not matching");
            }

            if (hashedPcks.GetSignatureExpirationTime() != TEST_EXPIRATION_TIME)
            {
                Fail("test signature expiration time not matching");
            }

            if (unhashedPcks.GetIssuerKeyId() != secretDSAKey.KeyId)
            {
                Fail("wrong issuer key ID found in certification");
            }

            int[] prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms();
            preferredAlgorithmCheck("compression", PREFERRED_COMPRESSION_ALGORITHMS, prefAlgs);

            prefAlgs = hashedPcks.GetPreferredHashAlgorithms();
            preferredAlgorithmCheck("hash", PREFERRED_HASH_ALGORITHMS, prefAlgs);

            prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms();
            preferredAlgorithmCheck("symmetric", PREFERRED_SYMMETRIC_ALGORITHMS, prefAlgs);

            SignatureSubpacketTag[] criticalHashed = hashedPcks.GetCriticalTags();

            if (criticalHashed.Length != 1)
            {
                Fail("wrong number of critical packets found.");
            }

            if (criticalHashed[0] != SignatureSubpacketTag.SignerUserId)
            {
                Fail("wrong critical packet found in tag list.");
            }

            //
            // no packets passed
            //
            sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);

            sGen.SetHashedSubpackets(null);
            sGen.SetUnhashedSubpackets(null);

            sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey);

            sig.InitVerify(secretDSAKey.PublicKey);

            if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey))
            {
                Fail("subkey binding verification failed.");
            }

            hashedPcks = sig.GetHashedSubPackets();

            if (hashedPcks.Count != 1)
            {
                Fail("found wrong number of hashed packets");
            }

            unhashedPcks = sig.GetUnhashedSubPackets();

            if (unhashedPcks.Count != 1)
            {
                Fail("found wrong number of unhashed packets");
            }

            try
            {
                sig.VerifyCertification(secretKey.PublicKey);

                Fail("failed to detect non-key signature.");
            }
            catch (InvalidOperationException)
            {
                // expected
            }

            //
            // override hash packets
            //
            sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);

            hashedGen = new PgpSignatureSubpacketGenerator();

            DateTime creationTime = new DateTime(1973, 7, 27);

            hashedGen.SetSignatureCreationTime(false, creationTime);

            sGen.SetHashedSubpackets(hashedGen.Generate());

            sGen.SetUnhashedSubpackets(null);

            sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey);

            sig.InitVerify(secretDSAKey.PublicKey);

            if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey))
            {
                Fail("subkey binding verification failed.");
            }

            hashedPcks = sig.GetHashedSubPackets();

            if (hashedPcks.Count != 1)
            {
                Fail("found wrong number of hashed packets in override test");
            }

            if (!hashedPcks.HasSubpacket(SignatureSubpacketTag.CreationTime))
            {
                Fail("hasSubpacket test for creation time failed");
            }

            DateTime sigCreationTime = hashedPcks.GetSignatureCreationTime();

            if (!sigCreationTime.Equals(creationTime))
            {
                Fail("creation of overridden date failed.");
            }

            prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms();
            preferredAlgorithmCheck("compression", NO_PREFERENCES, prefAlgs);

            prefAlgs = hashedPcks.GetPreferredHashAlgorithms();
            preferredAlgorithmCheck("hash", NO_PREFERENCES, prefAlgs);

            prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms();
            preferredAlgorithmCheck("symmetric", NO_PREFERENCES, prefAlgs);

            if (hashedPcks.GetKeyExpirationTime() != 0)
            {
                Fail("unexpected key expiration time found");
            }

            if (hashedPcks.GetSignatureExpirationTime() != 0)
            {
                Fail("unexpected signature expiration time found");
            }

            if (hashedPcks.GetSignerUserId() != null)
            {
                Fail("unexpected signer user ID found");
            }

            criticalHashed = hashedPcks.GetCriticalTags();

            if (criticalHashed.Length != 0)
            {
                Fail("critical packets found when none expected");
            }

            unhashedPcks = sig.GetUnhashedSubPackets();

            if (unhashedPcks.Count != 1)
            {
                Fail("found wrong number of unhashed packets in override test");
            }

            //
            // general signatures
            //
            doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha256, secretKey.PublicKey, pgpPrivKey);
            doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha384, secretKey.PublicKey, pgpPrivKey);
            doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha512, secretKey.PublicKey, pgpPrivKey);
            doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
            doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
            doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
            doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
            doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);

            //
            // DSA Tests
            //
            pgpPriv    = new PgpSecretKeyRing(dsaKeyRing);
            secretKey  = pgpPriv.GetSecretKey();
            pgpPrivKey = secretKey.ExtractPrivateKey(dsaPass);

            try
            {
                doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);

                Fail("DSA wrong key test failed.");
            }
            catch (PgpException)
            {
                // expected
            }

            try
            {
                doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);

                Fail("DSA V3 wrong key test failed.");
            }
            catch (PgpException)
            {
                // expected
            }

            doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
            doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
            doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
            doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
            doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
            doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);

            // special cases
            //
            doTestMissingSubpackets(nullPacketsSubKeyBinding);

            doTestMissingSubpackets(generateV3BinarySig(pgpPrivKey, PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1));

            // keyflags
            doTestKeyFlagsValues();
        }
        /**
         * Generate an encapsulated signed file.
         *
         * @param fileName
         * @param keyIn
         * @param outputStream
         * @param pass
         * @param armor
         */
        private static void SignFile(
            string fileName,
            Stream keyIn,
            Stream outputStream,
            char[]      pass,
            bool armor,
            bool compress)
        {
            if (armor)
            {
                outputStream = new ArmoredOutputStream(outputStream);
            }

            IPgpSecretKey         pgpSec     = PgpExampleUtilities.ReadSecretKey(keyIn);
            IPgpPrivateKey        pgpPrivKey = pgpSec.ExtractPrivateKey(pass);
            PgpSignatureGenerator sGen       = new PgpSignatureGenerator(pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
            foreach (string userId in pgpSec.PublicKey.GetUserIds())
            {
                PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();
                spGen.SetSignerUserId(false, userId);
                sGen.SetHashedSubpackets(spGen.Generate());
                // Just the first one!
                break;
            }

            Stream cOut = outputStream;
            PgpCompressedDataGenerator cGen = null;

            if (compress)
            {
                cGen = new PgpCompressedDataGenerator(CompressionAlgorithmTag.ZLib);

                cOut = cGen.Open(cOut);
            }

            BcpgOutputStream bOut = new BcpgOutputStream(cOut);

            sGen.GenerateOnePassVersion(false).Encode(bOut);

            FileInfo file = new FileInfo(fileName);
            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
            Stream     lOut = lGen.Open(bOut, PgpLiteralData.Binary, file);
            FileStream fIn  = file.OpenRead();
            int        ch   = 0;

            while ((ch = fIn.ReadByte()) >= 0)
            {
                lOut.WriteByte((byte)ch);
                sGen.Update((byte)ch);
            }

            fIn.Close();
            lGen.Close();

            sGen.Generate().Encode(bOut);

            if (cGen != null)
            {
                cGen.Close();
            }

            if (armor)
            {
                outputStream.Close();
            }
        }
        /*
         * create a clear text signed file.
         */
        private static void SignFile(
            string fileName,
            Stream keyIn,
            Stream outputStream,
            char[]      pass,
            string digestName)
        {
            HashAlgorithmTag digest;

            if (digestName.Equals("SHA256"))
            {
                digest = HashAlgorithmTag.Sha256;
            }
            else if (digestName.Equals("SHA384"))
            {
                digest = HashAlgorithmTag.Sha384;
            }
            else if (digestName.Equals("SHA512"))
            {
                digest = HashAlgorithmTag.Sha512;
            }
            else if (digestName.Equals("MD5"))
            {
                digest = HashAlgorithmTag.MD5;
            }
            else if (digestName.Equals("RIPEMD160"))
            {
                digest = HashAlgorithmTag.RipeMD160;
            }
            else
            {
                digest = HashAlgorithmTag.Sha1;
            }

            IPgpSecretKey                  pgpSecKey  = PgpExampleUtilities.ReadSecretKey(keyIn);
            IPgpPrivateKey                 pgpPrivKey = pgpSecKey.ExtractPrivateKey(pass);
            PgpSignatureGenerator          sGen       = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, digest);
            PgpSignatureSubpacketGenerator spGen      = new PgpSignatureSubpacketGenerator();

            sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey);

            IEnumerator enumerator = pgpSecKey.PublicKey.GetUserIds().GetEnumerator();

            if (enumerator.MoveNext())
            {
                spGen.SetSignerUserId(false, (string)enumerator.Current);
                sGen.SetHashedSubpackets(spGen.Generate());
            }

            Stream fIn = File.OpenRead(fileName);
            ArmoredOutputStream aOut = new ArmoredOutputStream(outputStream);

            aOut.BeginClearText(digest);

            //
            // note the last \n/\r/\r\n in the file is ignored
            //
            MemoryStream lineOut   = new MemoryStream();
            int          lookAhead = ReadInputLine(lineOut, fIn);

            ProcessLine(aOut, sGen, lineOut.ToArray());

            if (lookAhead != -1)
            {
                do
                {
                    lookAhead = ReadInputLine(lineOut, lookAhead, fIn);

                    sGen.Update((byte)'\r');
                    sGen.Update((byte)'\n');

                    ProcessLine(aOut, sGen, lineOut.ToArray());
                }while (lookAhead != -1);
            }

            fIn.Close();

            aOut.EndClearText();

            BcpgOutputStream bOut = new BcpgOutputStream(aOut);

            sGen.Generate().Encode(bOut);

            aOut.Close();
        }
        private static byte[] SignPublicKey(
			IPgpSecretKey	secretKey,
			string			secretKeyPass,
			IPgpPublicKey	keyToBeSigned,
			string			notationName,
			string			notationValue,
			bool			armor)
        {
            Stream os = new MemoryStream();
            if (armor)
            {
                os = new ArmoredOutputStream(os);
            }

            IPgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(
                secretKeyPass.ToCharArray());

            PgpSignatureGenerator sGen = new PgpSignatureGenerator(
                secretKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);

            sGen.InitSign(PgpSignature.DirectKey, pgpPrivKey);

            BcpgOutputStream bOut = new BcpgOutputStream(os);

            sGen.GenerateOnePassVersion(false).Encode(bOut);

            PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();

            bool isHumanReadable = true;

            spGen.SetNotationData(true, isHumanReadable, notationName, notationValue);

            PgpSignatureSubpacketVector packetVector = spGen.Generate();
            sGen.SetHashedSubpackets(packetVector);

            bOut.Flush();

            if (armor)
            {
                os.Close();
            }

            return PgpPublicKey.AddCertification(keyToBeSigned, sGen.Generate()).GetEncoded();
        }