General class to contain a private key for use with other OpenPGP objects.
Beispiel #1
1
        /// <summary>
        /// Attempt to encrypt a message using PGP with the specified public key(s).
        /// </summary>
        /// <param name="messageStream">Stream containing the message to encrypt.</param>
        /// <param name="fileName">File name of for the message.</param>
        /// <param name="signedAndEncryptedMessageStream">Stream to write the encrypted message into.</param>
        /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param>
        /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param>
        /// <param name="recipientPublicKeys">Collection of BouncyCastle public keys to be used for encryption.</param>
        /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param>
        /// <param name="symmetricKeyAlgorithmTag">The symmetric key algorithm tag to use for encryption.</param>
        /// <param name="armor">Whether to wrap the message with ASCII armor.</param>
        /// <returns>Whether the encryption completed successfully.</returns>
        public static bool SignAndEncrypt(Stream messageStream, string fileName, Stream signedAndEncryptedMessageStream, PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, IEnumerable<PgpPublicKey> recipientPublicKeys, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = SymmetricKeyAlgorithmTag.TripleDes, bool armor = true)
        {
            // Create a signature generator.
            PgpSignatureGenerator signatureGenerator = new PgpSignatureGenerator(senderPublicKey.Algorithm, hashAlgorithmTag);
            signatureGenerator.InitSign(PgpSignature.BinaryDocument, senderPrivateKey);

            // Add the public key user ID.
            foreach (string userId in senderPublicKey.GetUserIds())
            {
                PgpSignatureSubpacketGenerator signatureSubGenerator = new PgpSignatureSubpacketGenerator();
                signatureSubGenerator.SetSignerUserId(false, userId);
                signatureGenerator.SetHashedSubpackets(signatureSubGenerator.Generate());
                break;
            }

            // Allow any of the corresponding keys to be used for decryption.
            PgpEncryptedDataGenerator encryptedDataGenerator = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.TripleDes, true, new SecureRandom());
            foreach (PgpPublicKey publicKey in recipientPublicKeys)
            {
                encryptedDataGenerator.AddMethod(publicKey);
            }

            // Handle optional ASCII armor.
            if (armor)
            {
                using (Stream armoredStream = new ArmoredOutputStream(signedAndEncryptedMessageStream))
                {
                    using (Stream encryptedStream = encryptedDataGenerator.Open(armoredStream, new byte[Constants.LARGEBUFFERSIZE]))
                    {
                        PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Uncompressed);
                        using (Stream compressedStream = compressedDataGenerator.Open(encryptedStream))
                        {
                            signatureGenerator.GenerateOnePassVersion(false).Encode(compressedStream);

                            PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator();
                            using (Stream literalStream = literalDataGenerator.Open(compressedStream, PgpLiteralData.Binary,
                                fileName, DateTime.Now, new byte[Constants.LARGEBUFFERSIZE]))
                            {
                                // Process each character in the message.
                                int messageChar;
                                while ((messageChar = messageStream.ReadByte()) >= 0)
                                {
                                    literalStream.WriteByte((byte)messageChar);
                                    signatureGenerator.Update((byte)messageChar);
                                }
                            }

                            signatureGenerator.Generate().Encode(compressedStream);
                        }
                    }
                }
            }
            else
            {
                using (Stream encryptedStream = encryptedDataGenerator.Open(signedAndEncryptedMessageStream, new byte[Constants.LARGEBUFFERSIZE]))
                {
                    PgpCompressedDataGenerator compressedDataGenerator = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Uncompressed);
                    using (Stream compressedStream = compressedDataGenerator.Open(encryptedStream))
                    {
                        signatureGenerator.GenerateOnePassVersion(false).Encode(compressedStream);

                        PgpLiteralDataGenerator literalDataGenerator = new PgpLiteralDataGenerator();
                        using (Stream literalStream = literalDataGenerator.Open(compressedStream, PgpLiteralData.Binary,
                            fileName, DateTime.Now, new byte[Constants.LARGEBUFFERSIZE]))
                        {
                            // Process each character in the message.
                            int messageChar;
                            while ((messageChar = messageStream.ReadByte()) >= 0)
                            {
                                literalStream.WriteByte((byte)messageChar);
                                signatureGenerator.Update((byte)messageChar);
                            }
                        }

                        signatureGenerator.Generate().Encode(compressedStream);
                    }
                }
            }

            return true;
        }
		/// <summary>
		/// Return the algorithm code for the symmetric algorithm used to encrypt the data.
		/// </summary>
		public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm(
			PgpPrivateKey privKey)
		{
			byte[] plain = fetchSymmetricKeyData(privKey);

			return (SymmetricKeyAlgorithmTag) plain[0];
		}
        /// <summary>
        /// Return the algorithm code for the symmetric algorithm used to encrypt the data.
        /// </summary>
        public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm(
            PgpPrivateKey privKey)
        {
            byte[] plain = fetchSymmetricKeyData(privKey);

            return((SymmetricKeyAlgorithmTag)plain[0]);
        }
Beispiel #4
0
		/// <summary>Create a key pair from a PgpPrivateKey and a PgpPublicKey.</summary>
		/// <param name="pub">The public key.</param>
		/// <param name="priv">The private key.</param>
        public PgpKeyPair(
            PgpPublicKey	pub,
            PgpPrivateKey	priv)
        {
            this.pub = pub;
            this.priv = priv;
        }
Beispiel #5
0
        /// <summary>
        /// Return the algorithm code for the symmetric algorithm used to encrypt the data.
        /// </summary>
        public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm(
            PgpPrivateKey privKey)
        {
            byte[] sessionData = RecoverSessionData(privKey);

            return((SymmetricKeyAlgorithmTag)sessionData[0]);
        }
		/// <summary>Initialise the generator for signing.</summary>
		public void InitSign(
			int				sigType,
			PgpPrivateKey	key,
			SecureRandom	random)
		{
			this.privKey = key;
			this.signatureType = sigType;

			try
			{
				ICipherParameters cp = key.Key;
				if (random != null)
				{
					cp = new ParametersWithRandom(key.Key, random);
				}

				sig.Init(true, cp);
			}
			catch (InvalidKeyException e)
			{
				throw new PgpException("invalid key.", e);
			}

			dig.Reset();
			lastb = 0;
		}
Beispiel #7
0
 /// <summary>
 /// Attempt to decrypt a PGP protected message using the matching private key.
 /// </summary>
 /// <param name="message">Byte array containing the message to decrypt.</param>
 /// <param name="decryptedMessageStream">Stream to write the decrypted message into.</param>
 /// <param name="recipientPrivateKey">The BouncyCastle private key to be used for decryption.</param>
 /// <remarks>The message should be passed in without ASCII Armor.</remarks>
 /// <returns>Whether the decryption completed successfully.</returns>
 public static bool Decrypt(byte[] message, Stream decryptedMessageStream, PgpPrivateKey recipientPrivateKey)
 {
     using (MemoryStream messageStream = new MemoryStream(message))
     {
         return Decrypt(messageStream, decryptedMessageStream, recipientPrivateKey);
     }
 }
 /// <summary>Create a key pair from a PgpPrivateKey and a PgpPublicKey.</summary>
 /// <param name="pub">The public key.</param>
 /// <param name="priv">The private key.</param>
 public PgpKeyPair(
     PgpPublicKey pub,
     PgpPrivateKey priv)
 {
     this.pub  = pub;
     this.priv = priv;
 }
		/// <summary>
		/// Return the algorithm code for the symmetric algorithm used to encrypt the data.
		/// </summary>
		public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm(
			PgpPrivateKey privKey)
		{
			byte[] sessionData = RecoverSessionData(privKey);

            return (SymmetricKeyAlgorithmTag)sessionData[0];
		}
Beispiel #10
0
        /// <summary>Initialise the generator for signing.</summary>
        public void InitSign(
            int sigType,
            PgpPrivateKey key,
            SecureRandom random)
        {
            this.privKey       = key;
            this.signatureType = sigType;

            try
            {
                ICipherParameters cp = key.Key;
                if (random != null)
                {
                    cp = new ParametersWithRandom(key.Key, random);
                }

                sig.Init(true, cp);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("invalid key.", e);
            }

            dig.Reset();
            lastb = 0;
        }
