/**
        * Generate an object that contains an CMS Compressed Data
        */

        public CmsCompressedData Generate(CmsProcessable content, string compressionOid)
        {
            AlgorithmIdentifier comAlgId;
            Asn1OctetString comOcts;

            try
            {
                using (var bOut = new MemoryStream())
                {
                    using (var zOut = new ZOutputStream(bOut, JZlib.Z_DEFAULT_COMPRESSION))
                    {
                        content.Write(zOut);
                    }

                    comAlgId = new AlgorithmIdentifier(new DerObjectIdentifier(compressionOid));
                    comOcts = new BerOctetString(bOut.ToArray());
                }
            }
            catch (IOException e)
            {
                throw new CmsException("exception encoding data.", e);
            }

            var comContent = new ContentInfo(CmsObjectIdentifiers.Data, comOcts);
            var contentInfo = new ContentInfo(CmsObjectIdentifiers.CompressedData, new CompressedData(comAlgId, comContent));

            return new CmsCompressedData(contentInfo);
        }
		internal override void Encode(
			DerOutputStream derOut)
		{
			if (derOut is Asn1OutputStream || derOut is BerOutputStream)
			{
				derOut.WriteTag((byte)(Asn1Tags.Constructed | Asn1Tags.Tagged), tagNo);
				derOut.WriteByte(0x80);

				if (!IsEmpty())
				{
					if (!explicitly)
					{
						IEnumerable eObj;
						if (obj is Asn1OctetString)
						{
							if (obj is BerOctetString)
							{
								eObj = (BerOctetString) obj;
							}
							else
							{
								Asn1OctetString octs = (Asn1OctetString)obj;
								eObj = new BerOctetString(octs.GetOctets());
							}
						}
						else if (obj is Asn1Sequence)
						{
							eObj = (Asn1Sequence) obj;
						}
						else if (obj is Asn1Set)
						{
							eObj = (Asn1Set) obj;
						}
						else
						{
							throw Platform.CreateNotImplementedException(obj.GetType().Name);
						}

						foreach (Asn1Encodable o in eObj)
						{
							derOut.WriteObject(o);
						}
					}
					else
					{
						derOut.WriteObject(obj);
					}
				}

				derOut.WriteByte(0x00);
				derOut.WriteByte(0x00);
			}
			else
			{
				base.Encode(derOut);
			}
		}
Beispiel #3
0
        internal override void Encode(
            DerOutputStream derOut)
        {
            if (derOut is Asn1OutputStream || derOut is BerOutputStream)
            {
                derOut.WriteTag((byte)(Asn1Tags.Constructed | Asn1Tags.Tagged), tagNo);
                derOut.WriteByte(0x80);

                if (!IsEmpty())
                {
                    if (!explicitly)
                    {
                        IEnumerable eObj;
                        if (obj is Asn1OctetString)
                        {
                            if (obj is BerOctetString)
                            {
                                eObj = (BerOctetString)obj;
                            }
                            else
                            {
                                Asn1OctetString octs = (Asn1OctetString)obj;
                                eObj = new BerOctetString(octs.GetOctets());
                            }
                        }
                        else if (obj is Asn1Sequence)
                        {
                            eObj = (Asn1Sequence)obj;
                        }
                        else if (obj is Asn1Set)
                        {
                            eObj = (Asn1Set)obj;
                        }
                        else
                        {
                            throw Platform.CreateNotImplementedException(obj.GetType().Name);
                        }

                        foreach (Asn1Encodable o in eObj)
                        {
                            derOut.WriteObject(o);
                        }
                    }
                    else
                    {
                        derOut.WriteObject(obj);
                    }
                }

                derOut.WriteByte(0x00);
                derOut.WriteByte(0x00);
            }
            else
            {
                base.Encode(derOut);
            }
        }
