private static void ProcessLine(
			PgpSignature	sig,
			byte[]			line)
		{
			int length = GetLengthWithoutWhiteSpace(line);
			if (length > 0)
			{
				sig.Update(line, 0, length);
			}
		}
Ejemplo n.º 2
0
        /*
         * decrypt a given stream.
         */

        public static void Decrypt(Stream inputStream, Stream privateKeyStream, string passPhrase, string outputFile, Stream publicKeyStream)
        {
            try
            {
                bool deleteOutputFile = false;

                PgpEncryptedDataList      enc;
                PgpObject                 o    = null;
                PgpPrivateKey             sKey = null;
                PgpPublicKeyEncryptedData pbe  = null;

                var pgpF = new PgpObjectFactory(PgpUtilities.GetDecoderStream(inputStream));
                // find secret key
                var pgpSec = new PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(privateKeyStream));

                if (pgpF != null)
                {
                    o = pgpF.NextPgpObject();
                }

                // the first object might be a PGP marker packet.
                if (o is PgpEncryptedDataList)
                {
                    enc = (PgpEncryptedDataList)o;
                }
                else
                {
                    enc = (PgpEncryptedDataList)pgpF.NextPgpObject();
                }

                // decrypt
                foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects())
                {
                    sKey = FindSecretKey(pgpSec, pked.KeyId, passPhrase.ToCharArray());

                    if (sKey != null)
                    {
                        pbe = pked;
                        break;
                    }
                }

                if (sKey == null)
                {
                    throw new ArgumentException("Secret key for message not found.");
                }

                PgpObjectFactory plainFact = null;

                using (Stream clear = pbe.GetDataStream(sKey))
                {
                    plainFact = new PgpObjectFactory(clear);
                }

                PgpObject message = plainFact.NextPgpObject();

                if (message is PgpCompressedData)
                {
                    PgpCompressedData cData = (PgpCompressedData)message;
                    PgpObjectFactory  of    = null;

                    using (Stream compDataIn = cData.GetDataStream())
                    {
                        of = new PgpObjectFactory(compDataIn);
                    }

                    message = of.NextPgpObject();
                    if (message is PgpOnePassSignatureList)
                    {
                        PgpOnePassSignature ops = ((PgpOnePassSignatureList)message)[0];

                        PgpPublicKeyRingBundle pgpRing = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(publicKeyStream));

                        //USE THE BELOW TO CHECK FOR A FAILING SIGNATURE VERIFICATION.
                        //THE CERTIFICATE MATCHING THE KEY ID MUST BE IN THE PUBLIC KEY RING.
                        //long fakeKeyId = 3008998260528343108L;
                        //PgpPublicKey key = pgpRing.GetPublicKey(fakeKeyId);

                        PgpPublicKey key = pgpRing.GetPublicKey(ops.KeyId);

                        ops.InitVerify(key);

                        message = of.NextPgpObject();
                        PgpLiteralData Ld = null;
                        Ld = (PgpLiteralData)message;

                        //THE OUTPUT FILENAME WILL BE BASED ON THE INPUT PARAMETER VALUE TO THIS METHOD. IF YOU WANT TO KEEP THE
                        //ORIGINAL FILENAME, UNCOMMENT THE FOLLOWING LINE.
                        //if (!String.IsNullOrEmpty(Ld.FileName))
                        //    outputFile = Ld.FileName;

                        using (Stream output = File.Create(outputFile))
                        {
                            Stream dIn = Ld.GetInputStream();

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

                        PgpSignatureList p3       = (PgpSignatureList)of.NextPgpObject();
                        PgpSignature     firstSig = p3[0];
                        if (ops.Verify(firstSig))
                        {
                            Console.Out.WriteLine("signature verified.");
                        }
                        else
                        {
                            Console.Out.WriteLine("signature verification failed.");

                            //YOU MAY OPT TO DELETE THE OUTPUT FILE IN THE EVENT THAT VERIFICATION FAILS.
                            //FILE DELETION HAPPENS FURTHER DOWN IN THIS METHOD
                            //AN ALTERNATIVE IS TO LOG THESE VERIFICATION FAILURE MESSAGES, BUT KEEP THE OUTPUT FILE FOR FURTHER ANALYSIS
                            //deleteOutputFile = true;
                        }
                    }
                    else
                    {
                        PgpLiteralData Ld = null;
                        Ld = (PgpLiteralData)message;
                        using (Stream output = File.Create(outputFile))
                        {
                            Stream unc = Ld.GetInputStream();
                            Streams.PipeAll(unc, output);
                        }
                    }
                }
                else if (message is PgpLiteralData)
                {
                    PgpLiteralData ld          = (PgpLiteralData)message;
                    string         outFileName = ld.FileName;

                    using (Stream fOut = File.Create(outFileName))
                    {
                        Stream unc = ld.GetInputStream();
                        Streams.PipeAll(unc, fOut);
                    }
                }
                else if (message is PgpOnePassSignatureList)
                {
                    throw new PgpException("Encrypted message contains a signed message - not literal data.");
                }
                else
                {
                    throw new PgpException("Message is not a simple encrypted file - type unknown.");
                }

                #region commented code

                if (pbe.IsIntegrityProtected())
                {
                    if (!pbe.Verify())
                    {
                        //msg = "message failed integrity check.";
                        Console.Error.WriteLine("message failed integrity check");

                        //YOU MAY OPT TO DELETE THE OUTPUT FILE IN THE EVENT THAT THE INTEGRITY PROTECTION CHECK FAILS.
                        //FILE DELETION HAPPENS FURTHER DOWN IN THIS METHOD.
                        //AN ALTERNATIVE IS TO LOG THESE VERIFICATION FAILURE MESSAGES, BUT KEEP THE OUTPUT FILE FOR FURTHER ANALYSIS
                        //deleteOutputFile = true;
                    }
                    else
                    {
                        //msg = "message integrity check passed.";
                        Console.Error.WriteLine("message integrity check passed");
                    }
                }
                else
                {
                    //msg = "no message integrity check.";
                    Console.Error.WriteLine("no message integrity check");
                }

                if (deleteOutputFile)
                {
                    File.Delete(outputFile);
                }

                #endregion commented code
            }
            catch (PgpException ex)
            {
                throw;
            }
        }