Beispiel #11
0
		public PgpKeyPair(
            PublicKeyAlgorithmTag	algorithm,
            AsymmetricKeyParameter	pubKey,
            AsymmetricKeyParameter	privKey,
            DateTime				time)
        {
            this.pub = new PgpPublicKey(algorithm, pubKey, time);
			this.priv = new PgpPrivateKey(privKey, pub.KeyId);
        }
 public PgpKeyPair(
     PublicKeyAlgorithmTag algorithm,
     IAsymmetricKeyParameter pubKey,
     IAsymmetricKeyParameter privKey,
     DateTime time)
 {
     this.pub  = new PgpPublicKey(algorithm, pubKey, time);
     this.priv = new PgpPrivateKey(privKey, pub.KeyId);
 }
Beispiel #13
0
		internal PgpSecretKey(
			PgpPrivateKey				privKey,
			PgpPublicKey				pubKey,
			SymmetricKeyAlgorithmTag	encAlgorithm,
			char[]						passPhrase,
			bool						useSha1,
			SecureRandom				rand)
			: this(privKey, pubKey, encAlgorithm, passPhrase, useSha1, rand, false)
		{
		}
 internal PgpSecretKey(
     PgpPrivateKey privKey,
     PgpPublicKey pubKey,
     SymmetricKeyAlgorithmTag encAlgorithm,
     char[]                                              passPhrase,
     bool useSha1,
     SecureRandom rand)
     : this(privKey, pubKey, encAlgorithm, passPhrase, useSha1, rand, false)
 {
 }
        private PgpPrivateKey ReadPrivateKey(string passPhrase)
        {
            Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey privateKey = SecretKey.ExtractPrivateKey(passPhrase.ToCharArray());

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

            throw new ArgumentException("No private key found in secret key.");
        }
        private byte[] RecoverSessionData(PgpPrivateKey privKey)
        {
            byte[][] encSessionKey = keyData.GetEncSessionKey();
            if (keyData.Algorithm == PublicKeyAlgorithmTag.EC)
            {
                ECDHPublicBcpgKey eCDHPublicBcpgKey = (ECDHPublicBcpgKey)privKey.PublicKeyPacket.Key;
                X9ECParameters    x9ECParameters    = ECKeyPairGenerator.FindECCurveByOid(eCDHPublicBcpgKey.CurveOid);
                byte[]            array             = encSessionKey[0];
                int    num    = (((array[0] & 0xFF) << 8) + (array[1] & 0xFF) + 7) / 8;
                byte[] array2 = new byte[num];
                global::System.Array.Copy((global::System.Array)array, 2, (global::System.Array)array2, 0, num);
                byte[] array3 = new byte[array[num + 2]];
                global::System.Array.Copy((global::System.Array)array, 2 + num + 1, (global::System.Array)array3, 0, array3.Length);
                ECPoint eCPoint = x9ECParameters.Curve.DecodePoint(array2);
                ECPrivateKeyParameters eCPrivateKeyParameters = (ECPrivateKeyParameters)privKey.Key;
                ECPoint      s          = eCPoint.Multiply(eCPrivateKeyParameters.D).Normalize();
                KeyParameter parameters = new KeyParameter(Rfc6637Utilities.CreateKey(privKey.PublicKeyPacket, s));
                IWrapper     wrapper    = PgpUtilities.CreateWrapper(eCDHPublicBcpgKey.SymmetricKeyAlgorithm);
                wrapper.Init(forWrapping: false, parameters);
                return(PgpPad.UnpadSessionData(wrapper.Unwrap(array3, 0, array3.Length)));
            }
            IBufferedCipher keyCipher = GetKeyCipher(keyData.Algorithm);

            try
            {
                keyCipher.Init(forEncryption: false, privKey.Key);
            }
            catch (InvalidKeyException exception)
            {
                throw new PgpException("error setting asymmetric cipher", exception);
            }
            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                byte[] array4 = encSessionKey[0];
                keyCipher.ProcessBytes(array4, 2, array4.Length - 2);
            }
            else
            {
                ElGamalPrivateKeyParameters elGamalPrivateKeyParameters = (ElGamalPrivateKeyParameters)privKey.Key;
                int size = (elGamalPrivateKeyParameters.Parameters.P.BitLength + 7) / 8;
                ProcessEncodedMpi(keyCipher, size, encSessionKey[0]);
                ProcessEncodedMpi(keyCipher, size, encSessionKey[1]);
            }
            try
            {
                return(keyCipher.DoFinal());
            }
            catch (global::System.Exception exception2)
            {
                throw new PgpException("exception decrypting secret key", exception2);
            }
        }
Beispiel #17
0
        /// <summary>
        /// Attempt to decrypt a PGP protected message using the matching private key.
        /// </summary>
        /// <param name="messageStream">Stream containing the message to decrypt.</param>
        /// <param name="decryptedMessage">If successful, the decrypted message.</param>
        /// <param name="recipientPrivateKey">The BouncyCastle private key to be used for decryption.</param>
        /// <remarks>The message should be passed in without ASCII Armor.</remarks>
        /// <returns>Whether the decryption completed successfully.</returns>
        public static bool Decrypt(Stream messageStream, out byte[] decryptedMessage, PgpPrivateKey recipientPrivateKey)
        {
            using (MemoryStream decryptedMessageStream = new MemoryStream())
            {
                bool decrypted = Decrypt(messageStream, decryptedMessageStream, recipientPrivateKey);
                if (decrypted)
                    decryptedMessage = decryptedMessageStream.ToArray();
                else
                    decryptedMessage = null;

                return decrypted;
            }
        }
Beispiel #18
0
        /// <summary>Initialise the generator for signing.</summary>
        public void InitSign(
            int signatureType,
            PgpPrivateKey key)
        {
            this.privKey       = key;
            this.signatureType = signatureType;

            try
            {
                sig.Init(true, key.Key);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("invalid key.", e);
            }

            dig.Reset();
            lastb = 0;
        }
 public void InitSign(int sigType, PgpPrivateKey key, SecureRandom random)
 {
     privKey       = key;
     signatureType = sigType;
     try
     {
         ICipherParameters parameters = key.Key;
         if (random != null)
         {
             parameters = new ParametersWithRandom(key.Key, random);
         }
         sig.Init(forSigning: true, parameters);
     }
     catch (InvalidKeyException exception)
     {
         throw new PgpException("invalid key.", exception);
     }
     dig.Reset();
     lastb = 0;
 }
