/// <summary>Add a revocation or some other key certification to a key.</summary>
        /// <param name="key">The key the revocation is to be added to.</param>
        /// <param name="certification">The key signature to be added.</param>
        /// <returns>The new changed public key object.</returns>
        public static PgpPublicKey AddCertification(IPgpPublicKey key, PgpSignature certification)
        {
            if (key.IsMasterKey)
            {
                if (certification.SignatureType == PgpSignature.SubkeyRevocation)
                {
                    throw new ArgumentException("signature type incorrect for master key revocation.");
                }
            }
            else
            {
                if (certification.SignatureType == PgpSignature.KeyRevocation)
                {
                    throw new ArgumentException("signature type incorrect for sub-key revocation.");
                }
            }

            var returnKey = new PgpPublicKey(key);

            if (returnKey.SubSigs != null)
            {
                returnKey.SubSigs.Add(certification);
            }
            else
            {
                returnKey.KeySigs.Add(certification);
            }

            return(returnKey);
        }
        private static PgpPublicKey AddCert(IPgpPublicKey key, object id, IPgpSignature certification)
        {
            var returnKey = new PgpPublicKey(key);
            IList <IPgpSignature> sigList = null;

            for (var i = 0; i != returnKey.Ids.Count; i++)
            {
                if (id.Equals(returnKey.Ids[i]))
                {
                    sigList = returnKey.IdSigs[i];
                }
            }

            if (sigList != null)
            {
                sigList.Add(certification);
            }
            else
            {
                sigList = Platform.CreateArrayList <IPgpSignature>();
                sigList.Add(certification);
                returnKey.Ids.Add(id);
                returnKey.IdTrusts.Add(null);
                returnKey.IdSigs.Add(sigList);
            }

            return(returnKey);
        }
        /// <summary>Verify a certification for the passed in key against the passed in master key.</summary>
        /// <param name="masterKey">The key we are verifying against.</param>
        /// <param name="pubKey">The key we are verifying.</param>
        /// <returns>True, if the certification is valid, false otherwise.</returns>
        public bool VerifyCertification(IPgpPublicKey masterKey, IPgpPublicKey pubKey)
        {
            UpdateWithPublicKey(masterKey);
            UpdateWithPublicKey(pubKey);

            Update(_sigPck.GetSignatureTrailer());

            return(_sig.VerifySignature(GetSignature()));
        }
Example #4
0
        private void verifySignature(
            byte[] encodedSig,
            HashAlgorithmTag hashAlgorithm,
            IPgpPublicKey pubKey,
            byte[] original)
        {
            PgpObjectFactory        pgpFact = new PgpObjectFactory(encodedSig);
            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();
            PgpSignature     sig = p3[0];

            DateTime creationTime = sig.CreationTime;

            // Check creationTime is recent
            if (creationTime.CompareTo(DateTime.UtcNow) > 0 ||
                creationTime.CompareTo(DateTime.UtcNow.AddMinutes(-10)) < 0)
            {
                Fail("bad creation time in signature: " + creationTime);
            }

            if (sig.KeyId != pubKey.KeyId)
            {
                Fail("key id mismatch in signature");
            }

            if (!ops.Verify(sig))
            {
                Fail("Failed generated signature check - " + hashAlgorithm);
            }

            sig.InitVerify(pubKey);

            for (int i = 0; i != original.Length; i++)
            {
                sig.Update(original[i]);
            }

            sig.Update(original);

            if (!sig.Verify())
            {
                Fail("Failed generated signature check against original data");
            }
        }
        /// <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>
        /// Generate a certification for the passed in key against the passed in master key.
        /// </summary>
        /// <param name="masterKey">The key we are certifying against.</param>
        /// <param name="pubKey">The key we are certifying.</param>
        /// <returns>
        /// The certification.
        /// </returns>
        public PgpSignature GenerateCertification(
            IPgpPublicKey masterKey,
            IPgpPublicKey pubKey)
        {
            UpdateWithPublicKey(masterKey);
            UpdateWithPublicKey(pubKey);

            return(Generate());
        }
        /// <summary>Add a public key encrypted session key to the encrypted object.</summary>
        public void AddMethod(IPgpPublicKey key)
        {
            if (!key.IsEncryptionKey)
            {
                throw new ArgumentException("passed in key not an encryption key!");
            }

            _methods.Add(new PubMethod(key));
        }
        /// <summary>
        /// Updates the with public key.
        /// </summary>
        /// <param name="key">The key.</param>
        private void UpdateWithPublicKey(IPgpPublicKey key)
        {
            var keyBytes = GetEncodedPublicKey(key);

            this.Update(
                (byte)0x99,
                (byte)(keyBytes.Length >> 8),
                (byte)(keyBytes.Length));
            this.Update(keyBytes);
        }
        internal PgpPublicKey(IPgpPublicKey key, ITrustPacket trust, IList <IPgpSignature> subSigs)
        {
            _publicPk = key.PublicKeyPacket;
            _trustPk  = trust;
            _subSigs  = subSigs;

            _fingerprint = key.GetFingerprint();
            KeyId        = key.KeyId;
            BitStrength  = key.BitStrength;
        }