Ejemplo n.º 3
0
 private static bool IsGoodUidSignature(PgpSignature sig, PgpPublicKey masterpk, string uid)
 {
     sig.InitVerify(masterpk);
     return sig.VerifyCertification(uid, masterpk);
 }
        /*
         * verify a clear text signed file
         */
        private static void VerifyFile(
            Stream inputStream,
            Stream keyIn,
            string resultName)
        {
            ArmoredInputStream aIn    = new ArmoredInputStream(inputStream);
            Stream             outStr = File.Create(resultName);

            //
            // write out signed section using the local line separator.
            // note: trailing white space needs to be removed from the end of
            // each line RFC 4880 Section 7.1
            //
            MemoryStream lineOut   = new MemoryStream();
            int          lookAhead = ReadInputLine(lineOut, aIn);

            byte[] lineSep = LineSeparator;

            if (lookAhead != -1 && aIn.IsClearText())
            {
                byte[] line = lineOut.ToArray();
                outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line));
                outStr.Write(lineSep, 0, lineSep.Length);

                while (lookAhead != -1 && aIn.IsClearText())
                {
                    lookAhead = ReadInputLine(lineOut, lookAhead, aIn);

                    line = lineOut.ToArray();
                    outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line));
                    outStr.Write(lineSep, 0, lineSep.Length);
                }
            }

            outStr.Close();

            PgpPublicKeyRingBundle pgpRings = new PgpPublicKeyRingBundle(keyIn);

            PgpObjectFactory pgpFact = new PgpObjectFactory(aIn);
            PgpSignatureList p3      = (PgpSignatureList)pgpFact.NextPgpObject();
            PgpSignature     sig     = p3[0];

            sig.InitVerify(pgpRings.GetPublicKey(sig.KeyId));

            //
            // read the input, making sure we ignore the last newline.
            //
            Stream sigIn = File.OpenRead(resultName);

            lookAhead = ReadInputLine(lineOut, sigIn);

            ProcessLine(sig, lineOut.ToArray());

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

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

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

            sigIn.Close();

            if (sig.Verify())
            {
                Console.WriteLine("signature verified.");
            }
            else
            {
                Console.WriteLine("signature verification failed.");
            }
        }
        private void messageTest(
            string message,
            string type)
        {
            ArmoredInputStream aIn = new ArmoredInputStream(
                new MemoryStream(Encoding.ASCII.GetBytes(message)));

            string[] headers = aIn.GetArmorHeaders();

            if (headers == null || headers.Length != 1)
            {
                Fail("wrong number of headers found");
            }

            if (!"Hash: SHA256".Equals(headers[0]))
            {
                Fail("header value wrong: " + headers[0]);
            }

            //
            // read the input, making sure we ingore the last newline.
            //
            MemoryStream bOut = new MemoryStream();
            int          ch;

            while ((ch = aIn.ReadByte()) >= 0 && aIn.IsClearText())
            {
                bOut.WriteByte((byte)ch);
            }

            PgpPublicKeyRingBundle pgpRings = new PgpPublicKeyRingBundle(publicKey);

            PgpObjectFactory pgpFact = new PgpObjectFactory(aIn);
            PgpSignatureList p3      = (PgpSignatureList)pgpFact.NextPgpObject();
            PgpSignature     sig     = p3[0];

            sig.InitVerify(pgpRings.GetPublicKey(sig.KeyId));

            MemoryStream lineOut   = new MemoryStream();
            Stream       sigIn     = new MemoryStream(bOut.ToArray(), false);
            int          lookAhead = ReadInputLine(lineOut, sigIn);

            ProcessLine(sig, lineOut.ToArray());

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

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

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

            if (!sig.Verify())
            {
                Fail("signature failed to verify m_in " + type);
            }
        }