Beispiel #20
0
 public PgpKeyPair(PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, AsymmetricKeyParameter privKey, global::System.DateTime time)
 {
     pub  = new PgpPublicKey(algorithm, pubKey, time);
     priv = new PgpPrivateKey(pub.KeyId, pub.PublicKeyPacket, privKey);
 }
        ////--------------------------------------------------- BUILDER ------------------------------------------------------
        //private  class Builder {
        //   private static char[] EMPTY_PASSWORD = new char[0];
        //   private PgpPublicKey publicKeyForEncryption = null;
        //   private PgpSecretKey secretKeyForSigning = null;
        //   private char[] secretKeyPassword = EMPTY_PASSWORD;
        //   public Builder setPublicKeyForEncryption(InputStream pgpPublicKeyIn) {
        //      Validate.notNull(pgpPublicKeyIn, "If you do not want to set public key, then simply do not call this method!");
        //      try {
        //         PgpPublicKey publicKey = KeyUtils.findPublicKeyForEncryption(pgpPublicKeyIn);
        //         if (publicKey == null) {
        //            throw new IllegalArgumentException("Cannot load public key from given input stream");
        //         }
        //         this.publicKeyForEncryption = publicKey;
        //      } catch (Exception e) {
        //         throw new IllegalArgumentException("Cannot load public key from given input stream");
        //      }
        //      return this;
        //   }
        //   public Builder setPublicKeyForEncryption(PgpPublicKey pgpPublicKey) {
        //      Validate.notNull(pgpPublicKey, "If you do not want to set public key, then simply do not call this method!");
        //      this.publicKeyForEncryption = pgpPublicKey;
        //      return this;
        //   }
        //   public Builder setSecretKeyForSigning(InputStream pgpSecretKeyIn) {
        //      Validate.notNull(pgpSecretKeyIn, "If you do not want to set private key, then simply do not call this method!");
        //      try {
        //         PgpSecretKey secretKey = KeyUtils.findSecretKeyForSigning(pgpSecretKeyIn);
        //         if (secretKey == null) {
        //            throw new IllegalArgumentException("Cannot load secret key from given input stream");
        //         }
        //         this.secretKeyForSigning = secretKey;
        //      } catch (Exception e) {
        //         throw new IllegalArgumentException("Cannot load secret key from given input stream");
        //      }
        //      return this;
        //   }
        //   public Builder setSecretKeyForSigning(PgpSecretKey pgpSecretKey) {
        //      Validate.notNull(pgpSecretKey, "If you do not want to set private key, then simply do not call this method!");
        //      this.secretKeyForSigning = pgpSecretKey;
        //      return this;
        //   }
        //   public Builder setSecretKeyPassword(char[] secretKeyPassword) {
        //      if (secretKeyPassword == null) {
        //         this.secretKeyPassword = EMPTY_PASSWORD;
        //      } else {
        //         this.secretKeyPassword = Arrays.copyOf(secretKeyPassword, secretKeyPassword.length);
        //      }
        //      return this;
        //   }
        //   public PgpEncryptor createPgpEncryptor() {
        //      return new PgpEncryptor(publicKeyForEncryption, secretKeyForSigning, secretKeyPassword);
        //   }
        //}
        //--------------------------------------------------- HELPER METHODS -----------------------------------------------
        private PgpSignatureGenerator createSignatureGenerator(PgpPrivateKey pgpPrivateKey)
        {
            PgpSignatureGenerator signatureGenerator = new PgpSignatureGenerator(
                secretKeyForSigning.PublicKey.Algorithm, HashAlgorithmTag.Sha1);

            signatureGenerator.InitSign(PgpSignature.BinaryDocument, pgpPrivateKey);

            setSignatureSubpackets(secretKeyForSigning, signatureGenerator);
            return signatureGenerator;
        }
Beispiel #22
0
 /// <summary>Initialise the generator for signing.</summary>
 public void InitSign(
     int sigType,
     PgpPrivateKey key)
 {
     InitSign(sigType, key, null);
 }
 /// <summary>
 /// Attempt to sign then encrypt a message using PGP with the specified private and public keys.
 /// </summary>
 /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param>
 /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param>
 /// <param name="recipientPublicKey">BouncyCastle public key to be used for encryption.</param>
 /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param>
 /// <param name="symmetricKeyAlgorithmTag">The symmetric key algorithm tag to use for encryption.</param>
 /// <returns>Whether the encryption completed successfully.</returns>
 public bool PgpSignAndEncrypt(PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, PgpPublicKey recipientPublicKey, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = SymmetricKeyAlgorithmTag.TripleDes)
 {
     return PgpSignAndEncrypt(senderPublicKey, senderPrivateKey, new List<PgpPublicKey>() { recipientPublicKey }, hashAlgorithmTag, symmetricKeyAlgorithmTag);
 }
        /// <summary>
        /// Attempt to decrypt a PGP protected message using the matching private key.
        /// </summary>
        /// <param name="decryptedMessage">If successful, the decrypted message.</param>
        /// <returns>Whether the decryption completed successfully.</returns>
        public bool PgpDecrypt(PgpPrivateKey recipientPrivateKey, out byte[] decryptedMessage)
        {
            string encryptedBody = "";

            // Process each MIME part.
            if (MimeParts != null)
            {
                for (int i = 0; i < MimeParts.Count; i++)
                {
                    MimePart mimePart = MimeParts[i];

                    // Check if the MIME part is encrypted or signed using PGP.
                    if (mimePart.Body.StartsWith("-----BEGIN PGP MESSAGE-----"))
                    {
                        encryptedBody = Functions.ReturnBetween(mimePart.Body, "-----BEGIN PGP MESSAGE-----\r\n", "\r\n-----END PGP MESSAGE-----");
                        break;
                    }
                }
            }
            else
            {
                if (Body.StartsWith("-----BEGIN PGP MESSAGE-----"))
                    encryptedBody = Functions.ReturnBetween(Body, "-----BEGIN PGP MESSAGE-----\r\n", "\r\n-----END PGP MESSAGE-----");
            }

            // Process an encrypted body if found.
            if (!string.IsNullOrEmpty(encryptedBody))
            {
                // Ignore the PGP headers.
                int doubleLineBreak = encryptedBody.IndexOf("\r\n\r\n");
                if (doubleLineBreak > -1)
                    encryptedBody = encryptedBody.Substring(doubleLineBreak + 4);

                // Attempt to decrypt the message and set the body if successful.
                if (Pgp.Decrypt(Encoding.UTF8.GetBytes(encryptedBody), out decryptedMessage, recipientPrivateKey))
                {
                    // Ensure a valid encoding.
                    if (BodyEncoding == null)
                        BodyEncoding = Encoding.UTF8;

                    // Convert the byte array back to a string.
                    Body = BodyEncoding.GetString(decryptedMessage);

                    // OpaqueMail optional setting for protecting the subject.
                    if (SubjectEncryption && Body.StartsWith("Subject: "))
                    {
                        int linebreakPosition = Body.IndexOf("\r\n");
                        if (linebreakPosition > -1)
                        {
                            // Decode international strings and remove escaped linebreaks.
                            string subjectText = Body.Substring(9, linebreakPosition - 9);
                            Subject = Functions.DecodeMailHeader(subjectText).Replace("\r", "").Replace("\n", "");

                            Body = Body.Substring(linebreakPosition + 2);
                        }
                    }

                    // If the body was successfully decrypted, attempt to decrypt attachments.
                    foreach (Attachment attachment in Attachments)
                    {
                        // Only process attachments with names ending in ".pgp".
                        if (attachment.Name.ToLower().EndsWith(".pgp"))
                        {
                            if (Pgp.Decrypt(attachment.ContentStream, out decryptedMessage, recipientPrivateKey))
                            {
                                attachment.ContentStream = new MemoryStream(decryptedMessage);
                                attachment.Name = attachment.Name.Substring(0, attachment.Name.Length - 4);
                            }
                        }
                    }

                    return true;
                }
                else
                    return false;
            }
            else
            {
                decryptedMessage = null;
                return false;
            }
        }