Example #10
0
        private void doTestSigV3(
            PublicKeyAlgorithmTag encAlgorithm,
            HashAlgorithmTag hashAlgorithm,
            IPgpPublicKey pubKey,
            IPgpPrivateKey privKey)
        {
            byte[] bytes = generateV3BinarySig(privKey, encAlgorithm, hashAlgorithm);

            verifySignature(bytes, hashAlgorithm, pubKey, TEST_DATA);
        }
        /// <summary>
        /// Generate a certification for the passed in ID and key.
        /// </summary>
        /// <param name="id">The ID we are certifying against the public key.</param>
        /// <param name="pubKey">The key we are certifying against the ID.</param>
        /// <returns>
        /// The certification.
        /// </returns>
        public PgpSignature GenerateCertification(string id, IPgpPublicKey pubKey)
        {
            UpdateWithPublicKey(pubKey);

            //
            // hash in the id
            //
            UpdateWithIdData(0xb4, Strings.ToByteArray(id));

            return(Generate());
        }
 /// <summary>
 /// Gets the encoded public key.
 /// </summary>
 /// <param name="pubKey">The pub key.</param>
 /// <returns></returns>
 /// <exception cref="PgpException">exception preparing key.</exception>
 private static byte[] GetEncodedPublicKey(IPgpPublicKey pubKey)
 {
     try
     {
         return(pubKey.PublicKeyPacket.GetEncodedContents());
     }
     catch (IOException e)
     {
         throw new PgpException("exception preparing key.", e);
     }
 }
        /// <summary>
        /// Verify the signature as certifying the passed in public key as associated
        /// with the passed in ID.
        /// </summary>
        /// <param name="id">ID the key was stored under.</param>
        /// <param name="key">The key to be verified.</param>
        /// <returns>True, if the signature matches, false otherwise.</returns>
        public bool VerifyCertification(string id, IPgpPublicKey key)
        {
            UpdateWithPublicKey(key);

            //
            // hash in the id
            //
            UpdateWithIdData(0xb4, Strings.ToByteArray(id));

            Update(_sigPck.GetSignatureTrailer());

            return(_sig.VerifySignature(GetSignature()));
        }
Example #14
0
        /**
         * verify the signature in in against the file fileName.
         */
        private static void VerifySignature(
            string fileName,
            Stream inputStream,
            Stream keyIn)
        {
            inputStream = PgpUtilities.GetDecoderStream(inputStream);

            PgpObjectFactory pgpFact = new PgpObjectFactory(inputStream);
            PgpSignatureList p3      = null;
            PgpObject        o       = pgpFact.NextPgpObject();

            if (o is PgpCompressedData)
            {
                PgpCompressedData c1 = (PgpCompressedData)o;
                pgpFact = new PgpObjectFactory(c1.GetDataStream());

                p3 = (PgpSignatureList)pgpFact.NextPgpObject();
            }
            else
            {
                p3 = (PgpSignatureList)o;
            }

            PgpPublicKeyRingBundle pgpPubRingCollection = new PgpPublicKeyRingBundle(
                PgpUtilities.GetDecoderStream(keyIn));
            Stream        dIn = File.OpenRead(fileName);
            PgpSignature  sig = p3[0];
            IPgpPublicKey key = pgpPubRingCollection.GetPublicKey(sig.KeyId);

            sig.InitVerify(key);

            int ch;

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

            dIn.Close();

            if (sig.Verify())
            {
                Console.WriteLine("signature verified.");
            }
            else
            {
                Console.WriteLine("signature verification failed.");
            }
        }
Example #15
0
        /// <summary>Return the PGP public key associated with the given key id.</summary>
        /// <param name="keyId">The ID of the public key to return.</param>
        public IPgpPublicKey GetPublicKey(
            long keyId)
        {
            foreach (PgpPublicKeyRing pubRing in GetKeyRings())
            {
                IPgpPublicKey pub = pubRing.GetPublicKey(keyId);

                if (pub != null)
                {
                    return(pub);
                }
            }

            return(null);
        }
        /// <summary>Verify a key certification, such as revocation, for the passed in key.</summary>
        /// <param name="pubKey">The key we are checking.</param>
        /// <returns>True, if the certification is valid, false otherwise.</returns>
        public bool VerifyCertification(
            IPgpPublicKey pubKey)
        {
            if (SignatureType != KeyRevocation &&
                SignatureType != SubkeyRevocation)
            {
                throw new InvalidOperationException("signature is not a key signature");
            }

            UpdateWithPublicKey(pubKey);

            Update(_sigPck.GetSignatureTrailer());

            return(_sig.VerifySignature(GetSignature()));
        }
