Inheritance: CmsContentInfoParser
Ejemplo n.º 1
0
        /// <summary>
        /// Decrypt the specified encryptedData.
        /// </summary>
        /// <returns>The decrypted <see cref="MimeKit.MimeEntity"/>.</returns>
        /// <param name="encryptedData">The encrypted data.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="encryptedData"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public override MimeEntity Decrypt(Stream encryptedData)
        {
            if (encryptedData == null)
                throw new ArgumentNullException ("encryptedData");

            var parser = new CmsEnvelopedDataParser (encryptedData);
            var recipients = parser.GetRecipientInfos ();
            var algorithm = parser.EncryptionAlgorithmID;
            AsymmetricKeyParameter key;

            foreach (RecipientInformation recipient in recipients.GetRecipients ()) {
                if ((key = GetPrivateKey (recipient.RecipientID)) == null)
                    continue;

                var content = recipient.GetContent (key);

                using (var memory = new MemoryStream (content, false)) {
                    return MimeEntity.Load (memory);
                }
            }

            throw new CmsException ("A suitable private key could not be found for decrypting.");
        }
		public void TestOriginatorInfo()
		{
			CmsEnvelopedDataParser env = new CmsEnvelopedDataParser(CmsSampleMessages.originatorMessage);

			env.GetRecipientInfos();

			Assert.AreEqual(CmsEnvelopedDataGenerator.DesEde3Cbc, env.EncryptionAlgOid);
		}
		public void TestWorkingData()
		{
			byte[] keyData = Base64.Decode(
				"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKrAz/SQKrcQ" +
				"nj9IxHIfKDbuXsMqUpI06s2gps6fp7RDNvtUDDMOciWGFhD45YSy8GO0mPx3" +
				"Nkc7vKBqX4TLcqLUz7kXGOHGOwiPZoNF+9jBMPNROe/B0My0PkWg9tuq+nxN" +
				"64oD47+JvDwrpNOS5wsYavXeAW8Anv9ZzHLU7KwZAgMBAAECgYA/fqdVt+5K" +
				"WKGfwr1Z+oAHvSf7xtchiw/tGtosZ24DOCNP3fcTXUHQ9kVqVkNyzt9ZFCT3" +
				"bJUAdBQ2SpfuV4DusVeQZVzcROKeA09nPkxBpTefWbSDQGhb+eZq9L8JDRSW" +
				"HyYqs+MBoUpLw7GKtZiJkZyY6CsYkAnQ+uYVWq/TIQJBAP5zafO4HUV/w4KD" +
				"VJi+ua+GYF1Sg1t/dYL1kXO9GP1p75YAmtm6LdnOCas7wj70/G1YlPGkOP0V" +
				"GFzeG5KAmAUCQQCryvKU9nwWA+kypcQT9Yr1P4vGS0APYoBThnZq7jEPc5Cm" +
				"ZI82yseSxSeea0+8KQbZ5mvh1p3qImDLEH/iNSQFAkAghS+tboKPN10NeSt+" +
				"uiGRRWNbiggv0YJ7Uldcq3ZeLQPp7/naiekCRUsHD4Qr97OrZf7jQ1HlRqTu" +
				"eZScjMLhAkBNUMZCQnhwFAyEzdPkQ7LpU1MdyEopYmRssuxijZao5JLqQAGw" +
				"YCzXokGFa7hz72b09F4DQurJL/WuDlvvu4jdAkEAxwT9lylvfSfEQw4/qQgZ" +
				"MFB26gqB6Gqs1pHIZCzdliKx5BO3VDeUGfXMI8yOkbXoWbYx5xPid/+N8R//" +
				"+sxLBw==");

			byte[] envData = Base64.Decode(
				"MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1C" +
				"b3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBHjANBgkqhkiG9w0BAQEFAASB" +
				"gDmnaDZ0vDJNlaUSYyEXsgbaUH+itNTjCOgv77QTX2ImXj+kTctM19PQF2I1" +
				"0/NL0fjakvCgBTHKmk13a7jqB6cX3bysenHNrglHsgNGgeXQ7ggAq5fV/JQQ" +
				"T7rSxEtuwpbuHQnoVUZahOHVKy/a0uLr9iIh1A3y+yZTZaG505ZJMIAGCSqG" +
				"SIb3DQEHATAdBglghkgBZQMEAQIEENmkYNbDXiZxJWtq82qIRZKggAQgkOGr" +
				"1JcTsADStez1eY4+rO4DtyBIyUYQ3pilnbirfPkAAAAAAAAAAAAA");


			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(envData);

			RecipientInformationStore recipients = ep.GetRecipientInfos();

			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);

			ICollection c = recipients.GetRecipients();