Beispiel #25
0
        internal PgpSecretKey(
            PgpPrivateKey				privKey,
            PgpPublicKey				pubKey,
            SymmetricKeyAlgorithmTag	encAlgorithm,
            byte[]						rawPassPhrase,
            bool                        clearPassPhrase,
            bool						useSha1,
            SecureRandom				rand,
            bool						isMasterKey)
        {
            BcpgObject secKey;

            this.pub = pubKey;

            switch (pubKey.Algorithm)
            {
                case PublicKeyAlgorithmTag.RsaEncrypt:
                case PublicKeyAlgorithmTag.RsaSign:
                case PublicKeyAlgorithmTag.RsaGeneral:
                    RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters) privKey.Key;
                    secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q);
                    break;
                case PublicKeyAlgorithmTag.Dsa:
                    DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters) privKey.Key;
                    secKey = new DsaSecretBcpgKey(dsK.X);
                    break;
                case PublicKeyAlgorithmTag.ECDH:
                case PublicKeyAlgorithmTag.ECDsa:
                    ECPrivateKeyParameters ecK = (ECPrivateKeyParameters)privKey.Key;
                    secKey = new ECSecretBcpgKey(ecK.D);
                    break;
                case PublicKeyAlgorithmTag.ElGamalEncrypt:
                case PublicKeyAlgorithmTag.ElGamalGeneral:
                    ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters) privKey.Key;
                    secKey = new ElGamalSecretBcpgKey(esK.X);
                    break;
                default:
                    throw new PgpException("unknown key class");
            }

            try
            {
                MemoryStream bOut = new MemoryStream();
                BcpgOutputStream pOut = new BcpgOutputStream(bOut);

                pOut.WriteObject(secKey);

                byte[] keyData = bOut.ToArray();
                byte[] checksumData = Checksum(useSha1, keyData, keyData.Length);

                keyData = Arrays.Concatenate(keyData, checksumData);

                if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
                {
                    if (isMasterKey)
                    {
                        this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, keyData);
                    }
                    else
                    {
                        this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, keyData);
                    }
                }
                else
                {
                    S2k s2k;
                    byte[] iv;

                    byte[] encData;
                    if (pub.Version >= 4)
                    {
                        encData = EncryptKeyDataV4(keyData, encAlgorithm, HashAlgorithmTag.Sha1, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv);
                    }
                    else
                    {
                        encData = EncryptKeyDataV3(keyData, encAlgorithm, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv);
                    }

                    int s2kUsage = useSha1
                        ?	SecretKeyPacket.UsageSha1
                        :	SecretKeyPacket.UsageChecksum;

                    if (isMasterKey)
                    {
                        this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
                    }
                    else
                    {
                        this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
                    }
                }
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception encrypting key", e);
            }
        }
        public Stream GetDataStream(PgpPrivateKey privKey)
        {
            //IL_012b: Unknown result type (might be due to invalid IL or missing references)
            //IL_015a: Unknown result type (might be due to invalid IL or missing references)
            byte[] array = RecoverSessionData(privKey);
            if (!ConfirmCheckSum(array))
            {
                throw new PgpKeyValidationException("key checksum failed");
            }
            SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = (SymmetricKeyAlgorithmTag)array[0];

            if (symmetricKeyAlgorithmTag == SymmetricKeyAlgorithmTag.Null)
            {
                return((Stream)(object)encData.GetInputStream());
            }
            string          symmetricCipherName = PgpUtilities.GetSymmetricCipherName(symmetricKeyAlgorithmTag);
            string          text = symmetricCipherName;
            IBufferedCipher cipher;

            try
            {
                text   = ((!(encData is SymmetricEncIntegrityPacket)) ? (text + "/OpenPGPCFB/NoPadding") : (text + "/CFB/NoPadding"));
                cipher = CipherUtilities.GetCipher(text);
            }
            catch (PgpException ex)
            {
                throw ex;
            }
            catch (global::System.Exception exception)
            {
                throw new PgpException("exception creating cipher", exception);
            }
            try
            {
                KeyParameter parameters = ParameterUtilities.CreateKeyParameter(symmetricCipherName, array, 1, array.Length - 3);
                byte[]       array2     = new byte[cipher.GetBlockSize()];
                cipher.Init(forEncryption: false, new ParametersWithIV(parameters, array2));
                encStream = (Stream)(object)BcpgInputStream.Wrap((Stream)(object)new CipherStream((Stream)(object)encData.GetInputStream(), cipher, null));
                if (encData is SymmetricEncIntegrityPacket)
                {
                    truncStream = new TruncatedStream(encStream);
                    string  digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
                    IDigest digest     = DigestUtilities.GetDigest(digestName);
                    encStream = (Stream)(object)new DigestStream((Stream)(object)truncStream, digest, null);
                }
                if (Streams.ReadFully(encStream, array2, 0, array2.Length) < array2.Length)
                {
                    throw new EndOfStreamException("unexpected end of stream.");
                }
                int num  = encStream.ReadByte();
                int num2 = encStream.ReadByte();
                if (num < 0 || num2 < 0)
                {
                    throw new EndOfStreamException("unexpected end of stream.");
                }
                return(encStream);
            }
            catch (PgpException ex2)
            {
                throw ex2;
            }
            catch (global::System.Exception exception2)
            {
                throw new PgpException("Exception starting decryption", exception2);
            }
        }
        /// <summary>Initialise the generator for signing.</summary>
        public void InitSign(
            int				sigType,
            PgpPrivateKey	key)
        {
            this.privKey = key;
            this.signatureType = sigType;

            try
            {
                sig.Init(true, key.Key);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("invalid key.", e);
            }

            dig.Reset();
            lastb = 0;
        }
		private byte[] fetchSymmetricKeyData(
			PgpPrivateKey privKey)
		{
			IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);

			try
			{
				c1.Init(false, privKey.Key);
			}
			catch (InvalidKeyException e)
			{
				throw new PgpException("error setting asymmetric cipher", e);
			}

			BigInteger[] keyD = keyData.GetEncSessionKey();

			if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt
				|| keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
			{
				c1.ProcessBytes(keyD[0].ToByteArrayUnsigned());
			}
			else
			{
				ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
				int size = (k.Parameters.P.BitLength + 7) / 8;

				byte[] bi = keyD[0].ToByteArray();

				int diff = bi.Length - size;
				if (diff >= 0)
				{
					c1.ProcessBytes(bi, diff, size);
				}
				else
				{
					byte[] zeros = new byte[-diff];
					c1.ProcessBytes(zeros);
					c1.ProcessBytes(bi);
				}

				bi = keyD[1].ToByteArray();

				diff = bi.Length - size;
				if (diff >= 0)
				{
					c1.ProcessBytes(bi, diff, size);
				}
				else
				{
					byte[] zeros = new byte[-diff];
					c1.ProcessBytes(zeros);
					c1.ProcessBytes(bi);
				}
			}

			byte[] plain;
			try
			{
				plain = c1.DoFinal();
			}
			catch (Exception e)
			{
				throw new PgpException("exception decrypting secret key", e);
			}

			if (!ConfirmCheckSum(plain))
				throw new PgpKeyValidationException("key checksum failed");

			return plain;
		}
        /// <summary>Return the decrypted data stream for the packet.</summary>
        public Stream GetDataStream(
            PgpPrivateKey privKey)
        {
            byte[] plain = fetchSymmetricKeyData(privKey);

            IBufferedCipher c2;
            string          cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag)plain[0]);
            string          cName      = cipherName;

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

                c2 = CipherUtilities.GetCipher(cName);
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("exception creating cipher", e);
            }

            if (c2 == null)
            {
                return(encData.GetInputStream());
            }

            try
            {
                KeyParameter key = ParameterUtilities.CreateKeyParameter(
                    cipherName, plain, 1, plain.Length - 3);

                byte[] iv = new byte[c2.GetBlockSize()];

                c2.Init(false, new ParametersWithIV(key, iv));

                encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null));

                if (encData is SymmetricEncIntegrityPacket)
                {
                    truncStream = new TruncatedStream(encStream);

                    string  digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
                    IDigest digest     = DigestUtilities.GetDigest(digestName);

                    encStream = new DigestStream(truncStream, digest, null);
                }

                if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length)
                {
                    throw new EndOfStreamException("unexpected end of stream.");
                }

                int v1 = encStream.ReadByte();
                int v2 = encStream.ReadByte();

                if (v1 < 0 || v2 < 0)
                {
                    throw new EndOfStreamException("unexpected end of stream.");
                }

                // Note: the oracle attack on the "quick check" bytes is deemed
                // a security risk for typical public key encryption usages,
                // therefore we do not perform the check.