Example #17
0
        private void doTestTextSig(
            PublicKeyAlgorithmTag encAlgorithm,
            HashAlgorithmTag hashAlgorithm,
            IPgpPublicKey pubKey,
            IPgpPrivateKey privKey,
            byte[]                                  data,
            byte[]                                  canonicalData)
        {
            PgpSignatureGenerator sGen   = new PgpSignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1);
            MemoryStream          bOut   = new MemoryStream();
            MemoryStream          testIn = new MemoryStream(data, false);
            DateTime creationTime        = DateTime.UtcNow;

            sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey);
            sGen.GenerateOnePassVersion(false).Encode(bOut);

            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
            Stream lOut = lGen.Open(
                new UncloseableStream(bOut),
                PgpLiteralData.Text,
                "_CONSOLE",
                data.Length * 2,
                creationTime);

            int ch;

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

            lOut.Write(data, 0, data.Length);
            sGen.Update(data);

            lGen.Close();

            PgpSignature sig = sGen.Generate();

            if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0))
            {
                Fail("creation time not set in v4 signature");
            }

            sig.Encode(bOut);

            verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData);
        }
 /// <summary>
 /// Inits the verification process.
 /// </summary>
 /// <param name="pubKey">The pub key.</param>
 /// <exception cref="PgpException">invalid key.</exception>
 public void InitVerify(IPgpPublicKey pubKey)
 {
     _lastb = 0;
     if (_sig == null)
     {
         _sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(_sigPck.KeyAlgorithm, _sigPck.HashAlgorithm));
     }
     try
     {
         _sig.Init(false, pubKey.GetKey());
     }
     catch (InvalidKeyException e)
     {
         throw new PgpException("invalid key.", e);
     }
 }
Example #19
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());
        }
        private static void ExportKeyPair(
            Stream secretOut,
            Stream publicOut,
            IAsymmetricKeyParameter publicKey,
            IAsymmetricKeyParameter privateKey,
            string identity,
            char[]                   passPhrase,
            bool armor)
        {
            if (armor)
            {
                secretOut = new ArmoredOutputStream(secretOut);
            }

            PgpSecretKey secretKey = new PgpSecretKey(
                PgpSignature.DefaultCertification,
                PublicKeyAlgorithmTag.RsaGeneral,
                publicKey,
                privateKey,
                DateTime.UtcNow,
                identity,
                SymmetricKeyAlgorithmTag.Cast5,
                passPhrase,
                null,
                null,
                new SecureRandom()
                );

            secretKey.Encode(secretOut);

            if (armor)
            {
                secretOut.Close();
                publicOut = new ArmoredOutputStream(publicOut);
            }

            IPgpPublicKey key = secretKey.PublicKey;

            key.Encode(publicOut);

            if (armor)
            {
                publicOut.Close();
            }
        }
        /// <summary>Copy constructor.</summary>
        /// <param name="pubKey">The public key to copy.</param>
        internal PgpPublicKey(IPgpPublicKey pubKey)
        {
            _publicPk = pubKey.PublicKeyPacket;

            _keySigs  = Platform.CreateArrayList(pubKey.KeySigs);
            _ids      = Platform.CreateArrayList(pubKey.Ids);
            _idTrusts = Platform.CreateArrayList(pubKey.IdTrusts);
            _idSigs   = Platform.CreateArrayList(pubKey.IdSigs);

            if (pubKey.SubSigs != null)
            {
                _subSigs = Platform.CreateArrayList(pubKey.SubSigs);
            }

            _fingerprint = pubKey.GetFingerprint();
            KeyId        = pubKey.KeyId;
            BitStrength  = pubKey.BitStrength;
        }
        /**
         * verify the passed in file as being correctly signed.
         */
        private static void VerifyFile(
            Stream inputStream,
            Stream keyIn)
        {
            inputStream = PgpUtilities.GetDecoderStream(inputStream);

            PgpObjectFactory  pgpFact = new PgpObjectFactory(inputStream);
            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();
            PgpPublicKeyRingBundle pgpRing = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(keyIn));
            IPgpPublicKey          key     = pgpRing.GetPublicKey(ops.KeyId);
            Stream                 fos     = File.Create(p2.FileName);

            ops.InitVerify(key);

            int ch;

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

            PgpSignatureList p3       = (PgpSignatureList)pgpFact.NextPgpObject();
            PgpSignature     firstSig = p3[0];

            if (ops.Verify(firstSig))
            {
                Console.Out.WriteLine("signature verified.");
            }
            else
            {
                Console.Out.WriteLine("signature verification failed.");
            }
        }
        private static IPgpPublicKey RemoveCert(IPgpPublicKey key, object id)
        {
            var returnKey = new PgpPublicKey(key);
            var found     = false;

            for (var i = 0; i < returnKey._ids.Count; i++)
            {
                if (!id.Equals(returnKey._ids[i]))
                {
                    continue;
                }

                found = true;
                returnKey.Ids.RemoveAt(i);
                returnKey.IdTrusts.RemoveAt(i);
                returnKey.IdSigs.RemoveAt(i);
            }

            return(found ? returnKey : null);
        }
Example #24
0
        /// <summary>Return the public key ring which contains the key referred to by keyId</summary>
        /// <param name="keyId">key ID to match against</param>
        public PgpPublicKeyRing GetPublicKeyRing(
            long keyId)
        {
            if (pubRings.Contains(keyId))
            {
                return((PgpPublicKeyRing)pubRings[keyId]);
            }

            foreach (PgpPublicKeyRing pubRing in GetKeyRings())
            {
                IPgpPublicKey pub = pubRing.GetPublicKey(keyId);

                if (pub != null)
                {
                    return(pubRing);
                }
            }

            return(null);
        }