//            PKCS8EncodedKeySpec	keySpec = new PKCS8EncodedKeySpec(keyData);
//            KeyFactory			keyFact = KeyFactory.GetInstance("RSA");
//            Key					priKey = keyFact.generatePrivate(keySpec);
			AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(keyData);
            byte[] data = Hex.Decode("57616c6c6157616c6c6157617368696e67746f6e");

			foreach (RecipientInformation recipient in c)
			{
				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);

				CmsTypedStream recData = recipient.GetContentStream(priKey);

				byte[] compare = CmsTestUtil.StreamToByteArray(recData.ContentStream);
				Assert.IsTrue(Arrays.AreEqual(data, compare));
			}
		}
		public void TestTwoAesKek()
		{
			byte[] data = Encoding.Default.GetBytes("WallaWallaWashington");
			KeyParameter kek1 = CmsTestUtil.MakeAes192Key();
			KeyParameter kek2 = CmsTestUtil.MakeAes192Key();

			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();

			byte[]  kekId1 = new byte[] { 1, 2, 3, 4, 5 };
			byte[]  kekId2 = new byte[] { 5, 4, 3, 2, 1 };

			edGen.AddKekRecipient("AES192", kek1, kekId1);
			edGen.AddKekRecipient("AES192", kek2, kekId2);

			MemoryStream bOut = new MemoryStream();

			Stream outStream = edGen.Open(
				bOut,
				CmsEnvelopedDataGenerator.DesEde3Cbc);
			outStream.Write(data, 0, data.Length);

			outStream.Close();

			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray());

			RecipientInformationStore recipients = ep.GetRecipientInfos();

			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc);

			RecipientID recSel = new RecipientID();

			recSel.KeyIdentifier = kekId2;

			RecipientInformation recipient = recipients.GetFirstRecipient(recSel);

			Assert.AreEqual(recipient.KeyEncryptionAlgOid, "2.16.840.1.101.3.4.1.25");

			CmsTypedStream recData = recipient.GetContentStream(kek2);

			Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream)));

			ep.Close();
		}
		public void TestECKeyAgree()
		{
			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");

			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();

			edGen.AddKeyAgreementRecipient(
				CmsEnvelopedDataGenerator.ECDHSha1Kdf,
				OrigECKP.Private,
				OrigECKP.Public,
				ReciECCert,
				CmsEnvelopedDataGenerator.Aes128Wrap);

			MemoryStream bOut = new MemoryStream();

			Stream outStr = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc);
			outStr.Write(data, 0, data.Length);

			outStr.Close();

			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray());

			RecipientInformationStore recipients = ep.GetRecipientInfos();

			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);

			RecipientID recSel = new RecipientID();