//				bool repeatCheckPassed =
//					iv[iv.Length - 2] == (byte)v1
//					&&	iv[iv.Length - 1] == (byte)v2;
//
//				// Note: some versions of PGP appear to produce 0 for the extra
//				// bytes rather than repeating the two previous bytes
//				bool zeroesCheckPassed =
//					v1 == 0
//					&&	v2 == 0;
//
//				if (!repeatCheckPassed && !zeroesCheckPassed)
//				{
//					throw new PgpDataValidationException("quick check failed.");
//				}

                return(encStream);
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception starting decryption", e);
            }
        }
        /// <summary>Return the decrypted data stream for the packet.</summary>
        public Stream GetDataStream(
            PgpPrivateKey privKey)
        {
            IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);

            try
            {
                c1.Init(false, privKey.Key);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("error setting asymmetric cipher", e);
            }

            BigInteger[] keyD = keyData.GetEncSessionKey();

            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt
                || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                byte[] bi = keyD[0].ToByteArray();

                if (bi[0] == 0)
                {
                    c1.ProcessBytes(bi, 1, bi.Length - 1);
                }
                else
                {
                    c1.ProcessBytes(bi, 0, bi.Length);
                }
            }
            else
            {
                ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
                int size = (k.Parameters.P.BitLength + 7) / 8;

                byte[] bi = keyD[0].ToByteArray();

                int diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }

                bi = keyD[1].ToByteArray();

                diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }
            }

            byte[] plain;
            try
            {
                plain = c1.DoFinal();
            }
            catch (Exception e)
            {
                throw new PgpException("exception decrypting secret key", e);
            }

            if (!ConfirmCheckSum(plain))
            {
                throw new PgpKeyValidationException("key checksum failed");
            }

            IBufferedCipher c2;
            string cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag) plain[0]);
            string cName = cipherName;

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

                c2 = CipherUtilities.GetCipher(cName);
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("exception creating cipher", e);
            }

            if (c2 == null)
            {
                return encData.GetInputStream();
            }

            try
            {
                byte[] keyBytes = new byte[plain.Length - 3];
                Array.Copy(plain, 1, keyBytes, 0, keyBytes.Length);

                KeyParameter key = ParameterUtilities.CreateKeyParameter(
                    cipherName, keyBytes);

                byte[] iv = new byte[c2.GetBlockSize()];

                c2.Init(false, new ParametersWithIV(key, iv));

                encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null));

                if (encData is SymmetricEncIntegrityPacket)
                {
                    truncStream = new TruncatedStream(encStream);
                    encStream = new DigestStream(truncStream,
                        DigestUtilities.GetDigest(PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1)), null);
                }

                for (int i = 0; i != iv.Length; i++)
                {
                    int ch = encStream.ReadByte();

                    if (ch < 0)
                    {
                        throw new EndOfStreamException("unexpected end of stream.");
                    }

                    iv[i] = (byte)ch;
                }

                int v1 = encStream.ReadByte();
                int v2 = encStream.ReadByte();

                if (v1 < 0 || v2 < 0)
                {
                    throw new EndOfStreamException("unexpected end of stream.");
                }

                // Note: the oracle attack on the "quick check" bytes is deemed
                // a security risk for typical public key encryption usages,
                // therefore we do not perform the check.

            //				bool repeatCheckPassed =
            //					iv[iv.Length - 2] == (byte)v1
            //					&&	iv[iv.Length - 1] == (byte)v2;
            //
            //				// Note: some versions of PGP appear to produce 0 for the extra
            //				// bytes rather than repeating the two previous bytes
            //				bool zeroesCheckPassed =
            //					v1 == 0
            //					&&	v2 == 0;
            //
            //				if (!repeatCheckPassed && !zeroesCheckPassed)
            //				{
            //					throw new PgpDataValidationException("quick check failed.");
            //				}

                return encStream;
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception starting decryption", e);
            }
        }
        private byte[] fetchSymmetricKeyData(
            PgpPrivateKey privKey)
        {
            IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);

            try
            {
                c1.Init(false, privKey.Key);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("error setting asymmetric cipher", e);
            }

            BigInteger[] keyD = keyData.GetEncSessionKey();

            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt ||
                keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                c1.ProcessBytes(keyD[0].ToByteArrayUnsigned());
            }
            else
            {
                ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
                int size = (k.Parameters.P.BitLength + 7) / 8;

                byte[] bi = keyD[0].ToByteArray();

                int diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }

                bi = keyD[1].ToByteArray();

                diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }
            }

            byte[] plain;
            try
            {
                plain = c1.DoFinal();
            }
            catch (Exception e)
            {
                throw new PgpException("exception decrypting secret key", e);
            }

            if (!ConfirmCheckSum(plain))
            {
                throw new PgpKeyValidationException("key checksum failed");
            }

            return(plain);
        }
 private static PgpObjectFactory getClearDataStream(PgpPrivateKey privateKey, PgpPublicKeyEncryptedData publicKeyED)
 {
     Stream clearStream = publicKeyED.GetDataStream(privateKey);
     PgpObjectFactory clearFactory = new PgpObjectFactory(clearStream);
     return clearFactory;
 }
		/// <summary>Return the decrypted data stream for the packet.</summary>
        public Stream GetDataStream(
            PgpPrivateKey privKey)
        {
			byte[] plain = fetchSymmetricKeyData(privKey);

			IBufferedCipher c2;
			string cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag) plain[0]);
			string cName = cipherName;

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

				c2 = CipherUtilities.GetCipher(cName);
			}
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("exception creating cipher", e);
            }

			if (c2 == null)
				return encData.GetInputStream();

			try
            {
				KeyParameter key = ParameterUtilities.CreateKeyParameter(
					cipherName, plain, 1, plain.Length - 3);

				byte[] iv = new byte[c2.GetBlockSize()];

				c2.Init(false, new ParametersWithIV(key, iv));

                encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null));

				if (encData is SymmetricEncIntegrityPacket)
                {
                    truncStream = new TruncatedStream(encStream);

					string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
					IDigest digest = DigestUtilities.GetDigest(digestName);

					encStream = new DigestStream(truncStream, digest, null);
                }

				if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length)
					throw new EndOfStreamException("unexpected end of stream.");

				int v1 = encStream.ReadByte();
                int v2 = encStream.ReadByte();

				if (v1 < 0 || v2 < 0)
                    throw new EndOfStreamException("unexpected end of stream.");

				// Note: the oracle attack on the "quick check" bytes is deemed
				// a security risk for typical public key encryption usages,
				// therefore we do not perform the check.

//				bool repeatCheckPassed =
//					iv[iv.Length - 2] == (byte)v1
//					&&	iv[iv.Length - 1] == (byte)v2;
//
//				// Note: some versions of PGP appear to produce 0 for the extra
//				// bytes rather than repeating the two previous bytes
//				bool zeroesCheckPassed =
//					v1 == 0
//					&&	v2 == 0;
//
//				if (!repeatCheckPassed && !zeroesCheckPassed)
//				{
//					throw new PgpDataValidationException("quick check failed.");
//				}

				return encStream;
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception starting decryption", e);
            }
		}
        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);
            }
        }