Ejemplo n.º 6
0
 internal OpenPgpDigitalSignature(PgpPublicKeyRing keyring, PgpPublicKey pubkey, PgpSignature signature)
 {
     SignerCertificate = pubkey != null ? new OpenPgpDigitalCertificate(keyring, pubkey) : null;
     Signature         = signature;
 }
Ejemplo n.º 7
0
        private void GenerateAndSign()
        {
            SecureRandom random = SecureRandom.GetInstance("SHA1PRNG");

            IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
            keyGen.Init(new ECKeyGenerationParameters(SecObjectIdentifiers.SecP256r1, random));

            AsymmetricCipherKeyPair kpSign = keyGen.GenerateKeyPair();

            PgpKeyPair ecdsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ECDsa, kpSign, DateTime.UtcNow);

            byte[] msg = Encoding.ASCII.GetBytes("hello world!");

            //
            // try a signature
            //
            PgpSignatureGenerator signGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.ECDsa, HashAlgorithmTag.Sha256);
            signGen.InitSign(PgpSignature.BinaryDocument, ecdsaKeyPair.PrivateKey);

            signGen.Update(msg);

            PgpSignature sig = signGen.Generate();

            sig.InitVerify(ecdsaKeyPair.PublicKey);
            sig.Update(msg);

            if (!sig.Verify())
            {
                Fail("signature failed to verify!");
            }

            //
            // generate a key ring
            //
            char[] passPhrase = "test".ToCharArray();
            PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, ecdsaKeyPair,
                "*****@*****.**", SymmetricKeyAlgorithmTag.Aes256, passPhrase, true, null, null, random);

            PgpPublicKeyRing pubRing = keyRingGen.GeneratePublicKeyRing();
            PgpSecretKeyRing secRing = keyRingGen.GenerateSecretKeyRing();

            PgpPublicKeyRing pubRingEnc = new PgpPublicKeyRing(pubRing.GetEncoded());
            if (!Arrays.AreEqual(pubRing.GetEncoded(), pubRingEnc.GetEncoded()))
            {
                Fail("public key ring encoding failed");
            }

            PgpSecretKeyRing secRingEnc = new PgpSecretKeyRing(secRing.GetEncoded());
            if (!Arrays.AreEqual(secRing.GetEncoded(), secRingEnc.GetEncoded()))
            {
                Fail("secret key ring encoding failed");
            }


            //
            // try a signature using encoded key
            //
            signGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.ECDsa, HashAlgorithmTag.Sha256);
            signGen.InitSign(PgpSignature.BinaryDocument, secRing.GetSecretKey().ExtractPrivateKey(passPhrase));
            signGen.Update(msg);

            sig = signGen.Generate();
            sig.InitVerify(secRing.GetSecretKey().PublicKey);
            sig.Update(msg);

            if (!sig.Verify())
            {
                Fail("re-encoded signature failed to verify!");
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Verifies clear text PGP signature. See documentation at https://github.com/CommunityHiQ/Frends.Community.PgpVerifyClearTextSignature Returns: Object {string FilePath, Boolean Verified}
        /// </summary>
        public static Result PGPVerifyClearTextSignFile(Input input)
        {
            using (var inStr = File.OpenRead(input.InputFile))
                using (var outStr = File.Create(input.OutputFile))
                    using (var keyStr = PgpUtilities.GetDecoderStream(File.OpenRead(input.PublicKeyFile)))
                    {
                        ArmoredInputStream aInputStr = new ArmoredInputStream(inStr);

                        //
                        // write out signed section using the local line separator.
                        // note: trailing white space needs to be removed from the end of
                        // each line RFC 4880 Section 7.1
                        //
                        MemoryStream lineOut   = new MemoryStream();
                        int          lookAhead = ReadInputLine(lineOut, aInputStr);
                        byte[]       lineSep   = Encoding.ASCII.GetBytes(Environment.NewLine);;


                        if (lookAhead != -1 && aInputStr.IsClearText())
                        {
                            byte[] line = lineOut.ToArray();
                            outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line));
                            outStr.Write(lineSep, 0, lineSep.Length);

                            while (lookAhead != -1 && aInputStr.IsClearText())
                            {
                                lookAhead = ReadInputLine(lineOut, lookAhead, aInputStr);

                                line = lineOut.ToArray();
                                outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line));
                                outStr.Write(lineSep, 0, lineSep.Length);
                            }
                        }
                        else
                        {
                            // a single line file
                            if (lookAhead != -1)
                            {
                                byte[] line = lineOut.ToArray();
                                outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line));
                                outStr.Write(lineSep, 0, lineSep.Length);
                            }
                        }
                        outStr.Close();

                        PgpPublicKeyRingBundle pgpRings = new PgpPublicKeyRingBundle(keyStr);

                        PgpObjectFactory pgpFact = new PgpObjectFactory(aInputStr);
                        PgpSignatureList p3      = (PgpSignatureList)pgpFact.NextPgpObject();
                        PgpSignature     sig     = p3[0];
                        inStr.Close();


                        sig.InitVerify(pgpRings.GetPublicKey(sig.KeyId));
                        // read the input, making sure we ignore the last newline.
                        bool verified = false;
                        using (var sigIn = File.OpenRead(input.OutputFile))
                        {
                            lookAhead = ReadInputLine(lineOut, sigIn);
                            ProcessLine(sig, lineOut.ToArray());
                            if (lookAhead != -1)
                            {
                                do
                                {
                                    lookAhead = ReadInputLine(lineOut, lookAhead, sigIn);

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

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

                            verified = sig.Verify();
                            sigIn.Close();
                        }
                        Result ret = new Result
                        {
                            FilePath = input.OutputFile,
                            Verified = verified
                        };

                        return(ret);
                    }
        }
        /// <summary>
        /// Verifies a PGP signature. See documentation at https://github.com/CommunityHiQ/Frends.Community.PgpVerifySignature Returns: Object {string FilePath, Boolean Verified}
        /// </summary>
        public static Result PGPVerifySignFile(Input input)
        {
            using (var inputStream = PgpUtilities.GetDecoderStream(File.OpenRead(input.InputFile)))
                using (var keyStream = PgpUtilities.GetDecoderStream(File.OpenRead(input.PublicKeyFile)))
                {
                    PgpObjectFactory        pgpFact          = new PgpObjectFactory(inputStream);
                    PgpOnePassSignatureList signatureList    = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
                    PgpOnePassSignature     onePassSignature = signatureList[0];

                    PgpLiteralData         p2      = (PgpLiteralData)pgpFact.NextPgpObject();
                    Stream                 dataIn  = p2.GetInputStream();
                    PgpPublicKeyRingBundle pgpRing = new PgpPublicKeyRingBundle(keyStream);
                    PgpPublicKey           key     = pgpRing.GetPublicKey(onePassSignature.KeyId);

                    string outputPath;
                    if (String.IsNullOrWhiteSpace(input.OutputFolder))
                    {
                        outputPath = Path.Combine(Path.GetDirectoryName(input.InputFile), p2.FileName);
                    }
                    else
                    {
                        outputPath = Path.Combine(input.OutputFolder, p2.FileName);
                    }
                    using (var outputStream = File.Create(outputPath))
                    {
                        onePassSignature.InitVerify(key);

                        int ch;
                        while ((ch = dataIn.ReadByte()) >= 0)
                        {
                            onePassSignature.Update((byte)ch);
                            outputStream.WriteByte((byte)ch);
                        }
                        outputStream.Close();
                    }

                    bool verified;
                    // Will throw Exception if file is altered
                    try
                    {
                        PgpSignatureList p3       = (PgpSignatureList)pgpFact.NextPgpObject();
                        PgpSignature     firstSig = p3[0];
                        verified = onePassSignature.Verify(firstSig);
                    }
                    catch (Exception)
                    {
                        Result retError = new Result
                        {
                            FilePath = input.OutputFolder,
                            Verified = false
                        };

                        return(retError);
                    }

                    Result ret = new Result
                    {
                        FilePath = outputPath,
                        Verified = verified
                    };

                    return(ret);
                }
        }
Ejemplo n.º 10
0
        public override void PerformTest()
        {
            //
            // RSA tests
            //
            PgpSecretKeyRing pgpPriv    = new PgpSecretKeyRing(rsaKeyRing);
            PgpSecretKey     secretKey  = pgpPriv.GetSecretKey();
            PgpPrivateKey    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);
            PgpSecretKey     secretDSAKey  = pgpDSAPriv.GetSecretKey();
            PgpPrivateKey    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.");
            }

            PgpSignatureSubpacketVector hashedPcks   = sig.GetHashedSubPackets();
            PgpSignatureSubpacketVector 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();

            // TODO Seems to depend on some other functionality that's yet to be ported
            //doTestUserAttributeEncoding();
        }