Inheritance: Org.BouncyCastle.Utilities.IO.BaseInputStream
        public static bool ReadAndVerifyFile(Stream inputStream, Stream keyIn, out Stream cleartextOut)
        {
            // Count any exception as BouncyCastle failing to parse something, because of corruption maybe?
            try
            {

                // Disposing this will close the underlying stream, which we don't want to do
                var armouredInputStream = new ArmoredInputStream(inputStream);

                // This stream is returned, so is not disposed
                var cleartextStream = new MemoryStream();

                int chr;

                while ((chr = armouredInputStream.ReadByte()) >= 0 && armouredInputStream.IsClearText())
                {
                    cleartextStream.WriteByte((byte)chr);
                }

                // Strip the trailing newline if set...
                cleartextStream.Position = Math.Max(0, cleartextStream.Position - 2);
                int count = 0;
                if (cleartextStream.ReadByte() == '\r')
                    count++;
                if (cleartextStream.ReadByte() == '\n')
                    count++;
                cleartextStream.SetLength(cleartextStream.Length - count);

                cleartextStream.Position = 0;

                // This will either return inputStream, or a new ArmouredStream(inputStream)
                // Either way, disposing it will close the underlying stream, which we don't want to do
                var decoderStream = PgpUtilities.GetDecoderStream(inputStream);

                var pgpObjectFactory = new PgpObjectFactory(decoderStream);

                var signatureList = (PgpSignatureList)pgpObjectFactory.NextPgpObject();
                var signature = signatureList[0];

                var publicKeyRing = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(keyIn));
                var publicKey = publicKeyRing.GetPublicKey(signature.KeyId);

                signature.InitVerify(publicKey);

                while ((chr = cleartextStream.ReadByte()) > 0)
                {
                    signature.Update((byte)chr);
                }
                cleartextStream.Position = 0;

                cleartextOut = cleartextStream;
                return signature.Verify();
            }
            catch
            {
                cleartextOut = null;
                return false;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Decrypt and verify signature of data.
        /// </summary>
        /// <param name="data">Data to decrypt and verify</param>
        /// <returns>Returns decrypted data if signature verifies.</returns>
        public byte[] DecryptAndVerify(byte[] data, bool ignoreIntegrityCheck = false)
        {
            Context = new CryptoContext(Context);

            var isArmored = ASCIIEncoding.ASCII.GetString(data).IndexOf("-----BEGIN PGP MESSAGE-----") > -1;

            using (var dataIn = new MemoryStream(data))
            {
                if (isArmored)
                {
                    using (var armoredIn = new ArmoredInputStream(dataIn))
                    {
                        var factory = new PgpObjectFactory(armoredIn);

                        while (true)
                        {
                            var obj = factory.NextPgpObject();
                            if (obj is PgpMarker)
                                continue;

                            var ret = DecryptHandlePgpObject(obj);
                            if (Context.FailedIntegrityCheck && !ignoreIntegrityCheck)
                                throw new VerifyException("Data not integrity protected.");

                            return ret;
                        }
                    }
                }
                else
                {
                    var factory = new PgpObjectFactory(dataIn);

                    while (true)
                    {
                        var obj = factory.NextPgpObject();
                        if (obj is PgpMarker)
                            continue;

                        var ret = DecryptHandlePgpObject(obj);
                        if (Context.FailedIntegrityCheck && !ignoreIntegrityCheck)
                            throw new VerifyException("Data not integrity protected.");

                        return ret;
                    }
                }
            }
        }
        /// <summary>
        /// Decrypt and verify signature of data.
        /// </summary>
        /// <param name="data">Data to decrypt and verify</param>
        /// <returns>Returns decrypted data if signature verifies.</returns>
        public byte[] DecryptAndVerify(byte[] data)
        {
            Context = new CryptoContext(Context);

            var isArmored = ASCIIEncoding.ASCII.GetString(data).IndexOf("-----BEGIN PGP MESSAGE-----") > -1;

            using (var dataIn = new MemoryStream(data))
            {
                if (isArmored)
                {
                    using (var armoredIn = new ArmoredInputStream(dataIn))
                    {
                        var factory = new PgpObjectFactory(armoredIn);

                        while (true)
                        {
                            var obj = factory.NextPgpObject();
                            if (obj is PgpMarker)
                                continue;

                            var ret = DecryptHandlePgpObject(obj);
                            return ret;
                        }
                    }
                }
                else
                {
                    var factory = new PgpObjectFactory(dataIn);

                    while (true)
                    {
                        var obj = factory.NextPgpObject();
                        if (obj is PgpMarker)
                            continue;

                        var ret = DecryptHandlePgpObject(obj);
                        return ret;
                    }
                }
            }
        }
		/// <summary>
		/// Verifies the specified content using the detached signatureData.
		/// </summary>
		/// <remarks>
		/// Verifies the specified content using the detached signatureData.
		/// </remarks>
		/// <returns>A list of digital signatures.</returns>
		/// <param name="content">The content.</param>
		/// <param name="signatureData">The signature data.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="content"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signatureData"/> is <c>null</c>.</para>
		/// </exception>
		public override DigitalSignatureCollection Verify (Stream content, Stream signatureData)
		{
			if (content == null)
				throw new ArgumentNullException ("content");

			if (signatureData == null)
				throw new ArgumentNullException ("signatureData");

			using (var armored = new ArmoredInputStream (signatureData)) {
				var factory = new PgpObjectFactory (armored);
				var data = factory.NextPgpObject ();
				PgpSignatureList signatureList;

				var compressed = data as PgpCompressedData;
				if (compressed != null) {
					factory = new PgpObjectFactory (compressed.GetDataStream ());
					data = factory.NextPgpObject ();
				}

				signatureList = (PgpSignatureList) data;

				return GetDigitalSignatures (signatureList, content);
			}
		}
		/// <summary>
		/// Imports secret pgp keys from the specified stream.
		/// </summary>
		/// <remarks>
		/// Imports secret pgp keys from the specified stream.
		/// </remarks>
		/// <param name="rawData">The raw key data.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="rawData"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// <para>An error occurred while parsing the raw key-ring data</para>
		/// <para>-or-</para>
		/// <para>An error occured while saving the public key-ring bundle.</para>
		/// </exception>
		public virtual void ImportSecretKeys (Stream rawData)
		{
			if (rawData == null)
				throw new ArgumentNullException ("rawData");

			using (var armored = new ArmoredInputStream (rawData)) {
				var imported = new PgpSecretKeyRingBundle (armored);
				if (imported.Count == 0)
					return;

				int secretKeysAdded = 0;

				foreach (PgpSecretKeyRing secring in imported.GetKeyRings ()) {
					if (!SecretKeyRingBundle.Contains (secring.GetSecretKey ().KeyId)) {
						SecretKeyRingBundle = PgpSecretKeyRingBundle.AddSecretKeyRing (SecretKeyRingBundle, secring);
						secretKeysAdded++;
					}
				}

				if (secretKeysAdded > 0)
					SaveSecretKeyRingBundle ();
			}
		}
		/// <summary>
		/// Imports public pgp keys from the specified stream.
		/// </summary>
		/// <remarks>
		/// Imports public pgp keys from the specified stream.
		/// </remarks>
		/// <param name="stream">The raw key data.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="stream"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// <para>An error occurred while parsing the raw key-ring data</para>
		/// <para>-or-</para>
		/// <para>An error occured while saving the public key-ring bundle.</para>
		/// </exception>
		public override void Import (Stream stream)
		{
			if (stream == null)
				throw new ArgumentNullException ("stream");

			using (var armored = new ArmoredInputStream (stream)) {
				var imported = new PgpPublicKeyRingBundle (armored);
				if (imported.Count == 0)
					return;

				int publicKeysAdded = 0;

				foreach (PgpPublicKeyRing pubring in imported.GetKeyRings ()) {
					if (!PublicKeyRingBundle.Contains (pubring.GetPublicKey ().KeyId)) {
						PublicKeyRingBundle = PgpPublicKeyRingBundle.AddPublicKeyRing (PublicKeyRingBundle, pubring);
						publicKeysAdded++;
					}
				}

				if (publicKeysAdded > 0)
					SavePublicKeyRingBundle ();
			}
		}
		/// <summary>
		/// Decrypts the specified encryptedData and extracts the digital signers if the content was also signed.
		/// </summary>
		/// <remarks>
		/// Decrypts the specified encryptedData and extracts the digital signers if the content was also signed.
		/// </remarks>
		/// <returns>The decrypted stream.</returns>
		/// <param name="encryptedData">The encrypted data.</param>
		/// <param name="signatures">A list of digital signatures if the data was both signed and encrypted.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="encryptedData"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="PrivateKeyNotFoundException">
		/// The private key could not be found to decrypt the stream.
		/// </exception>
		/// <exception cref="System.OperationCanceledException">
		/// The user chose to cancel the password prompt.
		/// </exception>
		/// <exception cref="System.UnauthorizedAccessException">
		/// 3 bad attempts were made to unlock the secret key.
		/// </exception>
		/// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">
		/// An OpenPGP error occurred.
		/// </exception>
		public Stream GetDecryptedStream (Stream encryptedData, out DigitalSignatureCollection signatures)
		{
			if (encryptedData == null)
				throw new ArgumentNullException ("encryptedData");

			using (var armored = new ArmoredInputStream (encryptedData)) {
				var factory = new PgpObjectFactory (armored);
				var obj = factory.NextPgpObject ();
				var list = obj as PgpEncryptedDataList;

				if (list == null) {
					// probably a PgpMarker...
					obj = factory.NextPgpObject ();

					list = obj as PgpEncryptedDataList;

					if (list == null)
						throw new PgpException ("Unexpected OpenPGP packet.");
				}

				PgpPublicKeyEncryptedData encrypted = null;
				PrivateKeyNotFoundException pkex = null;
				bool hasEncryptedPackets = false;
				PgpSecretKey secret = null;

				foreach (PgpEncryptedData data in list.GetEncryptedDataObjects ()) {
					if ((encrypted = data as PgpPublicKeyEncryptedData) == null)
						continue;

					hasEncryptedPackets = true;

					try {
						secret = GetSecretKey (encrypted.KeyId);
						break;
					} catch (PrivateKeyNotFoundException ex) {
						pkex = ex;
					}
				}

				if (!hasEncryptedPackets)
					throw new PgpException ("No encrypted packets found.");

				if (secret == null)
					throw pkex;

				factory = new PgpObjectFactory (encrypted.GetDataStream (GetPrivateKey (secret)));
				List<IDigitalSignature> onepassList = null;
				PgpSignatureList signatureList = null;
				PgpCompressedData compressed = null;
				var memory = new MemoryBlockStream ();

				obj = factory.NextPgpObject ();
				while (obj != null) {
					if (obj is PgpCompressedData) {
						if (compressed != null)
							throw new PgpException ("Recursive compression packets are not supported.");

						compressed = (PgpCompressedData) obj;
						factory = new PgpObjectFactory (compressed.GetDataStream ());
					} else if (obj is PgpOnePassSignatureList) {
						if (memory.Length == 0) {
							var onepasses = (PgpOnePassSignatureList) obj;

							onepassList = new List<IDigitalSignature> ();

							for (int i = 0; i < onepasses.Count; i++) {
								var onepass = onepasses[i];
								var pubkey = PublicKeyRingBundle.GetPublicKey (onepass.KeyId);

								if (pubkey == null) {
									// too messy, pretend we never found a one-pass signature list
									onepassList = null;
									break;
								}

								onepass.InitVerify (pubkey);

								var signature = new OpenPgpDigitalSignature (pubkey, onepass) {
									PublicKeyAlgorithm = GetPublicKeyAlgorithm (onepass.KeyAlgorithm),
									DigestAlgorithm = GetDigestAlgorithm (onepass.HashAlgorithm),
								};

								onepassList.Add (signature);
							}
						}
					} else if (obj is PgpSignatureList) {
						signatureList = (PgpSignatureList) obj;
					} else if (obj is PgpLiteralData) {
						var literal = (PgpLiteralData) obj;

						using (var stream = literal.GetDataStream ()) {
							var buffer = new byte[4096];
							int nread;

							while ((nread = stream.Read (buffer, 0, buffer.Length)) > 0) {
								if (onepassList != null) {
									// update our one-pass signatures...
									for (int index = 0; index < nread; index++) {
										byte c = buffer[index];

										for (int i = 0; i < onepassList.Count; i++) {
											var pgp = (OpenPgpDigitalSignature) onepassList[i];
											pgp.OnePassSignature.Update (c);
										}
									}
								}

								memory.Write (buffer, 0, nread);
							}
						}
					}

					obj = factory.NextPgpObject ();
				}

				memory.Position = 0;

				if (signatureList != null) {
					if (onepassList != null && signatureList.Count == onepassList.Count) {
						for (int i = 0; i < onepassList.Count; i++) {
							var pgp = (OpenPgpDigitalSignature) onepassList[i];
							pgp.CreationDate = signatureList[i].CreationTime;
							pgp.Signature = signatureList[i];
						}

						signatures = new DigitalSignatureCollection (onepassList);
					} else {
						signatures = GetDigitalSignatures (signatureList, memory);
						memory.Position = 0;
					}
				} else {
					signatures = null;
				}

				return memory;
			}
		}
		public virtual void ImportSecretKeys (Stream rawData)
		{
			if (rawData == null)
				throw new ArgumentNullException (nameof (rawData));

			using (var armored = new ArmoredInputStream (rawData))
				Import (new PgpSecretKeyRingBundle (armored));
		}
		/// <summary>
		/// Imports public pgp keys from the specified stream.
		/// </summary>
		/// <remarks>
		/// Imports public pgp keys from the specified stream.
		/// </remarks>
		/// <param name="stream">The raw key data.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <paramref name="stream"/> is <c>null</c>.
		/// </exception>
		/// <exception cref="System.IO.IOException">
		/// <para>An error occurred while parsing the raw key-ring data</para>
		/// <para>-or-</para>
		/// <para>An error occured while saving the public key-ring bundle.</para>
		/// </exception>
		public override void Import (Stream stream)
		{
			if (stream == null)
				throw new ArgumentNullException (nameof (stream));

			using (var armored = new ArmoredInputStream (stream))
				Import (new PgpPublicKeyRingBundle (armored));
		}
		/// <summary>
		/// Decrypt and verify signature of data.
		/// </summary>
		/// <param name="data">Data to decrypt and verify</param>
		/// <returns>Returns decrypted data if signature verifies.</returns>
		public byte[] DecryptAndVerify(byte[] data, bool ignoreIntegrityCheck = false)
		{
			logger.Trace(string.Format("DecryptAndVerify({0}, {1})", data.Length, ignoreIntegrityCheck));

			Context = new CryptoContext(Context);

			var isArmored = ASCIIEncoding.ASCII.GetString(data).IndexOf("-----BEGIN PGP MESSAGE-----") > -1;

			using (var dataIn = new MemoryStream(data))
			{
				if (isArmored)
				{
					logger.Trace("isArmored");

					using (var armoredIn = new ArmoredInputStream(dataIn))
					{
						var factory = new PgpObjectFactory(armoredIn);

						while (true)
						{
							var obj = factory.NextPgpObject();
							if (obj == null)
								return null;

							if (obj is PgpMarker)
								continue;

							var ret = DecryptHandlePgpObject(obj);
							if (Context.FailedIntegrityCheck && !ignoreIntegrityCheck)
							{
								logger.Error("DecryptAndVerify: Data not integrity protected.");
								throw new VerifyException("Data not integrity protected.");
							}

							logger.Trace("DecryptAndVerify: Returning " +
								(ret == null ? "null" : ret.Length.ToString()) + " bytes");

							return ret;
						}
					}
				}
				else
				{
					var factory = new PgpObjectFactory(dataIn);

					while (true)
					{
						var obj = factory.NextPgpObject();
						if (obj == null)
							return null;

						if (obj is PgpMarker)
							continue;

						var ret = DecryptHandlePgpObject(obj);
						if (Context.FailedIntegrityCheck && !ignoreIntegrityCheck)
						{
							logger.Error("DecryptAndVerify: Data not integrity protected.");
							throw new VerifyException("Data not integrity protected.");
						}

						logger.Trace("DecryptAndVerify: Returning " +
							(ret == null ? "null" : ret.Length.ToString()) + " bytes");

						return ret;
					}
				}
			}
		}
Beispiel #11
0
		/// <summary>
		/// Verifies the specified content using the detached signatureData.
		/// </summary>
		/// <remarks>
		/// Verifies the specified content using the detached signatureData.
		/// </remarks>
		/// <returns>A list of digital signatures.</returns>
		/// <param name="content">The content.</param>
		/// <param name="signatureData">The signature data.</param>
		/// <exception cref="System.ArgumentNullException">
		/// <para><paramref name="content"/> is <c>null</c>.</para>
		/// <para>-or-</para>
		/// <para><paramref name="signatureData"/> is <c>null</c>.</para>
		/// </exception>
		public override DigitalSignatureCollection Verify (Stream content, Stream signatureData)
		{
			if (content == null)
				throw new ArgumentNullException ("content");

			if (signatureData == null)
				throw new ArgumentNullException ("signatureData");

			using (var armored = new ArmoredInputStream (signatureData)) {
				var factory = new PgpObjectFactory (armored);
				var data = factory.NextPgpObject ();
				PgpSignatureList signatureList;

				var compressed = data as PgpCompressedData;
				if (compressed != null) {
					factory = new PgpObjectFactory (compressed.GetDataStream ());
					signatureList = (PgpSignatureList) factory.NextPgpObject ();
				} else {
					// FIXME: this should probably throw a FormatException? Also needs docs.
					if ((signatureList = data as PgpSignatureList) == null)
						throw new Exception ("Unexpected pgp object");
				}

				return GetDigitalSignatures (signatureList, content);
			}
		}
        /// <summary>
        /// Verify signature for cleartext (e.g. emails)
        /// </summary>
        /// <param name="data">Data to verify</param>
        /// <returns>Return true if signature validates, else false.</returns>
        public bool VerifyClear(byte[] data)
        {
            Context = new CryptoContext(Context);

            var crlf = new byte[] { (byte)'\r', (byte)'\n' };
            var encoding = ASCIIEncoding.UTF8;

            using (var dataIn = new MemoryStream(data))
            using (var armoredIn = new ArmoredInputStream(dataIn))
            {
                if (!armoredIn.IsClearText())
                    throw new CryptoException("Error, message is not armored clear-text.");

                var headers = armoredIn.GetArmorHeaders();
                if(headers != null)
                {
                    foreach (var header in headers)
                    {
                        if (Regex.IsMatch(header, @"Charset: ([^\s]*)"))
                        {
                            var encodingType = Regex.Match(header, @"Charset: ([^\s]*)").Groups[1].Value;
                            encoding = Encoding.GetEncoding(encodingType);
                        }
                    }
                }

                using (var clearOut = new MemoryStream())
                {
                    using (var clearIn = new MemoryStream())
                    {
                        int ch = 0;
                        while ((ch = armoredIn.ReadByte()) >= 0 && armoredIn.IsClearText())
                            clearIn.WriteByte((byte)ch);

                        clearIn.Position = 0;

                        using (var stringIn = new StringReader(encoding.GetString(clearIn.ToArray())))
                        {
                            do
                            {
                                var line = stringIn.ReadLine();
                                if (line == null)
                                    break;

                                line = line
                                    .TrimEnd(null)
                                    .TrimEnd(new char[] { ' ', '\t', '\n', '\r' })
                                    .TrimEnd(null)
                                    +"\r\n";

                                var buff = encoding.GetBytes(line);
                                clearOut.Write(buff, 0, buff.Length);
                            }
                            while (true);
                        }
                    }

                    clearOut.Position = 0;

                    var factory = new PgpObjectFactory(armoredIn);
                    var signatureList = (PgpSignatureList)factory.NextPgpObject();
                    var signature = signatureList[0];

                    Context.IsEncrypted = false;
                    Context.IsSigned = true;
                    Context.SignedBy = GetPublicKey(signature.KeyId);

                    if (Context.SignedBy == null)
                        throw new PublicKeyNotFoundException("Public key not found for key id \"" + signature.KeyId + "\".");

                    signature.InitVerify(GetPublicKey(signature.KeyId));
                    signature.Update(clearOut.ToArray(), 0, (int)(clearOut.Length - 2));
                    Context.SignatureValidated = signature.Verify();

                    return Context.SignatureValidated;
                }
            }
        }
        /// <summary>
        /// Verify signature
        /// </summary>
        /// <param name="data">Data to verify</param>
        /// <returns>Return true if signature validates, else false.</returns>
        public bool Verify(byte[] data)
        {
            Context = new CryptoContext(Context);

            using (var dataIn = new MemoryStream(data))
            using (var armoredIn = new ArmoredInputStream(dataIn))
            {
                if (!armoredIn.IsClearText())
                {
                    var factory = new PgpObjectFactory(armoredIn);

                    DecryptHandlePgpObject(factory.NextPgpObject());

                    if (!Context.IsSigned)
                        throw new CryptoException("Error, message is not signed.");

                    return Context.SignatureValidated;
                }
            }

            return VerifyClear(data);
        }
		/// <summary>
		/// Verify signature
		/// </summary>
		/// <param name="data">Data to verify</param>
		/// <returns>Return true if signature validates, else false.</returns>
		public bool Verify(byte[] data)
		{
			Context = new CryptoContext(Context);

			using (var dataIn = new MemoryStream(data))
			using (var armoredIn = new ArmoredInputStream(dataIn))
			{
				if (!armoredIn.IsClearText())
				{
					var factory = new PgpObjectFactory(armoredIn);

					var pgpObject = factory.NextPgpObject();
					if (pgpObject == null)
						return false;

					DecryptHandlePgpObject(pgpObject);
					if (Context.FailedIntegrityCheck)
						throw new VerifyException("Error, failed validation check.");

					if (!Context.IsSigned)
						throw new CryptoException("Error, message is not signed.");

					return Context.SignatureValidated;
				}
			}

			return VerifyClear(data);
		}
Beispiel #15
0
    /// <summary>
    /// Decrypt a PGP message (i.e. "-----BEGIN PGP MESSAGE----- ... -----END PGP MESSAGE-----")
    /// using the supplied private key.
    /// </summary>
    /// <param name="armoredCipher">PGP message to decrypt</param>
    /// <param name="armoredPrivateKey">PGP private key</param>
    /// <param name="keyPassword">PGP private key password or null if none</param>
    /// <returns>decrypted plain text</returns>
    public static string PGPDecrypt(string armoredCipher, string armoredPrivateKey, string keyPassword)
    {
      // decode the private key
      PgpPrivateKey privateKey = null;
      using (MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(armoredPrivateKey)))
      {
        using (Stream dis = PgpUtilities.GetDecoderStream(ms))
        {
          PgpSecretKeyRingBundle bundle = new PgpSecretKeyRingBundle(dis);
          foreach (PgpSecretKeyRing keyring in bundle.GetKeyRings())
          {
            foreach (PgpSecretKey key in keyring.GetSecretKeys())
            {
              privateKey = key.ExtractPrivateKey(keyPassword != null ? keyPassword.ToCharArray() : null);
              break;
            }
          }
        }
      }

      // decrypt armored block using our private key
      byte[] cipher = Encoding.ASCII.GetBytes(armoredCipher);
      using (MemoryStream decryptedStream = new MemoryStream())
      {
        using (MemoryStream inputStream = new MemoryStream(cipher))
        {
          using (ArmoredInputStream ais = new ArmoredInputStream(inputStream))
          {
            PgpObject message = new PgpObjectFactory(ais).NextPgpObject();
            if (message is PgpEncryptedDataList)
            {
              foreach (PgpPublicKeyEncryptedData pked in ((PgpEncryptedDataList)message).GetEncryptedDataObjects())
              {
                message = new PgpObjectFactory(pked.GetDataStream(privateKey)).NextPgpObject();
              }
            }
            if (message is PgpCompressedData)
            {
              message = new PgpObjectFactory(((PgpCompressedData)message).GetDataStream()).NextPgpObject();
            }
            if (message is PgpLiteralData)
            {
              byte[] buffer = new byte[4096];
              using (Stream stream = ((PgpLiteralData)message).GetInputStream())
              {
                int read;
                while ((read = stream.Read(buffer, 0, 4096)) > 0)
                {
                  decryptedStream.Write(buffer, 0, read);
                }
              }
            }

            return Encoding.UTF8.GetString(decryptedStream.ToArray());
          }
        }
      }
		}