Beispiel #35
0
        /// <summary>
        /// Attempt to decrypt a PGP protected message using the matching private key.
        /// </summary>
        /// <param name="messageStream">Stream containing the message to decrypt.</param>
        /// <param name="decryptedMessageStream">Stream to write the decrypted message into.</param>
        /// <param name="recipientPrivateKey">The BouncyCastle private key to be used for decryption.</param>
        /// <remarks>The message should be passed in without ASCII Armor.</remarks>
        /// <returns>Whether the decryption completed successfully.</returns>
        public static bool Decrypt(Stream messageStream, Stream decryptedMessageStream, PgpPrivateKey recipientPrivateKey)
        {
            // Decode from Base-64.
            using (Stream decoderStream = PgpUtilities.GetDecoderStream(messageStream))
            {
                // Extract the encrypted data list.
                PgpObjectFactory pgpObjectFactory = new PgpObjectFactory(decoderStream);
                PgpObject pgpObject = pgpObjectFactory.NextPgpObject();
                while (!(pgpObject is PgpEncryptedDataList))
                {
                    pgpObject = pgpObjectFactory.NextPgpObject();
                    if (pgpObject == null)
                        return false;
                }
                PgpEncryptedDataList pgpEncryptedDataList = pgpObject as PgpEncryptedDataList;

                // Attempt to extract the encrypted data stream.
                Stream decryptedStream = null;
                foreach (PgpPublicKeyEncryptedData pgpEncryptedData in pgpEncryptedDataList.GetEncryptedDataObjects().Cast<PgpPublicKeyEncryptedData>()){
                    if (pgpEncryptedData.KeyId == recipientPrivateKey.KeyId)
                        decryptedStream = pgpEncryptedData.GetDataStream(recipientPrivateKey);
                }

                // If we're unable to decrypt any of the streams, fail.
                if (decryptedStream == null)
                    return false;

                PgpObjectFactory clearPgpObjectFactory = new PgpObjectFactory(decryptedStream);
                PgpObject message = clearPgpObjectFactory.NextPgpObject();

                // Deal with compression.
                if (message is PgpCompressedData)
                {
                    PgpCompressedData compressedMessage = (PgpCompressedData)message;
                    using (Stream compressedDataStream = compressedMessage.GetDataStream())
                    {
                        PgpObjectFactory compressedPgpObjectFactory = new PgpObjectFactory(compressedDataStream);

                        pgpObject = compressedPgpObjectFactory.NextPgpObject();
                        while (!(pgpObject is PgpLiteralData))
                        {
                            pgpObject = compressedPgpObjectFactory.NextPgpObject();
                            if (pgpObject == null)
                                return false;
                        }
                    }
                }
                else if (message is PgpLiteralData)
                {
                    pgpObject = message;
                }
                else
                {
                    // If not compressed and the following object isn't literal data, fail.
                    decryptedStream.Dispose();
                    return false;
                }

                // If a literal data stream was found, extract the decrypted message.
                PgpLiteralData literalData = pgpObject as PgpLiteralData;
                if (literalData != null)
                {
                    using (Stream literalDataStream = literalData.GetDataStream())
                    {
                        literalDataStream.CopyTo(decryptedMessageStream);
                    }

                    decryptedStream.Dispose();
                    return true;
                }
            }

            return false;
        }
        internal PgpSecretKey(
            PgpPrivateKey privKey,
            PgpPublicKey pubKey,
            SymmetricKeyAlgorithmTag encAlgorithm,
            char[]                                              passPhrase,
            bool useSha1,
            SecureRandom rand,
            bool isMasterKey)
        {
            BcpgObject secKey;

            this.pub = pubKey;

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

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

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

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

            try
            {
                MemoryStream     bOut = new MemoryStream();
                BcpgOutputStream pOut = new BcpgOutputStream(bOut);

                pOut.WriteObject(secKey);

                byte[] keyData      = bOut.ToArray();
                byte[] checksumData = Checksum(useSha1, keyData, keyData.Length);

                keyData = Arrays.Concatenate(keyData, checksumData);

                if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
                {
                    if (isMasterKey)
                    {
                        this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, keyData);
                    }
                    else
                    {
                        this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, keyData);
                    }
                }
                else
                {
                    S2k    s2k;
                    byte[] iv;

                    byte[] encData;
                    if (pub.Version >= 4)
                    {
                        encData = EncryptKeyData(keyData, encAlgorithm, passPhrase, rand, out s2k, out iv);
                    }
                    else
                    {
                        // TODO v3 RSA key encryption
                        throw Platform.CreateNotImplementedException("v3 RSA");
                    }

                    int s2kUsage = useSha1
                        ?       SecretKeyPacket.UsageSha1
                        :       SecretKeyPacket.UsageChecksum;

                    if (isMasterKey)
                    {
                        this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
                    }
                    else
                    {
                        this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
                    }
                }
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception encrypting key", e);
            }
        }
Beispiel #37
0
 /// <summary>
 /// Attempt to sign a PGP message using the specific private key.
 /// </summary>
 /// <param name="message">Byte array containing the message to sign.</param>
 /// <param name="signatureStream">Stream to write the signature into.</param>
 /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param>
 /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param>
 /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param>
 /// <param name="armor">Whether to wrap the message with ASCII armor.</param>
 /// <returns>Whether the signature completed successfully.</returns>
 public static bool Sign(byte[] message, Stream signatureStream, PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, bool armor = true)
 {
     using (MemoryStream messageStream = new MemoryStream(message))
     {
         return Sign(messageStream, signatureStream, senderPublicKey, senderPrivateKey, hashAlgorithmTag, armor);
     }
 }
		/// <summary>Initialise the generator for signing.</summary>
        public void InitSign(
            int				sigType,
            PgpPrivateKey	key)
        {
			InitSign(sigType, key, null);
        }
Beispiel #39
0
        /// <summary>
        /// Attempt to sign a PGP message using the specific private key.
        /// </summary>
        /// <param name="messageStream">Stream containing the message to sign.</param>
        /// <param name="signature">If successful, the signature.</param>
        /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param>
        /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param>
        /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param>
        /// <param name="armor">Whether to wrap the message with ASCII armor.</param>
        /// <returns>Whether the signature completed successfully.</returns>
        public static bool Sign(Stream messageStream, out byte[] signature, PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, bool armor = true)
        {
            using (MemoryStream signatureStream = new MemoryStream())
            {
                bool signed = Sign(messageStream, signatureStream, senderPublicKey, senderPrivateKey, hashAlgorithmTag, armor);
                if (signed)
                    signature = signatureStream.ToArray();
                else
                    signature = null;

                return signed;
            }
        }
        /// <summary>
        /// Attempt to sign a PGP message using the specific private key.
        /// </summary>
        /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param>
        /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param>
        /// <param name="recipientPublicKeys">Collection of BouncyCastle public keys to be used for encryption.</param>
        /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param>
        /// <returns>Whether the signature completed successfully.</returns>
        public bool PgpSign(PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256)
        {
            // Ensure a valid encoding.
            if (BodyEncoding == null)
                BodyEncoding = Encoding.UTF8;

            byte[] signatureBytes;
            if (Pgp.Sign(BodyEncoding.GetBytes(Body), out signatureBytes, senderPublicKey, senderPrivateKey, hashAlgorithmTag))
            {
                // Fix up a formatting bug in BouncyCastle.
                RawBody = Encoding.UTF8.GetString(signatureBytes).Replace("-----BEGIN PGP SIGNATURE-----", "\r\n-----BEGIN PGP SIGNATURE-----");

                return true;
            }

            return false;
        }