//			recSel.SetIssuer(PrincipalUtilities.GetIssuerX509Principal(ReciECCert).GetEncoded());
			recSel.Issuer = PrincipalUtilities.GetIssuerX509Principal(ReciECCert);
			recSel.SerialNumber = ReciECCert.SerialNumber;

			RecipientInformation recipient = recipients.GetFirstRecipient(recSel);

			CmsTypedStream recData = recipient.GetContentStream(ReciECKP.Private);

			Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream)));

			ep.Close();
		}
		public void TestAesKek()
		{
			byte[] data = Encoding.Default.GetBytes("WallaWallaWashington");
			KeyParameter kek = CmsTestUtil.MakeAes192Key();

			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();

			byte[] kekId = new byte[] { 1, 2, 3, 4, 5 };

			edGen.AddKekRecipient("AES192", kek, kekId);

			MemoryStream  bOut = new MemoryStream();

			Stream outStream = edGen.Open(
				bOut,
				CmsEnvelopedDataGenerator.DesEde3Cbc);
			outStream.Write(data, 0, data.Length);

			outStream.Close();

			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray());

			RecipientInformationStore recipients = ep.GetRecipientInfos();

			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc);

			ICollection c = recipients.GetRecipients();

			foreach (RecipientInformation recipient in c)
			{
				Assert.AreEqual(recipient.KeyEncryptionAlgOid, "2.16.840.1.101.3.4.1.25");

				CmsTypedStream recData = recipient.GetContentStream(kek);

				Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream)));
			}

			ep.Close();
		}
		public void TestKeyTransAes128()
		{
			byte[] data = Encoding.Default.GetBytes("WallaWallaWashington");

			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();

			edGen.AddKeyTransRecipient(ReciCert);

			MemoryStream bOut = new MemoryStream();

			Stream outStream = edGen.Open(
				bOut, CmsEnvelopedDataGenerator.Aes128Cbc);

			outStream.Write(data, 0, data.Length);

			outStream.Close();

			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray());

			RecipientInformationStore recipients = ep.GetRecipientInfos();

			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);

			ICollection c = recipients.GetRecipients();

			foreach (RecipientInformation recipient in c)
			{
				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);

				CmsTypedStream recData = recipient.GetContentStream(ReciKP.Private);

				Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream)));
			}

			ep.Close();
		}
		public void TestKeyTransAes128Throughput()
		{
			byte[] data = new byte[40001];
			for (int i = 0; i != data.Length; i++)
			{
				data[i] = (byte)(i & 0xff);
			}

			//
			// buffered
			//
			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();

			edGen.SetBufferSize(BufferSize);

			edGen.AddKeyTransRecipient(ReciCert);

			MemoryStream bOut = new MemoryStream();

			Stream outStream = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc);

			for (int i = 0; i != data.Length; i++)
			{
				outStream.WriteByte(data[i]);
			}

			outStream.Close();

			CmsEnvelopedDataParser		ep = new CmsEnvelopedDataParser(bOut.ToArray());
			RecipientInformationStore	recipients = ep.GetRecipientInfos();
			ICollection					c = recipients.GetRecipients();

			IEnumerator e = c.GetEnumerator();

			if (e.MoveNext())
			{
				RecipientInformation recipient = (RecipientInformation) e.Current;

				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);

				CmsTypedStream recData = recipient.GetContentStream(ReciKP.Private);

				Stream dataStream = recData.ContentStream;
				MemoryStream dataOut = new MemoryStream();
				int len;
				byte[] buf = new byte[BufferSize];
				int count = 0;

				while (count != 10 && (len = dataStream.Read(buf, 0, buf.Length)) > 0)
				{
					Assert.AreEqual(buf.Length, len);

					dataOut.Write(buf, 0, buf.Length);
					count++;
				}

				len = dataStream.Read(buf, 0, buf.Length);
				dataOut.Write(buf, 0, len);

				Assert.IsTrue(Arrays.AreEqual(data, dataOut.ToArray()));
			}
			else
			{
				Assert.Fail("recipient not found.");
			}
		}
		private void VerifyData(
			byte[]	encodedBytes,
			string	expectedOid,
			byte[]	expectedData)
		{
			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(encodedBytes);
			RecipientInformationStore recipients = ep.GetRecipientInfos();

			Assert.AreEqual(ep.EncryptionAlgOid, expectedOid);

			ICollection c = recipients.GetRecipients();

			foreach (RecipientInformation recipient in c)
			{
				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);

				CmsTypedStream recData = recipient.GetContentStream(ReciKP.Private);

				Assert.IsTrue(Arrays.AreEqual(expectedData, CmsTestUtil.StreamToByteArray(
					recData.ContentStream)));
			}
		}