Beispiel #16
0
        /// <summary>
        /// Decrypt an encrypted stream.
        /// </summary>
        /// <returns>The decrypted <see cref="MimeKit.MimeEntity"/>.</returns>
        /// <param name="encryptedData">The encrypted data.</param>
        /// <param name="signatures">A list of digital signatures if the data was both signed and encrypted.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="encryptedData"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="PrivateKeyNotFoundException">
        /// The private key could not be found to decrypt the stream.
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The user chose to cancel the password prompt.
        /// </exception>
        /// <exception cref="System.UnauthorizedAccessException">
        /// 3 bad attempts were made to unlock the secret key.
        /// </exception>
        public MimeEntity Decrypt(Stream encryptedData, out DigitalSignatureCollection signatures)
        {
            if (encryptedData == null)
                throw new ArgumentNullException ("encryptedData");

            // FIXME: document the exceptions that can be thrown by BouncyCastle
            using (var armored = new ArmoredInputStream (encryptedData)) {
                var factory = new PgpObjectFactory (armored);
                var obj = factory.NextPgpObject ();
                var list = obj as PgpEncryptedDataList;

                if (list == null) {
                    // probably a PgpMarker...
                    obj = factory.NextPgpObject ();

                    list = obj as PgpEncryptedDataList;
                    if (list == null)
                        throw new Exception ("Unexpected pgp object");
                }

                PgpPublicKeyEncryptedData encrypted = null;
                foreach (PgpEncryptedData data in list.GetEncryptedDataObjects ()) {
                    if ((encrypted = data as PgpPublicKeyEncryptedData) != null)
                        break;
                }

                if (encrypted == null)
                    throw new Exception ("no encrypted data objects found?");

                factory = new PgpObjectFactory (encrypted.GetDataStream (GetPrivateKey (encrypted.KeyId)));
                PgpOnePassSignatureList onepassList = null;
                PgpSignatureList signatureList = null;
                PgpCompressedData compressed = null;

                using (var memory = new MemoryStream ()) {
                    obj = factory.NextPgpObject ();
                    while (obj != null) {
                        if (obj is PgpCompressedData) {
                            if (compressed != null)
                                throw new Exception ("recursive compression detected.");

                            compressed = (PgpCompressedData) obj;
                            factory = new PgpObjectFactory (compressed.GetDataStream ());
                        } else if (obj is PgpOnePassSignatureList) {
                            onepassList = (PgpOnePassSignatureList) obj;
                        } else if (obj is PgpSignatureList) {
                            signatureList = (PgpSignatureList) obj;
                        } else if (obj is PgpLiteralData) {
                            var literal = (PgpLiteralData) obj;

                            using (var stream = literal.GetDataStream ()) {
                                stream.CopyTo (memory, 4096);
                            }
                        }

                        obj = factory.NextPgpObject ();
                    }

                    memory.Position = 0;

                    // FIXME: validate the OnePass signatures... and do what with them?
            //					if (onepassList != null) {
            //						for (int i = 0; i < onepassList.Count; i++) {
            //							var onepass = onepassList[i];
            //						}
            //					}

                    if (signatureList != null) {
                        signatures = GetDigitalSignatures (signatureList, memory);
                        memory.Position = 0;
                    } else {
                        signatures = null;
                    }

                    return MimeEntity.Load (memory);
                }
            }
        }