Beispiel #41
0
        /// <summary>
        /// Attempt to sign a PGP message using the specific private key.
        /// </summary>
        /// <param name="messageStream">Stream containing the message to sign.</param>
        /// <param name="signatureStream">Stream to write the signature into.</param>
        /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param>
        /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param>
        /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param>
        /// <param name="armor">Whether to wrap the message with ASCII armor.</param>
        /// <returns>Whether the signature completed successfully.</returns>
        public static bool Sign(Stream messageStream, Stream signatureStream, PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, bool armor = true)
        {
            // Create a signature generator.
            PgpSignatureGenerator signatureGenerator = new PgpSignatureGenerator(senderPublicKey.Algorithm, hashAlgorithmTag);
            signatureGenerator.InitSign(PgpSignature.BinaryDocument, senderPrivateKey);

            // Add the public key user ID.
            foreach (string userId in senderPublicKey.GetUserIds())
            {
                PgpSignatureSubpacketGenerator signatureSubGenerator = new PgpSignatureSubpacketGenerator();
                signatureSubGenerator.SetSignerUserId(false, userId);
                signatureGenerator.SetHashedSubpackets(signatureSubGenerator.Generate());
                break;
            }

            // Handle ASCII armor.
            if (armor)
            {
                using (ArmoredOutputStream armoredStream = new ArmoredOutputStream(signatureStream))
                {
                    armoredStream.BeginClearText(hashAlgorithmTag);

                    // Process each character in the message.
                    int messageChar;
                    while ((messageChar = messageStream.ReadByte()) >= 0)
                    {
                        armoredStream.WriteByte((byte)messageChar);
                        signatureGenerator.Update((byte)messageChar);
                    }

                    armoredStream.EndClearText();

                    using (BcpgOutputStream bcpgStream = new BcpgOutputStream(armoredStream))
                    {
                        signatureGenerator.Generate().Encode(bcpgStream);
                    }
                }
            }
            else
            {
                // Process each character in the message.
                int messageChar;
                while ((messageChar = messageStream.ReadByte()) >= 0)
                {
                    signatureGenerator.Update((byte)messageChar);
                }

                signatureGenerator.Generate().Encode(signatureStream);
            }

            return true;
        }
        /// <summary>
        /// Attempt to sign then encrypt a message using PGP with the specified private and public keys.
        /// </summary>
        /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param>
        /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param>
        /// <param name="recipientPublicKeys">Collection of BouncyCastle public keys to be used for encryption.</param>
        /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param>
        /// <param name="symmetricKeyAlgorithmTag">The symmetric key algorithm tag to use for encryption.</param>
        /// <returns>Whether the encryption completed successfully.</returns>
        public bool PgpSignAndEncrypt(PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, IEnumerable<PgpPublicKey> recipientPublicKeys, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = SymmetricKeyAlgorithmTag.TripleDes)
        {
            // Ensure a valid encoding.
            if (BodyEncoding == null)
                BodyEncoding = Encoding.UTF8;

            // Attempt to sign.
            bool signedAndEncrypted = false;
            using (MemoryStream signedAndEncryptedMessageStream = new MemoryStream())
            {
                // Attempt to encrypt the message.
                // OpaqueMail optional setting for protecting the subject.
                if (SubjectEncryption && !Body.StartsWith("Subject: "))
                    signedAndEncrypted = Pgp.SignAndEncrypt(BodyEncoding.GetBytes("Subject: " + Subject + "\r\n" + Body), "", signedAndEncryptedMessageStream, senderPublicKey, senderPrivateKey, recipientPublicKeys, hashAlgorithmTag, symmetricKeyAlgorithmTag, true);
                else
                    signedAndEncrypted = Pgp.SignAndEncrypt(BodyEncoding.GetBytes(Body), "", signedAndEncryptedMessageStream, senderPublicKey, senderPrivateKey, recipientPublicKeys, hashAlgorithmTag, symmetricKeyAlgorithmTag, true);

                if (signedAndEncrypted)
                {
                    // OpaqueMail optional setting for protecting the subject.
                    if (SubjectEncryption)
                        Subject = "PGP Encrypted Message";

                    signedAndEncrypted = true;

                    RawBody = BodyEncoding.GetString(signedAndEncryptedMessageStream.ToArray());
                }
            }

            return signedAndEncrypted;
        }
Beispiel #43
0
 /// <summary>
 /// Attempt to encrypt a message using PGP with the specified public key(s).
 /// </summary>
 /// <param name="message">Byte array containing the message to encrypt.</param>
 /// <param name="fileName">File name of for the message.</param>
 /// <param name="signedAndEncryptedMessageStream">Stream to write the signed and encrypted message into.</param>
 /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param>
 /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param>
 /// <param name="recipientPublicKeys">Collection of BouncyCastle public keys to be used for encryption.</param>
 /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param>
 /// <param name="symmetricKeyAlgorithmTag">The symmetric key algorithm tag to use for encryption.</param>
 /// <param name="armor">Whether to wrap the message with ASCII armor.</param>
 /// <returns>Whether the encryption completed successfully.</returns>
 public static bool SignAndEncrypt(byte[] message, string fileName, Stream signedAndEncryptedMessageStream, PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, IEnumerable<PgpPublicKey> recipientPublicKeys, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = SymmetricKeyAlgorithmTag.TripleDes, bool armor = true)
 {
     using (MemoryStream messageStream = new MemoryStream(message))
     {
         return SignAndEncrypt(messageStream, fileName, signedAndEncryptedMessageStream, senderPublicKey, senderPrivateKey, recipientPublicKeys, hashAlgorithmTag, symmetricKeyAlgorithmTag, armor);
     }
 }
Beispiel #44
0
 /// <summary>
 /// Attempt to encrypt a message using PGP with the specified public key(s).
 /// </summary>
 /// <param name="messageStream">Stream containing the message to encrypt.</param>
 /// <param name="fileName">File name of for the message.</param>
 /// <param name="signedAndEncryptedMessage">If successful, the encrypted message.</param>
 /// <param name="senderPublicKey">The BouncyCastle public key associated with the signature.</param>
 /// <param name="senderPrivateKey">The BouncyCastle private key to be used for signing.</param>
 /// <param name="recipientPublicKeys">Collection of BouncyCastle public keys to be used for encryption.</param>
 /// <param name="hashAlgorithmTag">The hash algorithm tag to use for signing.</param>
 /// <param name="symmetricKeyAlgorithmTag">The symmetric key algorithm tag to use for encryption.</param>
 /// <param name="armor">Whether to wrap the message with ASCII armor.</param>
 /// <returns>Whether the encryption completed successfully.</returns>
 public static bool SignAndEncrypt(Stream messageStream, string fileName, out byte[] signedAndEncryptedMessage, PgpPublicKey senderPublicKey, PgpPrivateKey senderPrivateKey, IEnumerable<PgpPublicKey> recipientPublicKeys, HashAlgorithmTag hashAlgorithmTag = HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = SymmetricKeyAlgorithmTag.TripleDes, bool armor = true)
 {
     using (MemoryStream signedAndEncryptedMessageStream = new MemoryStream())
     {
         if (SignAndEncrypt(messageStream, fileName, signedAndEncryptedMessageStream, senderPublicKey, senderPrivateKey, recipientPublicKeys, hashAlgorithmTag, symmetricKeyAlgorithmTag, armor))
         {
             signedAndEncryptedMessage = signedAndEncryptedMessageStream.ToArray();
             return true;
         }
         else
         {
             signedAndEncryptedMessage = null;
             return false;
         }
     }
 }
Beispiel #45
0
        private byte[] RecoverSessionData(PgpPrivateKey privKey)
        {
            byte[][] secKeyData = keyData.GetEncSessionKey();

            if (keyData.Algorithm == PublicKeyAlgorithmTag.ECDH)
            {
                ECDHPublicBcpgKey ecKey    = (ECDHPublicBcpgKey)privKey.PublicKeyPacket.Key;
                X9ECParameters    x9Params = ECKeyPairGenerator.FindECCurveByOid(ecKey.CurveOid);

                byte[] enc = secKeyData[0];

                int    pLen = ((((enc[0] & 0xff) << 8) + (enc[1] & 0xff)) + 7) / 8;
                byte[] pEnc = new byte[pLen];

                Array.Copy(enc, 2, pEnc, 0, pLen);

                byte[] keyEnc = new byte[enc[pLen + 2]];

                Array.Copy(enc, 2 + pLen + 1, keyEnc, 0, keyEnc.Length);

                ECPoint publicPoint = x9Params.Curve.DecodePoint(pEnc);

                ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters)privKey.Key;
                ECPoint S = publicPoint.Multiply(privKeyParams.D).Normalize();

                KeyParameter key = new KeyParameter(Rfc6637Utilities.CreateKey(privKey.PublicKeyPacket, S));

                IWrapper w = PgpUtilities.CreateWrapper(ecKey.SymmetricKeyAlgorithm);
                w.Init(false, key);

                return(PgpPad.UnpadSessionData(w.Unwrap(keyEnc, 0, keyEnc.Length)));
            }

            IBufferedCipher cipher = GetKeyCipher(keyData.Algorithm);

            try
            {
                cipher.Init(false, privKey.Key);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("error setting asymmetric cipher", e);
            }

            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt ||
                keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                byte[] bi = secKeyData[0];

                cipher.ProcessBytes(bi, 2, bi.Length - 2);
            }
            else
            {
                ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
                int size = (k.Parameters.P.BitLength + 7) / 8;

                ProcessEncodedMpi(cipher, size, secKeyData[0]);
                ProcessEncodedMpi(cipher, size, secKeyData[1]);
            }

            try
            {
                return(cipher.DoFinal());
            }
            catch (Exception e)
            {
                throw new PgpException("exception decrypting secret key", e);
            }
        }
        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>Return the decrypted data stream for the packet.</summary>
        public Stream GetDataStream(
            PgpPrivateKey privKey)
        {
            IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);

            try
            {
                c1.Init(false, privKey.Key);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("error setting asymmetric cipher", e);
            }

            BigInteger[] keyD = keyData.GetEncSessionKey();

            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt ||
                keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                byte[] bi = keyD[0].ToByteArray();

                if (bi[0] == 0)
                {
                    c1.ProcessBytes(bi, 1, bi.Length - 1);
                }
                else
                {
                    c1.ProcessBytes(bi, 0, bi.Length);
                }
            }
            else
            {
                ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
                int size = (k.Parameters.P.BitLength + 7) / 8;

                byte[] bi = keyD[0].ToByteArray();

                int diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }

                bi = keyD[1].ToByteArray();

                diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }
            }

            byte[] plain;
            try
            {
                plain = c1.DoFinal();
            }
            catch (Exception e)
            {
                throw new PgpException("exception decrypting secret key", e);
            }

            if (!ConfirmCheckSum(plain))
            {
                throw new PgpKeyValidationException("key checksum failed");
            }

            IBufferedCipher c2;
            string          cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag)plain[0]);
            string          cName      = cipherName;

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

                c2 = CipherUtilities.GetCipher(cName);
            }