Beispiel #4
0
        /**
         * return an Octet string from a tagged object.
         *
         * @param obj the tagged object holding the object we want.
         * @param explicitly true if the object is meant to be explicitly
         *              tagged false otherwise.
         * @exception ArgumentException if the tagged object cannot
         *              be converted.
         */
        public static Asn1OctetString GetInstance(
            Asn1TaggedObject obj,
            bool isExplicit)
        {
            Asn1Object o = obj.GetObject();

            if (isExplicit || o is Asn1OctetString)
            {
                return(GetInstance(o));
            }

            return(BerOctetString.FromSequence(Asn1Sequence.GetInstance(o)));
        }
        public void Save(Stream stream, char[] password, SecureRandom random)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (password == null)
            {
                throw new ArgumentNullException("password");
            }
            if (random == null)
            {
                throw new ArgumentNullException("random");
            }

            //
            // handle the key
            //
            var keyS = new Asn1EncodableVector();
            foreach (string name in _keys.Keys)
            {
                var kSalt = new byte[SaltSize];
                random.NextBytes(kSalt);

                var privKey = (AsymmetricKeyEntry) _keys[name];
                EncryptedPrivateKeyInfo kInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(_keyAlgorithm, password, kSalt, MinIterations, privKey.Key);

                var kName = new Asn1EncodableVector();

                foreach (string oid in privKey.BagAttributeKeys)
                {
                    Asn1Encodable entry = privKey[oid];

                    // NB: Ignore any existing FriendlyName
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        continue;
                    }

                    kName.Add(new DerSequence(new DerObjectIdentifier(oid), new DerSet(entry)));
                }

                //
                // make sure we are using the local alias on store
                //
                // NB: We always set the FriendlyName based on 'name'
                //if (privKey[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
                {
                    kName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(name))));
                }

                //
                // make sure we have a local key-id
                //
                if (privKey[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
                {
                    X509CertificateEntry ct = GetCertificate(name);
                    AsymmetricKeyParameter pubKey = ct.Certificate.GetPublicKey();
                    SubjectKeyIdentifier subjectKeyID = CreateSubjectKeyID(pubKey);

                    kName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(subjectKeyID)));
                }

                var kBag = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, kInfo.ToAsn1Object(), new DerSet(kName));
                keyS.Add(kBag);
            }

            byte[] derEncodedBytes = new DerSequence(keyS).GetDerEncoded();

            var keyString = new BerOctetString(derEncodedBytes);

            //
            // certificate processing
            //
            var cSalt = new byte[SaltSize];

            random.NextBytes(cSalt);

            var certSeq = new Asn1EncodableVector();
            var cParams = new Pkcs12PbeParams(cSalt, MinIterations);
            var cAlgId = new AlgorithmIdentifier(_certAlgorithm, cParams.ToAsn1Object());
            ISet doneCerts = new HashSet();

            foreach (string name in _keys.Keys)
            {
                X509CertificateEntry certEntry = GetCertificate(name);
                var cBag = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(certEntry.Certificate.GetEncoded()));

                var fName = new Asn1EncodableVector();

                foreach (string oid in certEntry.BagAttributeKeys)
                {
                    Asn1Encodable entry = certEntry[oid];

                    // NB: Ignore any existing FriendlyName
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        continue;
                    }

                    fName.Add(new DerSequence(new DerObjectIdentifier(oid), new DerSet(entry)));
                }

                //
                // make sure we are using the local alias on store
                //
                // NB: We always set the FriendlyName based on 'name'
                //if (certEntry[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
                {
                    fName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(name))));
                }

                //
                // make sure we have a local key-id
                //
                if (certEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
                {
                    AsymmetricKeyParameter pubKey = certEntry.Certificate.GetPublicKey();
                    SubjectKeyIdentifier subjectKeyID = CreateSubjectKeyID(pubKey);

                    fName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID, new DerSet(subjectKeyID)));
                }

                var sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName));

                certSeq.Add(sBag);

                doneCerts.Add(certEntry.Certificate);
            }

            foreach (string certId in _certs.Keys)
            {
                var cert = (X509CertificateEntry) _certs[certId];

                if (_keys[certId] != null)
                {
                    continue;
                }

                var cBag = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(cert.Certificate.GetEncoded()));

                var fName = new Asn1EncodableVector();

                foreach (string oid in cert.BagAttributeKeys)
                {
                    // a certificate not immediately linked to a key doesn't require
                    // a localKeyID and will confuse some PKCS12 implementations.
                    //
                    // If we find one, we'll prune it out.
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
                    {
                        continue;
                    }

                    Asn1Encodable entry = cert[oid];

                    // NB: Ignore any existing FriendlyName
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
                    {
                        continue;
                    }

                    fName.Add(new DerSequence(new DerObjectIdentifier(oid), new DerSet(entry)));
                }

                //
                // make sure we are using the local alias on store
                //
                // NB: We always set the FriendlyName based on 'certId'
                //if (cert[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
                {
                    fName.Add(new DerSequence(PkcsObjectIdentifiers.Pkcs9AtFriendlyName, new DerSet(new DerBmpString(certId))));
                }

                var sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName));

                certSeq.Add(sBag);

                doneCerts.Add(cert.Certificate);
            }

            foreach (CertId certId in _chainCerts.Keys)
            {
                var cert = (X509CertificateEntry) _chainCerts[certId];

                if (doneCerts.Contains(cert.Certificate))
                {
                    continue;
                }

                var cBag = new CertBag(PkcsObjectIdentifiers.X509Certificate, new DerOctetString(cert.Certificate.GetEncoded()));

                var fName = new Asn1EncodableVector();

                foreach (string oid in cert.BagAttributeKeys)
                {
                    // a certificate not immediately linked to a key doesn't require
                    // a localKeyID and will confuse some PKCS12 implementations.
                    //
                    // If we find one, we'll prune it out.
                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
                    {
                        continue;
                    }

                    fName.Add(new DerSequence(new DerObjectIdentifier(oid), new DerSet(cert[oid])));
                }

                var sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName));

                certSeq.Add(sBag);
            }

            derEncodedBytes = new DerSequence(certSeq).GetDerEncoded();

            byte[] certBytes = CryptPbeData(true, cAlgId, password, false, derEncodedBytes);

            var cInfo = new EncryptedData(PkcsObjectIdentifiers.Data, cAlgId, new BerOctetString(certBytes));

            ContentInfo[] info = {new ContentInfo(PkcsObjectIdentifiers.Data, keyString), new ContentInfo(PkcsObjectIdentifiers.EncryptedData, cInfo.ToAsn1Object())};

            byte[] data = new AuthenticatedSafe(info).GetEncoded(_useDerEncoding ? Asn1Encodable.Der : Asn1Encodable.Ber);

            var mainInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(data));

            //
            // create the mac
            //
            var mSalt = new byte[20];
            random.NextBytes(mSalt);

            byte[] mac = CalculatePbeMac(OiwObjectIdentifiers.IdSha1, mSalt, MinIterations, password, false, data);

            var algId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
            var dInfo = new DigestInfo(algId, mac);

            var mData = new MacData(dInfo, mSalt, MinIterations);

            //
            // output the Pfx
            //
            var pfx = new Pfx(mainInfo, mData);

            DerOutputStream derOut;
            if (_useDerEncoding)
            {
                derOut = new DerOutputStream(stream);
            }
            else
            {
                derOut = new BerOutputStream(stream);
            }

            derOut.WriteObject(pfx);
        }
		/// <summary>
		/// Generate an enveloped object that contains a CMS Enveloped Data
		/// object using the passed in key generator.
		/// </summary>
        private CmsEnvelopedData Generate(
            CmsProcessable		content,
            string				encryptionOid,
            CipherKeyGenerator	keyGen)
        {
            AlgorithmIdentifier encAlgId = null;
			KeyParameter encKey;
            Asn1OctetString encContent;

			try
			{
				byte[] encKeyBytes = keyGen.GenerateKey();
				encKey = ParameterUtilities.CreateKeyParameter(encryptionOid, encKeyBytes);

				Asn1Encodable asn1Params = GenerateAsn1Parameters(encryptionOid, encKeyBytes);

				ICipherParameters cipherParameters;
				encAlgId = GetAlgorithmIdentifier(
					encryptionOid, encKey, asn1Params, out cipherParameters);

				IBufferedCipher cipher = CipherUtilities.GetCipher(encryptionOid);
				cipher.Init(true, new ParametersWithRandom(cipherParameters, rand));

				MemoryStream bOut = new MemoryStream();
				CipherStream cOut = new CipherStream(bOut, null, cipher);

				content.Write(cOut);

				cOut.Dispose();

				encContent = new BerOctetString(bOut.ToArray());
			}
			catch (SecurityUtilityException e)
			{
				throw new CmsException("couldn't create cipher.", e);
			}
			catch (InvalidKeyException e)
			{
				throw new CmsException("key invalid in message.", e);
			}
			catch (IOException e)
			{
				throw new CmsException("exception decoding algorithm parameters.", e);
			}


			Asn1EncodableVector recipientInfos = new Asn1EncodableVector();

            foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
            {
                try
                {
                    recipientInfos.Add(rig.Generate(encKey, rand));
                }
                catch (InvalidKeyException e)
                {
                    throw new CmsException("key inappropriate for algorithm.", e);
                }
                catch (GeneralSecurityException e)
                {
                    throw new CmsException("error making encrypted content.", e);
                }
            }

            EncryptedContentInfo eci = new EncryptedContentInfo(
                CmsObjectIdentifiers.Data,
                encAlgId,
                encContent);

			Asn1Set unprotectedAttrSet = null;
            if (unprotectedAttributeGenerator != null)
            {
                Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable());

                unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector());
            }

			ContentInfo contentInfo = new ContentInfo(
                CmsObjectIdentifiers.EnvelopedData,
                new EnvelopedData(null, new DerSet(recipientInfos), eci, unprotectedAttrSet));

            return new CmsEnvelopedData(contentInfo);
        }
	    /**
	     * generate an enveloped object that contains an CMS Enveloped Data
	     * object using the given provider and the passed in key generator.
	     */
		private CmsAuthenticatedData Generate(
			CmsProcessable		content,
			string				macOid,
			CipherKeyGenerator	keyGen)
		{
			AlgorithmIdentifier macAlgId;
			KeyParameter encKey;
			Asn1OctetString encContent;
			Asn1OctetString macResult;

			try
			{
				// FIXME Will this work for macs?
				byte[] encKeyBytes = keyGen.GenerateKey();
				encKey = ParameterUtilities.CreateKeyParameter(macOid, encKeyBytes);

				Asn1Encodable asn1Params = GenerateAsn1Parameters(macOid, encKeyBytes);

				ICipherParameters cipherParameters;
				macAlgId = GetAlgorithmIdentifier(
				macOid, encKey, asn1Params, out cipherParameters);

				IMac mac = MacUtilities.GetMac(macOid);
				// TODO Confirm no ParametersWithRandom needed
				// FIXME Only passing key at the moment
//	            mac.Init(cipherParameters);
				mac.Init(encKey);

				MemoryStream bOut = new MemoryStream();
				Stream mOut = new TeeOutputStream(bOut, new MacOutputStream(mac));

				content.Write(mOut);

				mOut.Dispose();
                bOut.Dispose();

				encContent = new BerOctetString(bOut.ToArray());

				byte[] macOctets = MacUtilities.DoFinal(mac);
				macResult = new DerOctetString(macOctets);
			}
			catch (SecurityUtilityException e)
			{
				throw new CmsException("couldn't create cipher.", e);
			}
			catch (InvalidKeyException e)
			{
				throw new CmsException("key invalid in message.", e);
			}
			catch (IOException e)
			{
				throw new CmsException("exception decoding algorithm parameters.", e);
			}

			Asn1EncodableVector recipientInfos = new Asn1EncodableVector();

			foreach (RecipientInfoGenerator rig in recipientInfoGenerators) 
			{
				try
				{
					recipientInfos.Add(rig.Generate(encKey, rand));
				}
				catch (InvalidKeyException e)
				{
					throw new CmsException("key inappropriate for algorithm.", e);
				}
				catch (GeneralSecurityException e)
				{
					throw new CmsException("error making encrypted content.", e);
				}
			}
			
			ContentInfo eci = new ContentInfo(CmsObjectIdentifiers.Data, encContent);
			
			ContentInfo contentInfo = new ContentInfo(
			CmsObjectIdentifiers.AuthenticatedData,
			new AuthenticatedData(null, new DerSet(recipientInfos), macAlgId, null, eci, null, macResult, null));
			
			return new CmsAuthenticatedData(contentInfo);
		}
        /**
        * generate a signed object that for a CMS Signed Data
        * object  - if encapsulate is true a copy
        * of the message will be included in the signature. The content type
        * is set according to the OID represented by the string signedContentType.
        */

        public CmsSignedData Generate(string signedContentType, // FIXME Avoid accessing more than once to support CmsProcessableInputStream
            CmsProcessable content, bool encapsulate)
        {
            var digestAlgs = new Asn1EncodableVector();
            var signerInfos = new Asn1EncodableVector();

            _digests.Clear(); // clear the current preserved digest state

            //
            // add the precalculated SignerInfo objects.
            //
            foreach (SignerInformation signer in _signers)
            {
                digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));

                // TODO Verify the content type and calculated digest match the precalculated SignerInfo
                signerInfos.Add(signer.ToSignerInfo());
            }

            //
            // add the SignerInfo objects
            //
            bool isCounterSignature = (signedContentType == null);

            DerObjectIdentifier contentTypeOid = isCounterSignature ? null : new DerObjectIdentifier(signedContentType);

            foreach (SignerInf signer in _signerInfs)
            {
                try
                {
                    digestAlgs.Add(signer.DigestAlgorithmID);
                    signerInfos.Add(signer.ToSignerInfo(contentTypeOid, content, rand));
                }
                catch (IOException e)
                {
                    throw new CmsException("encoding error.", e);
                }
                catch (InvalidKeyException e)
                {
                    throw new CmsException("key inappropriate for signature.", e);
                }
                catch (SignatureException e)
                {
                    throw new CmsException("error creating signature.", e);
                }
                catch (CertificateEncodingException e)
                {
                    throw new CmsException("error creating sid.", e);
                }
            }

            Asn1Set certificates = null;

            if (_certs.Count != 0)
            {
                certificates = CmsUtilities.CreateBerSetFromList(_certs);
            }

            Asn1Set certrevlist = null;

            if (_crls.Count != 0)
            {
                certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
            }

            Asn1OctetString octs = null;
            if (encapsulate)
            {
                var bOut = new MemoryStream();
                if (content != null)
                {
                    try
                    {
                        content.Write(bOut);
                    }
                    catch (IOException e)
                    {
                        throw new CmsException("encapsulation error.", e);
                    }
                }
                octs = new BerOctetString(bOut.ToArray());
            }

            var encInfo = new ContentInfo(contentTypeOid, octs);

            var sd = new SignedData(new DerSet(digestAlgs), encInfo, certificates, certrevlist, new DerSet(signerInfos));

            var contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);

            return new CmsSignedData(content, contentInfo);
        }