Ejemplo n.º 10
0
        private SecurityInformation Decrypt(Stream clear, Stream cypher, SecretKey key, DateTime? sealedOn)
        {
            int i;
            bool found;
            StringBuilder algos;
            DateTime date = sealedOn == null ? DateTime.UtcNow : sealedOn.Value;

            trace.TraceEvent(TraceEventType.Information, 0, "Decrypting message for {0} recipient", key == null ? "known" : "unknown");
            try
            {
                SecurityInformation result = new SecurityInformation();
                CmsEnvelopedDataParser cypherData;
                try
                {
                    cypherData = new CmsEnvelopedDataParser(cypher);
                    trace.TraceEvent(TraceEventType.Verbose, 0, "Read the cms header");
                }
                catch (Exception e)
                {
                    trace.TraceEvent(TraceEventType.Error, 0, "The messages isn't encrypted");
                    throw new InvalidMessageException("The message isn't a triple wrapped message", e);
                }
                RecipientInformationStore recipientInfos = cypherData.GetRecipientInfos();
                trace.TraceEvent(TraceEventType.Verbose, 0, "Got the recipient info of the encrypted message");

                i = 0;
                found = false;
                algos = new StringBuilder();
                string encryptionAlgOid = cypherData.EncryptionAlgOid;
                while (!found && i < EteeActiveConfig.Unseal.EncryptionAlgorithms.Count)
                {
                    Oid algo = EteeActiveConfig.Unseal.EncryptionAlgorithms[i++];
                    algos.Append(algo.Value + " (" + algo.FriendlyName + ") ");
                    found = algo.Value == encryptionAlgOid;
                }
                if (!found)
                {
                    result.securityViolations.Add(SecurityViolation.NotAllowedEncryptionAlgorithm);
                    trace.TraceEvent(TraceEventType.Warning, 0, "The encryption algorithm {0} isn't allowed, only {1} are", encryptionAlgOid, algos);
                }
                trace.TraceEvent(TraceEventType.Verbose, 0, "The encryption algorithm is verified: {0}", encryptionAlgOid);

                //Key size of the message should not be checked, size is determined by the algorithm

                //Get recipient, should be receiver.
                RecipientInformation recipientInfo;
                ICipherParameters recipientKey;
                if (key == null)
                {
                    if (encCertStore != null)
                    {
                        //Find find a matching receiver
                        ICollection recipients = recipientInfos.GetRecipients(); //recipients in the message
                        IList<KeyValuePair<RecipientInformation, IList>> allMatches = new List<KeyValuePair<RecipientInformation, IList>>();
                        foreach (RecipientInformation recipient in recipients)
                        {
                            trace.TraceEvent(TraceEventType.Verbose, 0, "The message is addressed to {0} ({1})", recipient.RecipientID.SerialNumber, recipient.RecipientID.Issuer);
                            if (recipient is KeyTransRecipientInformation) {
                                IList matches = (IList) encCertStore.GetMatches(recipient.RecipientID);
                                if (matches.Count > 0)
                                {
                                    allMatches.Add(new KeyValuePair<RecipientInformation, IList>(recipient, matches));
                                }
                            }
                        }

                        //Did we find a receiver?
                        if (allMatches.Count == 0)
                        {
                            trace.TraceEvent(TraceEventType.Error, 0, "The recipients doe not contain any of your your encryption certificates");
                            throw new InvalidMessageException("The message isn't a message that is addressed to you.  Or it is an unaddressed message or it is addressed to somebody else");
                        }

                        //check with encryption cert matches where valid at creation time
                        IList<KeyValuePair<RecipientInformation, IList>> validMatches = new List<KeyValuePair<RecipientInformation, IList>>();
                        foreach (KeyValuePair<RecipientInformation, IList> match in allMatches)
                        {
                            IList validCertificate = new List<X509Certificate2>();
                            foreach (X509Certificate2 cert in match.Value)
                            {
                                //Validate the description cert, providing minimal info to force minimal validation.
                                CertificateSecurityInformation certVerRes = CertVerifier.VerifyEnc(DotNetUtilities.FromX509Certificate(cert), null, date, null, false);
                                trace.TraceEvent(TraceEventType.Verbose, 0, "Validated potential decryption certificate ({0}) : Validation Status = {1}, Trust Status = {2}",
                                    cert.Subject, certVerRes.ValidationStatus, certVerRes.TrustStatus);
                                if (certVerRes.SecurityViolations.Count == 0)
                                {
                                    validCertificate.Add(cert);
                                }
                            }

                            if (validCertificate.Count > 0)
                            {
                                validMatches.Add(new KeyValuePair<RecipientInformation, IList>(match.Key, validCertificate));
                            }
                        }

                        //If we have a valid encCert use that one, otherwise use an invalid one (at least we can read it, but should not use it)
                        X509Certificate2 selectedCert;
                        if (validMatches.Count > 0)
                        {
                            selectedCert = (X509Certificate2)validMatches[0].Value[0];
                            recipientInfo = validMatches[0].Key;
                            trace.TraceEvent(TraceEventType.Information, 0, "Found valid decryption certificate ({0}) that matches one the the recipients", selectedCert.Subject);
                        }
                        else
                        {
                            selectedCert = (X509Certificate2)allMatches[0].Value[0];
                            recipientInfo = allMatches[0].Key;
                            trace.TraceEvent(TraceEventType.Warning, 0, "Found *invalid* decryption certificate ({0}) that matches one the the recipients", selectedCert.Subject);
                        }
                        recipientKey = DotNetUtilities.GetKeyPair(selectedCert.PrivateKey).Private;

                        //we validate the selected certificate again to inform the caller
                        result.Subject = CertVerifier.VerifyEnc(DotNetUtilities.FromX509Certificate(selectedCert),  null, date, null, false);
                    }
                    else
                    {
                        trace.TraceEvent(TraceEventType.Error, 0, "The unsealer does not have an decryption certificate and no symmetric key was provided");
                        throw new InvalidOperationException("There should be an receiver (=yourself) and/or a key provided");
                    }
                }
                else
                {
                    trace.TraceEvent(TraceEventType.Verbose, 0, "Found symmetric key: {0}", key.IdString);

                    RecipientID recipientId = new RecipientID();
                    recipientId.KeyIdentifier = key.Id;
                    recipientInfo = recipientInfos.GetFirstRecipient(recipientId);
                    if (recipientInfo == null)
                    {
                        trace.TraceEvent(TraceEventType.Error, 0, "The symmetric key was not found in this cms message");
                        throw new InvalidMessageException("The key isn't for this unaddressed message");
                    }
                    trace.TraceEvent(TraceEventType.Verbose, 0, "Found symmetric key in recipients of the cms message");

                    //Get receivers key
                    recipientKey = key.BCKey;

                    //Validate the unaddressed key
                    if ((((KeyParameter)recipientKey).GetKey().Length * 8) < EteeActiveConfig.Unseal.MinimumEncryptionKeySize.SymmetricRecipientKey)
                    {
                        result.securityViolations.Add(SecurityViolation.NotAllowedEncryptionKeySize);
                        trace.TraceEvent(TraceEventType.Warning, 0, "The symmetric key was only {0} bits while it should be at least {0}",
                            ((KeyParameter)recipientKey).GetKey().Length * 8,  EteeActiveConfig.Unseal.MinimumEncryptionKeySize.SymmetricRecipientKey);
                    }
                }

                //check if key encryption algorithm is allowed
                i = 0;
                found = false;
                algos = new StringBuilder();
                while (!found && i < EteeActiveConfig.Unseal.KeyEncryptionAlgorithms.Count)
                {
                    Oid algo = EteeActiveConfig.Unseal.KeyEncryptionAlgorithms[i++];
                    algos.Append(algo.Value + " (" + algo.FriendlyName + ") ");
                    found = algo.Value == recipientInfo.KeyEncryptionAlgOid;
                }
                if (!found)
                {
                    result.securityViolations.Add(SecurityViolation.NotAllowedKeyEncryptionAlgorithm);
                    trace.TraceEvent(TraceEventType.Warning, 0, "Encryption algorithm is {0} while it should be one of the following {1}",
                        recipientInfo.KeyEncryptionAlgOid, algos);
                }
                trace.TraceEvent(TraceEventType.Verbose, 0, "Finished verifying the encryption algorithm: {0}", recipientInfo.KeyEncryptionAlgOid);

                //Decrypt!
                CmsTypedStream clearStream = recipientInfo.GetContentStream(recipientKey);
                trace.TraceEvent(TraceEventType.Verbose, 0, "Accessed the encrypted content");

                try
                {
                    clearStream.ContentStream.CopyTo(clear);
                    trace.TraceEvent(TraceEventType.Verbose, 0, "Decrypted the content");
                }
                finally
                {
                    clearStream.ContentStream.Close();
                }

                return result;
            }
            catch (CmsException cmse)
            {
                trace.TraceEvent(TraceEventType.Error, 0, "The message isn't a CMS message");
                throw new InvalidMessageException("The message isn't a triple wrapped message", cmse);
            }
        }