Example #25
0
        /// <summary>
        /// Returns a new key ring with the public key passed in either added or
        /// replacing an existing one.
        /// </summary>
        /// <param name="pubRing">The public key ring to be modified.</param>
        /// <param name="pubKey">The public key to be inserted.</param>
        /// <returns>A new <c>PgpPublicKeyRing</c></returns>
        public static PgpPublicKeyRing InsertPublicKey(IPgpPublicKeyRing pubRing, IPgpPublicKey pubKey)
        {
            var keys        = Platform.CreateArrayList(pubRing.GetPublicKeys());
            var found       = false;
            var masterFound = false;

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

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

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

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

            return(new PgpPublicKeyRing(keys));
        }
        private static PgpPublicKey RemoveCert(IPgpPublicKey key, object id, PgpSignature certification)
        {
            var returnKey = new PgpPublicKey(key);
            var found     = false;

            for (var i = 0; i < returnKey._ids.Count; i++)
            {
                if (!id.Equals(returnKey._ids[i]))
                {
                    continue;
                }

                var certs = returnKey.IdSigs[i];
                found = certs.Contains(certification);
                if (found)
                {
                    certs.Remove(certification);
                }
            }

            return(found ? returnKey : null);
        }
        /// <summary>
        /// Returns a new key ring with the public key passed in either added or
        /// replacing an existing one.
        /// </summary>
        /// <param name="pubRing">The public key ring to be modified.</param>
        /// <param name="pubKey">The public key to be inserted.</param>
        /// <returns>A new <c>PgpPublicKeyRing</c></returns>
        public static PgpPublicKeyRing InsertPublicKey(IPgpPublicKeyRing pubRing, IPgpPublicKey pubKey)
        {
            var keys = Platform.CreateArrayList(pubRing.GetPublicKeys());
            var found = false;
            var masterFound = false;

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

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

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

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

            return new PgpPublicKeyRing(keys);
        }