Beispiel #17
0
        public static bool VerifySig(byte[] asc, string sig, out string message)
        {
            try
            {
                foreach(PgpPublicKey pubkey in new PgpPublicKeyRing(GetStream(asc)).GetPublicKeys().OfType<PgpPublicKey>()) //java madness
                {

                    //AGAIN MADNESS THIS MAKE PERFECT SENSE !
                    ArmoredInputStream sigInput = new ArmoredInputStream(new MemoryStream(Encoding.UTF8.GetBytes(sig)));

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

                    while((ch = sigInput.ReadByte()) >= 0 && sigInput.IsClearText())
                    {
                        if(newLine != null)
                        {
                            foreach(var c in newLine)
                                bOut.WriteByte((byte)c);
                            newLine = null;
                        }
                        if(ch == '\r')
                        {
                            ch = sigInput.ReadByte();
                            if(ch == '\n')
                            {
                                newLine = "\r\n";
                                continue;
                            }
                        }
                        if(ch == '\n')
                        {
                            newLine = "\n";
                            continue;
                        }

                        bOut.WriteByte((byte)ch);
                    }

                    var toSign = bOut.ToArray();
                    message = Encoding.UTF8.GetString(toSign);

                    PgpObjectFactory pgpObjFactory = new PgpObjectFactory(sigInput);
                    var list = (PgpSignatureList)pgpObjFactory.NextPgpObject();
                    PgpSignature pgpSig = list[0];
                    pgpSig.InitVerify(pubkey);
                    pgpSig.Update(toSign);
                    var result = pgpSig.Verify();
                    if(result)
                        return result;
                    Regex endofline = new Regex("[ ]+?(\r?)\n");
                    message = endofline.Replace(message, "$1\n");
                    toSign = Encoding.UTF8.GetBytes(message);
                    pgpSig.InitVerify(pubkey);
                    pgpSig.Update(toSign);
                    result = pgpSig.Verify();
                    if(result)
                        return result;
                }
            }
            catch //Don't do it at home kids
            {

            }
            message = null;
            return false;
        }