//            catch (NoSuchProviderException e)
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("exception creating cipher", e);
            }

            if (c2 == null)
            {
                return(encData.GetInputStream());
            }

            try
            {
                byte[] keyBytes = new byte[plain.Length - 3];
                Array.Copy(plain, 1, keyBytes, 0, keyBytes.Length);

                KeyParameter key = ParameterUtilities.CreateKeyParameter(
                    cipherName, keyBytes);

                byte[] iv = new byte[c2.GetBlockSize()];

                c2.Init(false, new ParametersWithIV(key, iv));

                encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null));

                if (encData is SymmetricEncIntegrityPacket)
                {
                    truncStream = new TruncatedStream(encStream);
                    encStream   = new DigestStream(truncStream,
                                                   DigestUtilities.GetDigest(PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1)), null);
                }

                for (int i = 0; i != iv.Length; i++)
                {
                    int ch = encStream.ReadByte();

                    if (ch < 0)
                    {
                        throw new EndOfStreamException("unexpected end of stream.");
                    }

                    iv[i] = (byte)ch;
                }

                int v1 = encStream.ReadByte();
                int v2 = encStream.ReadByte();

                if (v1 < 0 || v2 < 0)
                {
                    throw new EndOfStreamException("unexpected end of stream.");
                }

                // Note: the oracle attack on the "quick check" bytes is deemed
                // a security risk for typical public key encryption usages,
                // therefore we do not perform the check.

//				bool repeatCheckPassed =
//					iv[iv.Length - 2] == (byte)v1
//					&&	iv[iv.Length - 1] == (byte)v2;
//
//				// Note: some versions of PGP appear to produce 0 for the extra
//				// bytes rather than repeating the two previous bytes
//				bool zeroesCheckPassed =
//					v1 == 0
//					&&	v2 == 0;
//
//				if (!repeatCheckPassed && !zeroesCheckPassed)
//				{
//					throw new PgpDataValidationException("quick check failed.");
//				}

                return(encStream);
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception starting decryption", e);
            }
        }
Beispiel #48
0
        internal PgpSecretKey(PgpPrivateKey privKey, PgpPublicKey pubKey, SymmetricKeyAlgorithmTag encAlgorithm, byte[] rawPassPhrase, bool clearPassPhrase, bool useSha1, SecureRandom rand, bool isMasterKey)
        {
            //IL_00cb: Unknown result type (might be due to invalid IL or missing references)
            //IL_00d2: Expected O, but got Unknown
            pub = pubKey;
            BcpgObject bcpgObject;

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

            case PublicKeyAlgorithmTag.Dsa:
            {
                DsaPrivateKeyParameters dsaPrivateKeyParameters = (DsaPrivateKeyParameters)privKey.Key;
                bcpgObject = new DsaSecretBcpgKey(dsaPrivateKeyParameters.X);
                break;
            }

            case PublicKeyAlgorithmTag.EC:
            case PublicKeyAlgorithmTag.ECDsa:
            {
                ECPrivateKeyParameters eCPrivateKeyParameters = (ECPrivateKeyParameters)privKey.Key;
                bcpgObject = new ECSecretBcpgKey(eCPrivateKeyParameters.D);
                break;
            }

            case PublicKeyAlgorithmTag.ElGamalEncrypt:
            case PublicKeyAlgorithmTag.ElGamalGeneral:
            {
                ElGamalPrivateKeyParameters elGamalPrivateKeyParameters = (ElGamalPrivateKeyParameters)privKey.Key;
                bcpgObject = new ElGamalSecretBcpgKey(elGamalPrivateKeyParameters.X);
                break;
            }

            default:
                throw new PgpException("unknown key class");
            }
            try
            {
                MemoryStream     val = new MemoryStream();
                BcpgOutputStream bcpgOutputStream = new BcpgOutputStream((Stream)(object)val);
                bcpgOutputStream.WriteObject(bcpgObject);
                byte[] array = val.ToArray();
                byte[] b     = Checksum(useSha1, array, array.Length);
                array = Arrays.Concatenate(array, b);
                if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
                {
                    if (isMasterKey)
                    {
                        secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, array);
                    }
                    else
                    {
                        secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, array);
                    }
                    return;
                }
                S2k    s2k;
                byte[] iv;
                byte[] secKeyData = ((pub.Version < 4) ? EncryptKeyDataV3(array, encAlgorithm, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv) : EncryptKeyDataV4(array, encAlgorithm, HashAlgorithmTag.Sha1, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv));
                int    s2kUsage   = (useSha1 ? 254 : 255);
                if (isMasterKey)
                {
                    secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, secKeyData);
                }
                else
                {
                    secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, secKeyData);
                }
            }
            catch (PgpException ex)
            {
                throw ex;
            }
            catch (global::System.Exception exception)
            {
                throw new PgpException("Exception encrypting key", exception);
            }
        }
        private byte[] RecoverSessionData(PgpPrivateKey privKey)
		{
            byte[][] secKeyData = keyData.GetEncSessionKey();

            if (keyData.Algorithm == PublicKeyAlgorithmTag.ECDH)
            {
                ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)privKey.PublicKeyPacket.Key;
                X9ECParameters x9Params = ECKeyPairGenerator.FindECCurveByOid(ecKey.CurveOid);

                byte[] enc = secKeyData[0];

                int pLen = ((((enc[0] & 0xff) << 8) + (enc[1] & 0xff)) + 7) / 8;
                byte[] pEnc = new byte[pLen];

                Array.Copy(enc, 2, pEnc, 0, pLen);

                byte[] keyEnc = new byte[enc[pLen + 2]];

                Array.Copy(enc, 2 + pLen + 1, keyEnc, 0, keyEnc.Length);

                ECPoint publicPoint = x9Params.Curve.DecodePoint(pEnc);

                ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters)privKey.Key;
                ECPoint S = publicPoint.Multiply(privKeyParams.D).Normalize();

                KeyParameter key = new KeyParameter(Rfc6637Utilities.CreateKey(privKey.PublicKeyPacket, S));

                IWrapper w = PgpUtilities.CreateWrapper(ecKey.SymmetricKeyAlgorithm);
                w.Init(false, key);

                return PgpPad.UnpadSessionData(w.Unwrap(keyEnc, 0, keyEnc.Length));
            }

            IBufferedCipher cipher = GetKeyCipher(keyData.Algorithm);

            try
			{
                cipher.Init(false, privKey.Key);
			}
			catch (InvalidKeyException e)
			{
				throw new PgpException("error setting asymmetric cipher", e);
			}

            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt
				|| keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
			{
                byte[] bi = secKeyData[0];

                cipher.ProcessBytes(bi, 2, bi.Length - 2);
			}
			else
			{
				ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
				int size = (k.Parameters.P.BitLength + 7) / 8;

                ProcessEncodedMpi(cipher, size, secKeyData[0]);
                ProcessEncodedMpi(cipher, size, secKeyData[1]);
			}

            try
			{
                return cipher.DoFinal();
			}
			catch (Exception e)
			{
				throw new PgpException("exception decrypting secret key", e);
			}
		}