Example #28
0
        private void doTestSig(
            PublicKeyAlgorithmTag encAlgorithm,
            HashAlgorithmTag hashAlgorithm,
            IPgpPublicKey pubKey,
            IPgpPrivateKey privKey)
        {
            MemoryStream          bOut   = new MemoryStream();
            MemoryStream          testIn = new MemoryStream(TEST_DATA, false);
            PgpSignatureGenerator sGen   = new PgpSignatureGenerator(encAlgorithm, hashAlgorithm);

            sGen.InitSign(PgpSignature.BinaryDocument, privKey);
            sGen.GenerateOnePassVersion(false).Encode(bOut);

            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
            Stream lOut = lGen.Open(
                new UncloseableStream(bOut),
                PgpLiteralData.Binary,
                "_CONSOLE",
                TEST_DATA.Length * 2,
                DateTime.UtcNow);

            int ch;

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

            lOut.Write(TEST_DATA, 0, TEST_DATA.Length);
            sGen.Update(TEST_DATA);

            lGen.Close();

            sGen.Generate().Encode(bOut);

            verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, TEST_DATA);
        }
 /// <summary>
 /// Inits the verification process.
 /// </summary>
 /// <param name="pubKey">The pub key.</param>
 /// <exception cref="PgpException">invalid key.</exception>
 public void InitVerify(IPgpPublicKey pubKey)
 {
     _lastb = 0;
     if (_sig == null)
     {
         _sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(_sigPck.KeyAlgorithm, _sigPck.HashAlgorithm));
     }
     try
     {
         _sig.Init(false, pubKey.GetKey());
     }
     catch (InvalidKeyException e)
     {
         throw new PgpException("invalid key.", e);
     }
 }
        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>
        /// Verify the signature as certifying the passed in public key as associated
        /// with the passed in ID.
        /// </summary>
        /// <param name="id">ID the key was stored under.</param>
        /// <param name="key">The key to be verified.</param>
        /// <returns>True, if the signature matches, false otherwise.</returns>
        public bool VerifyCertification(string id, IPgpPublicKey key)
        {
            UpdateWithPublicKey(key);

            //
            // hash in the id
            //
            UpdateWithIdData(0xb4, Strings.ToByteArray(id));

            Update(_sigPck.GetSignatureTrailer());

            return _sig.VerifySignature(GetSignature());
        }
        private void doTestSig(
			PublicKeyAlgorithmTag	encAlgorithm,
			HashAlgorithmTag		hashAlgorithm,
			IPgpPublicKey			pubKey,
			IPgpPrivateKey			privKey)
        {
            MemoryStream bOut = new MemoryStream();
            MemoryStream testIn = new MemoryStream(TEST_DATA, false);
            PgpSignatureGenerator sGen = new PgpSignatureGenerator(encAlgorithm, hashAlgorithm);

            sGen.InitSign(PgpSignature.BinaryDocument, privKey);
            sGen.GenerateOnePassVersion(false).Encode(bOut);

            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
            Stream lOut = lGen.Open(
                new UncloseableStream(bOut),
                PgpLiteralData.Binary,
                "_CONSOLE",
                TEST_DATA.Length * 2,
                DateTime.UtcNow);

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

            lOut.Write(TEST_DATA, 0, TEST_DATA.Length);
            sGen.Update(TEST_DATA);

            lGen.Close();

            sGen.Generate().Encode(bOut);

            verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, TEST_DATA);
        }
        private static IPgpPublicKey RemoveCert(IPgpPublicKey key, object id)
        {
            var returnKey = new PgpPublicKey(key);
            var found = false;

            for (var i = 0; i < returnKey._ids.Count; i++)
            {
                if (!id.Equals(returnKey._ids[i]))
                    continue;

                found = true;
                returnKey.Ids.RemoveAt(i);
                returnKey.IdTrusts.RemoveAt(i);
                returnKey.IdSigs.RemoveAt(i);
            }

            return found ? returnKey : null;
        }
 /// <summary>Remove a certification associated with a given user attributes on a key.</summary>
 /// <param name="key">The key the certifications are to be removed from.</param>
 /// <param name="userAttributes">The user attributes that the certfication is to be removed from.</param>
 /// <param name="certification">The certification to be removed.</param>
 /// <returns>The re-certified key, or null if the certification was not found.</returns>
 public static PgpPublicKey RemoveCertification(IPgpPublicKey key, IPgpUserAttributeSubpacketVector userAttributes, PgpSignature certification)
 {
     return RemoveCert(key, userAttributes, certification);
 }
 /// <summary>Remove any certifications associated with a given ID on a key.</summary>
 /// <param name="key">The key the certifications are to be removed from.</param>
 /// <param name="id">The ID that is to be removed.</param>
 /// <returns>The re-certified key, or null if the ID was not found on the key.</returns>
 public static IPgpPublicKey RemoveCertification(IPgpPublicKey key, string id)
 {
     return RemoveCert(key, id);
 }
        /// <summary>Add a revocation or some other key certification to a key.</summary>
        /// <param name="key">The key the revocation is to be added to.</param>
        /// <param name="certification">The key signature to be added.</param>
        /// <returns>The new changed public key object.</returns>
        public static PgpPublicKey AddCertification(IPgpPublicKey key, PgpSignature certification)
        {
            if (key.IsMasterKey)
            {
                if (certification.SignatureType == PgpSignature.SubkeyRevocation)
                {
                    throw new ArgumentException("signature type incorrect for master key revocation.");
                }
            }
            else
            {
                if (certification.SignatureType == PgpSignature.KeyRevocation)
                {
                    throw new ArgumentException("signature type incorrect for sub-key revocation.");
                }
            }

            var returnKey = new PgpPublicKey(key);
            if (returnKey.SubSigs != null)
            {
                returnKey.SubSigs.Add(certification);
            }
            else
            {
                returnKey.KeySigs.Add(certification);
            }

            return returnKey;
        }
        internal PgpPublicKey(IPgpPublicKey key, ITrustPacket trust, IList<IPgpSignature> subSigs)
        {
            _publicPk = key.PublicKeyPacket;
            _trustPk = trust;
            _subSigs = subSigs;

            _fingerprint = key.GetFingerprint();
            KeyId = key.KeyId;
            BitStrength = key.BitStrength;
        }
        /// <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);
        }
 internal PubMethod(IPgpPublicKey pubKey)
 {
     _pubKey = pubKey;
 }
 /// <summary>
 /// Gets the encoded public key.
 /// </summary>
 /// <param name="pubKey">The pub key.</param>
 /// <returns></returns>
 /// <exception cref="PgpException">exception preparing key.</exception>
 private static byte[] GetEncodedPublicKey(IPgpPublicKey pubKey)
 {
     try
     {
         return pubKey.PublicKeyPacket.GetEncodedContents();
     }
     catch (IOException e)
     {
         throw new PgpException("exception preparing key.", e);
     }
 }
 private void UpdateWithPublicKey(IPgpPublicKey key)
 {
     var keyBytes = GetEncodedPublicKey(key);
     this.Update(
         (byte)0x99,
         (byte)(keyBytes.Length >> 8),
         (byte)(keyBytes.Length));
     this.Update(keyBytes);
 }
        /// <summary>
        /// Verify the signature as certifying the passed in public key as associated
        /// with the passed in user attributes.
        /// </summary>
        /// <param name="userAttributes">User attributes the key was stored under.</param>
        /// <param name="key">The key to be verified.</param>
        /// <returns>True, if the signature matches, false otherwise.</returns>
        public bool VerifyCertification(IPgpUserAttributeSubpacketVector userAttributes, IPgpPublicKey key)
        {
            UpdateWithPublicKey(key);

            //
            // hash in the userAttributes
            //
            try
            {
                using (var bOut = new MemoryStream())
                {
                    foreach (var packet in userAttributes.ToSubpacketArray())
                    {
                        packet.Encode(bOut);
                    }
                    UpdateWithIdData(0xd1, bOut.ToArray());
                }
            }
            catch (IOException e)
            {
                throw new PgpException("cannot encode subpacket array", e);
            }

            this.Update(_sigPck.GetSignatureTrailer());

            return _sig.VerifySignature(this.GetSignature());
        }
        internal PgpSecretKey(
            PgpPrivateKey privKey,
            PgpPublicKey pubKey,
            SymmetricKeyAlgorithmTag encAlgorithm,
            char[] passPhrase,
            bool useSha1,
            ISecureRandom rand,
            bool isMasterKey)
        {
            BcpgObject secKey;

            _pub = pubKey;

            switch (pubKey.Algorithm)
            {
                case PublicKeyAlgorithmTag.RsaEncrypt:
                case PublicKeyAlgorithmTag.RsaSign:
                case PublicKeyAlgorithmTag.RsaGeneral:
                    var rsK = (RsaPrivateCrtKeyParameters)privKey.Key;
                    secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q);
                    break;
                case PublicKeyAlgorithmTag.Dsa:
                    var dsK = (DsaPrivateKeyParameters)privKey.Key;
                    secKey = new DsaSecretBcpgKey(dsK.X);
                    break;
                case PublicKeyAlgorithmTag.ElGamalEncrypt:
                case PublicKeyAlgorithmTag.ElGamalGeneral:
                    var esK = (ElGamalPrivateKeyParameters)privKey.Key;
                    secKey = new ElGamalSecretBcpgKey(esK.X);
                    break;

                case PublicKeyAlgorithmTag.Ecdh:
                case PublicKeyAlgorithmTag.Ecdsa:
                    var ecK = (ECPrivateKeyParameters)privKey.Key;
                    secKey = new ECSecretBcpgKey(ecK.D);
                    break;

                default:
                    throw new PgpException("unknown key class");
            }

            try
            {
                using (var bOut = new MemoryStream())
                {

                    using (var pOut = new BcpgOutputStream(bOut))
                    {

                        pOut.WriteObject(secKey);

                        var keyData = bOut.ToArray();
                        var checksumBytes = Checksum(useSha1, keyData, keyData.Length);

                        pOut.Write(checksumBytes);

                        var bOutData = bOut.ToArray();

                        if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
                        {
                            this._secret = isMasterKey
                                ? new SecretKeyPacket(_pub.PublicKeyPacket, encAlgorithm, null, null, bOutData)
                                : new SecretSubkeyPacket(_pub.PublicKeyPacket, encAlgorithm, null, null, bOutData);
                        }
                        else
                        {
                            S2k s2K;
                            byte[] iv;
                            var encData = EncryptKeyData(bOutData, encAlgorithm, passPhrase, rand, out s2K, out iv);

                            var s2KUsage = useSha1 ? SecretKeyPacket.UsageSha1 : SecretKeyPacket.UsageChecksum;
                            this._secret = isMasterKey
                                ? new SecretKeyPacket(_pub.PublicKeyPacket, encAlgorithm, s2KUsage, s2K, iv, encData)
                                : new SecretSubkeyPacket(_pub.PublicKeyPacket, encAlgorithm, s2KUsage, s2K, iv, encData);
                        }
                    }
                }
            }
            catch (PgpException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception encrypting key", e);
            }
        }
        /// <summary>
        /// Generate a certification, such as a revocation, for the passed in key.
        /// </summary>
        /// <param name="pubKey">The key we are certifying.</param>
        /// <returns>
        /// The certification.
        /// </returns>
        public PgpSignature GenerateCertification(IPgpPublicKey pubKey)
        {
            UpdateWithPublicKey(pubKey);

            return Generate();
        }
 internal PgpSecretKey(ISecretKeyPacket secret, IPgpPublicKey pub)
 {
     _secret = secret;
     _pub = pub;
 }
        /**
        * Generated signature test
        *
        * @param sKey
        * @param pgpPrivKey
        * @return test result
        */
        public void GenerateTest(
            PgpSecretKeyRing sKey,
            IPgpPublicKey     pgpPubKey,
            IPgpPrivateKey    pgpPrivKey)
        {
            string data = "hello world!";
            MemoryStream bOut = new MemoryStream();

            byte[] dataBytes = Encoding.ASCII.GetBytes(data);
            MemoryStream testIn = new MemoryStream(dataBytes, false);

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

            sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);

            PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();

            IEnumerator enumerator = sKey.GetSecretKey().PublicKey.GetUserIds().GetEnumerator();
            enumerator.MoveNext();
            string primaryUserId = (string) enumerator.Current;

            spGen.SetSignerUserId(true, primaryUserId);

            sGen.SetHashedSubpackets(spGen.Generate());

            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();

            PgpObjectFactory 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(pgpPubKey);

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

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

            if (!ops.Verify(p3[0]))
            {
                Fail("Failed generated signature check");
            }
        }
        /// <summary>Copy constructor.</summary>
        /// <param name="pubKey">The public key to copy.</param>
        internal PgpPublicKey(IPgpPublicKey pubKey)
        {
            _publicPk = pubKey.PublicKeyPacket;

            _keySigs = Platform.CreateArrayList(pubKey.KeySigs);
            _ids = Platform.CreateArrayList(pubKey.Ids);
            _idTrusts = Platform.CreateArrayList(pubKey.IdTrusts);
            _idSigs = Platform.CreateArrayList(pubKey.IdSigs);

            if (pubKey.SubSigs != null)
            {
                _subSigs = Platform.CreateArrayList(pubKey.SubSigs);
            }

            _fingerprint = pubKey.GetFingerprint();
            KeyId = pubKey.KeyId;
            BitStrength = pubKey.BitStrength;
        }
        /// <summary>
        /// Generate a certification for the passed in userAttributes.
        /// </summary>
        /// <param name="userAttributes">The ID we are certifying against the public key.</param>
        /// <param name="pubKey">The key we are certifying against the ID.</param>
        /// <returns>
        /// The certification.
        /// </returns>
        /// <exception cref="PgpException">cannot encode subpacket array</exception>
        public PgpSignature GenerateCertification(PgpUserAttributeSubpacketVector userAttributes, IPgpPublicKey pubKey)
        {
            UpdateWithPublicKey(pubKey);

            //
            // hash in the attributes
            //
            try
            {
                using (var bOut = new MemoryStream())
                {
                    foreach (var packet in userAttributes.ToSubpacketArray())
                    {
                        packet.Encode(bOut);
                    }
                    UpdateWithIdData(0xd1, bOut.ToArray());
                }
            }
            catch (IOException e)
            {
                throw new PgpException("cannot encode subpacket array", e);
            }

            return this.Generate();
        }
 /// <summary>
 /// Remove any certifications associated with a user attribute subpacket on a key.
 /// </summary>
 /// <param name="key">The key the certifications are to be removed from.</param>
 /// <param name="userAttributes">The attributes to be removed.</param>
 /// <returns>
 /// The re-certified key, or null if the user attribute subpacket was not found on the key.
 /// </returns>
 public static IPgpPublicKey RemoveCertification(IPgpPublicKey key, PgpUserAttributeSubpacketVector userAttributes)
 {
     return RemoveCert(key, userAttributes);
 }
        /// <summary>Add a public key encrypted session key to the encrypted object.</summary>
        public void AddMethod(IPgpPublicKey key)
        {
            if (!key.IsEncryptionKey)
            {
                throw new ArgumentException("passed in key not an encryption key!");
            }

            _methods.Add(new PubMethod(key));
        }
 /// <summary>Remove a certification associated with a given ID on a key.</summary>
 /// <param name="key">The key the certifications are to be removed from.</param>
 /// <param name="id">The ID that the certfication is to be removed from.</param>
 /// <param name="certification">The certfication to be removed.</param>
 /// <returns>The re-certified key, or null if the certification was not found.</returns>
 public static PgpPublicKey RemoveCertification(IPgpPublicKey key, string id, PgpSignature certification)
 {
     return RemoveCert(key, id, certification);
 }
        private void doTestTextSigV3(
			PublicKeyAlgorithmTag	encAlgorithm,
			HashAlgorithmTag		hashAlgorithm,
			IPgpPublicKey			pubKey,
			IPgpPrivateKey			privKey,
			byte[]					data,
			byte[]					canonicalData)
        {
            PgpV3SignatureGenerator sGen = new PgpV3SignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1);
            MemoryStream bOut = new MemoryStream();
            MemoryStream testIn = new MemoryStream(data, false);

            sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey);
            sGen.GenerateOnePassVersion(false).Encode(bOut);

            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
            Stream lOut = lGen.Open(
                new UncloseableStream(bOut),
                PgpLiteralData.Text,
                "_CONSOLE",
                data.Length * 2,
                DateTime.UtcNow);

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

            lOut.Write(data, 0, data.Length);
            sGen.Update(data);

            lGen.Close();

            PgpSignature sig = sGen.Generate();

            if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0))
            {
                Fail("creation time not set in v3 signature");
            }

            sig.Encode(bOut);

            verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData);
        }
        private static PgpPublicKey AddCert(IPgpPublicKey key, object id, IPgpSignature certification)
        {
            var returnKey = new PgpPublicKey(key);
            IList<IPgpSignature> sigList = null;

            for (var i = 0; i != returnKey.Ids.Count; i++)
            {
                if (id.Equals(returnKey.Ids[i]))
                {
                    sigList = returnKey.IdSigs[i];
                }
            }

            if (sigList != null)
            {
                sigList.Add(certification);
            }
            else
            {
                sigList = Platform.CreateArrayList<IPgpSignature>();
                sigList.Add(certification);
                returnKey.Ids.Add(id);
                returnKey.IdTrusts.Add(null);
                returnKey.IdSigs.Add(sigList);
            }

            return returnKey;
        }
        /// <summary>
        /// Generate a certification for the passed in ID and key.
        /// </summary>
        /// <param name="id">The ID we are certifying against the public key.</param>
        /// <param name="pubKey">The key we are certifying against the ID.</param>
        /// <returns>
        /// The certification.
        /// </returns>
        public PgpSignature GenerateCertification(string id, IPgpPublicKey pubKey)
        {
            UpdateWithPublicKey(pubKey);

            //
            // hash in the id
            //
            UpdateWithIdData(0xb4, Strings.ToByteArray(id));

            return Generate();
        }
        private static PgpPublicKey RemoveCert(IPgpPublicKey key, object id, PgpSignature certification)
        {
            var returnKey = new PgpPublicKey(key);
            var found = false;

            for (var i = 0; i < returnKey._ids.Count; i++)
            {
                if (!id.Equals(returnKey._ids[i]))
                    continue;

                var certs = returnKey.IdSigs[i];
                found = certs.Contains(certification);
                if (found)
                {
                    certs.Remove(certification);
                }
            }

            return found ? returnKey : null;
        }
        internal PgpSecretKey(
            PgpPrivateKey privKey,
            PgpPublicKey pubKey,
            SymmetricKeyAlgorithmTag encAlgorithm,
            char[] passPhrase,
            bool useSha1,
            ISecureRandom rand,
            bool isMasterKey)
        {
            BcpgObject secKey;

            _pub = pubKey;

            switch (pubKey.Algorithm)
            {
            case PublicKeyAlgorithmTag.RsaEncrypt:
            case PublicKeyAlgorithmTag.RsaSign:
            case PublicKeyAlgorithmTag.RsaGeneral:
                var rsK = (RsaPrivateCrtKeyParameters)privKey.Key;
                secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q);
                break;

            case PublicKeyAlgorithmTag.Dsa:
                var dsK = (DsaPrivateKeyParameters)privKey.Key;
                secKey = new DsaSecretBcpgKey(dsK.X);
                break;

            case PublicKeyAlgorithmTag.ElGamalEncrypt:
            case PublicKeyAlgorithmTag.ElGamalGeneral:
                var esK = (ElGamalPrivateKeyParameters)privKey.Key;
                secKey = new ElGamalSecretBcpgKey(esK.X);
                break;

            case PublicKeyAlgorithmTag.Ecdh:
            case PublicKeyAlgorithmTag.Ecdsa:
                var ecK = (ECPrivateKeyParameters)privKey.Key;
                secKey = new ECSecretBcpgKey(ecK.D);
                break;

            default:
                throw new PgpException("unknown key class");
            }

            try
            {
                using (var bOut = new MemoryStream())
                {
                    using (var pOut = new BcpgOutputStream(bOut))
                    {
                        pOut.WriteObject(secKey);

                        var keyData       = bOut.ToArray();
                        var checksumBytes = Checksum(useSha1, keyData, keyData.Length);

                        pOut.Write(checksumBytes);

                        var bOutData = bOut.ToArray();

                        if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
                        {
                            this._secret = isMasterKey
                                ? new SecretKeyPacket(_pub.PublicKeyPacket, encAlgorithm, null, null, bOutData)
                                : new SecretSubkeyPacket(_pub.PublicKeyPacket, encAlgorithm, null, null, bOutData);
                        }
                        else
                        {
                            S2k    s2K;
                            byte[] iv;
                            var    encData = EncryptKeyData(bOutData, encAlgorithm, passPhrase, rand, out s2K, out iv);

                            var s2KUsage = useSha1 ? SecretKeyPacket.UsageSha1 : SecretKeyPacket.UsageChecksum;
                            this._secret = isMasterKey
                                ? new SecretKeyPacket(_pub.PublicKeyPacket, encAlgorithm, s2KUsage, s2K, iv, encData)
                                : new SecretSubkeyPacket(_pub.PublicKeyPacket, encAlgorithm, s2KUsage, s2K, iv, encData);
                        }
                    }
                }
            }
            catch (PgpException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception encrypting key", e);
            }
        }
        private void doTestSigV3(
			PublicKeyAlgorithmTag	encAlgorithm,
			HashAlgorithmTag		hashAlgorithm,
			IPgpPublicKey			pubKey,
			IPgpPrivateKey			privKey)
        {
            byte[] bytes = generateV3BinarySig(privKey, encAlgorithm, hashAlgorithm);

            verifySignature(bytes, hashAlgorithm, pubKey, TEST_DATA);
        }
        /// <summary>Verify a certification for the passed in key against the passed in master key.</summary>
        /// <param name="masterKey">The key we are verifying against.</param>
        /// <param name="pubKey">The key we are verifying.</param>
        /// <returns>True, if the certification is valid, false otherwise.</returns>
        public bool VerifyCertification(IPgpPublicKey masterKey, IPgpPublicKey pubKey)
        {
            UpdateWithPublicKey(masterKey);
            UpdateWithPublicKey(pubKey);

            Update(_sigPck.GetSignatureTrailer());

            return _sig.VerifySignature(GetSignature());
        }
        private void verifySignature(
			byte[] encodedSig,
			HashAlgorithmTag hashAlgorithm,
			IPgpPublicKey pubKey,
			byte[] original)
        {
            PgpObjectFactory        pgpFact = new PgpObjectFactory(encodedSig);
            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();
            PgpSignature sig = p3[0];

            DateTime creationTime = sig.CreationTime;

            // Check creationTime is recent
            if (creationTime.CompareTo(DateTime.UtcNow) > 0
                || creationTime.CompareTo(DateTime.UtcNow.AddMinutes(-10)) < 0)
            {
                Fail("bad creation time in signature: " + creationTime);
            }

            if (sig.KeyId != pubKey.KeyId)
            {
                Fail("key id mismatch in signature");
            }

            if (!ops.Verify(sig))
            {
                Fail("Failed generated signature check - " + hashAlgorithm);
            }

            sig.InitVerify(pubKey);

            for (int i = 0; i != original.Length; i++)
            {
                sig.Update(original[i]);
            }

            sig.Update(original);

            if (!sig.Verify())
            {
                Fail("Failed generated signature check against original data");
            }
        }
        /// <summary>Verify a key certification, such as revocation, for the passed in key.</summary>
        /// <param name="pubKey">The key we are checking.</param>
        /// <returns>True, if the certification is valid, false otherwise.</returns>
        public bool VerifyCertification(
            IPgpPublicKey pubKey)
        {
            if (SignatureType != KeyRevocation
                && SignatureType != SubkeyRevocation)
            {
                throw new InvalidOperationException("signature is not a key signature");
            }

            UpdateWithPublicKey(pubKey);

            Update(_sigPck.GetSignatureTrailer());

            return _sig.VerifySignature(GetSignature());
        }