Exemple #1
0
        /* SubjectPublicKeyInfo  ::=  SEQUENCE  {
         *      algorithm            AlgorithmIdentifier,
         *      subjectPublicKey     BIT STRING  }
         */
        private ASN1 SubjectPublicKeyInfo()
        {
            ASN1 keyInfo = new ASN1(0x30);

            if (aa is RSA)
            {
                keyInfo.Add(PKCS7.AlgorithmIdentifier("1.2.840.113549.1.1.1"));
                RSAParameters p = (aa as RSA).ExportParameters(false);

                /* RSAPublicKey ::= SEQUENCE {
                 *       modulus            INTEGER,    -- n
                 *       publicExponent     INTEGER  }  -- e
                 */
                ASN1 key = new ASN1(0x30);
                key.Add(ASN1Convert.FromUnsignedBigInteger(p.Modulus));
                key.Add(ASN1Convert.FromUnsignedBigInteger(p.Exponent));
                keyInfo.Add(new ASN1(UniqueIdentifier(key.GetBytes())));
            }
            else if (aa is DSA)
            {
                DSAParameters p = (aa as DSA).ExportParameters(false);

                /* Dss-Parms  ::=  SEQUENCE  {
                 *       p             INTEGER,
                 *       q             INTEGER,
                 *       g             INTEGER  }
                 */
                ASN1 param = new ASN1(0x30);
                param.Add(ASN1Convert.FromUnsignedBigInteger(p.P));
                param.Add(ASN1Convert.FromUnsignedBigInteger(p.Q));
                param.Add(ASN1Convert.FromUnsignedBigInteger(p.G));
                keyInfo.Add(PKCS7.AlgorithmIdentifier("1.2.840.10040.4.1", param));
                ASN1 key = keyInfo.Add(new ASN1(0x03));
                // DSAPublicKey ::= INTEGER  -- public key, y
                key.Add(ASN1Convert.FromUnsignedBigInteger(p.Y));
            }
            else
            {
                throw new NotSupportedException("Unknown Asymmetric Algorithm " + aa.ToString());
            }
            return(keyInfo);
        }
            /*
             * RSAPrivateKey ::= SEQUENCE {
             *	version           Version,
             *	modulus           INTEGER,  -- n
             *	publicExponent    INTEGER,  -- e
             *	privateExponent   INTEGER,  -- d
             *	prime1            INTEGER,  -- p
             *	prime2            INTEGER,  -- q
             *	exponent1         INTEGER,  -- d mod (p-1)
             *	exponent2         INTEGER,  -- d mod (q-1)
             *	coefficient       INTEGER,  -- (inverse of q) mod p
             *	otherPrimeInfos   OtherPrimeInfos OPTIONAL
             * }
             */
            static public byte[] Encode(RSA rsa)
            {
                RSAParameters param = rsa.ExportParameters(true);

                ASN1 rsaPrivateKey = new ASN1(0x30);

                rsaPrivateKey.Add(new ASN1(0x02, new byte [1] {
                    0x00
                }));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.Modulus));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.Exponent));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.D));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.P));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.Q));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.DP));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.DQ));
                rsaPrivateKey.Add(ASN1Convert.FromUnsignedBigInteger(param.InverseQ));

                return(rsaPrivateKey.GetBytes());
            }
            public bool VerifySignature(AsymmetricAlgorithm aa)
            {
                if (aa == null)
                {
                    return(false);
                }

                RSAPKCS1SignatureDeformatter r = new RSAPKCS1SignatureDeformatter(aa);

                r.SetHashAlgorithm(hashAlgorithm);
                HashAlgorithm ha = HashAlgorithm.Create(hashAlgorithm);

                byte[] signature = signerInfo.Signature;
                byte[] hash      = null;

                if (mda)
                {
                    ASN1 asn = new ASN1(0x31);
                    foreach (ASN1 attr in signerInfo.AuthenticatedAttributes)
                    {
                        asn.Add(attr);
                    }

                    hash = ha.ComputeHash(asn.GetBytes());
                }
                else
                {
                    hash = ha.ComputeHash(contentInfo.Content[0].Value);
                }

                if (hash != null && signature != null)
                {
                    return(r.VerifySignature(hash, signature));
                }
                return(false);
            }
Exemple #4
0
			public byte[] GetBytes () 
			{
				ASN1 privateKeyAlgorithm = new ASN1 (0x30);
				privateKeyAlgorithm.Add (ASN1Convert.FromOid (_algorithm));
				privateKeyAlgorithm.Add (new ASN1 (0x05)); // ASN.1 NULL

				ASN1 pki = new ASN1 (0x30);
				pki.Add (new ASN1 (0x02, new byte [1] { (byte) _version }));
				pki.Add (privateKeyAlgorithm);
				pki.Add (new ASN1 (0x04, _key));

				if (_list.Count > 0) {
					ASN1 attributes = new ASN1 (0xA0);
					foreach (ASN1 attribute in _list) {
						attributes.Add (attribute);
					}
					pki.Add (attributes);
				}

				return pki.GetBytes ();
			}
Exemple #5
0
		// PKCS #1 v.2.1, Section 9.2
		// EMSA-PKCS1-v1_5-Encode
		public static byte[] Encode_v15 (HashAlgorithm hash, byte[] hashValue, int emLength) 
		{
			if (hashValue.Length != (hash.HashSize >> 3))
				throw new CryptographicException ("bad hash length for " + hash.ToString ());

			// DigestInfo ::= SEQUENCE {
			//	digestAlgorithm AlgorithmIdentifier,
			//	digest OCTET STRING
			// }
		
			byte[] t = null;

			string oid = CryptoConfig.MapNameToOID (hash.ToString ());
			if (oid != null)
			{
				ASN1 digestAlgorithm = new ASN1 (0x30);
				digestAlgorithm.Add (new ASN1 (CryptoConfig.EncodeOID (oid)));
				digestAlgorithm.Add (new ASN1 (0x05));		// NULL
				ASN1 digest = new ASN1 (0x04, hashValue);
				ASN1 digestInfo = new ASN1 (0x30);
				digestInfo.Add (digestAlgorithm);
				digestInfo.Add (digest);

				t = digestInfo.GetBytes ();
			}
			else
			{
				// There are no valid OID, in this case t = hashValue
				// This is the case of the MD5SHA hash algorithm
				t = hashValue;
			}

			Buffer.BlockCopy (hashValue, 0, t, t.Length - hashValue.Length, hashValue.Length);
	
			int PSLength = System.Math.Max (8, emLength - t.Length - 3);
			// PS = PSLength of 0xff
	
			// EM = 0x00 | 0x01 | PS | 0x00 | T
			byte[] EM = new byte [PSLength + t.Length + 3];
			EM [1] = 0x01;
			for (int i=2; i < PSLength + 2; i++)
				EM[i] = 0xff;
			Buffer.BlockCopy (t, 0, EM, PSLength + 3, t.Length);
	
			return EM;
		}
Exemple #6
0
		public byte[] GetBytes () 
		{
			if (InnerList.Count < 1)
				return null;
			ASN1 sequence = new ASN1 (0x30);
			for (int i=0; i < InnerList.Count; i++) {
				X509Extension x = (X509Extension) InnerList [i];
				sequence.Add (x.ASN1);
			}
			return sequence.GetBytes ();
		}
Exemple #7
0
 public byte[] GetBytes()
 {
     return(ASN1.GetBytes());
 }
Exemple #8
0
        // that's were the real job is!
        private void Parse(byte[] data)
        {
            try {
                decoder = new ASN1(data);
                // Certificate
                if (decoder.Tag != 0x30)
                {
                    throw new CryptographicException(encoding_error);
                }
                // Certificate / TBSCertificate
                if (decoder [0].Tag != 0x30)
                {
                    throw new CryptographicException(encoding_error);
                }

                ASN1 tbsCertificate = decoder [0];

                int tbs = 0;
                // Certificate / TBSCertificate / Version
                ASN1 v = decoder [0][tbs];
                version = 1;                                    // DEFAULT v1
                if ((v.Tag == 0xA0) && (v.Count > 0))
                {
                    // version (optional) is present only in v2+ certs
                    version += v [0].Value [0];                         // zero based
                    tbs++;
                }

                // Certificate / TBSCertificate / CertificateSerialNumber
                ASN1 sn = decoder [0][tbs++];
                if (sn.Tag != 0x02)
                {
                    throw new CryptographicException(encoding_error);
                }
                serialnumber = sn.Value;
                Array.Reverse(serialnumber, 0, serialnumber.Length);

                // Certificate / TBSCertificate / AlgorithmIdentifier
                tbs++;
                // ASN1 signatureAlgo = tbsCertificate.Element (tbs++, 0x30);

                issuer       = tbsCertificate.Element(tbs++, 0x30);
                m_issuername = X501.ToString(issuer);

                ASN1 validity  = tbsCertificate.Element(tbs++, 0x30);
                ASN1 notBefore = validity [0];
                m_from = ASN1Convert.ToDateTime(notBefore);
                ASN1 notAfter = validity [1];
                m_until = ASN1Convert.ToDateTime(notAfter);

                subject   = tbsCertificate.Element(tbs++, 0x30);
                m_subject = X501.ToString(subject);

                ASN1 subjectPublicKeyInfo = tbsCertificate.Element(tbs++, 0x30);

                ASN1 algorithm = subjectPublicKeyInfo.Element(0, 0x30);
                ASN1 algo      = algorithm.Element(0, 0x06);
                m_keyalgo = ASN1Convert.ToOid(algo);
                // parameters ANY DEFINED BY algorithm OPTIONAL
                // so we dont ask for a specific (Element) type and return DER
                ASN1 parameters = algorithm [1];
                m_keyalgoparams = ((algorithm.Count > 1) ? parameters.GetBytes() : null);

                ASN1 subjectPublicKey = subjectPublicKeyInfo.Element(1, 0x03);
                // we must drop th first byte (which is the number of unused bits
                // in the BITSTRING)
                int n = subjectPublicKey.Length - 1;
                m_publickey = new byte [n];
                Buffer.BlockCopy(subjectPublicKey.Value, 1, m_publickey, 0, n);

                // signature processing
                byte[] bitstring = decoder [2].Value;
                // first byte contains unused bits in first byte
                signature = new byte [bitstring.Length - 1];
                Buffer.BlockCopy(bitstring, 1, signature, 0, signature.Length);

                algorithm       = decoder [1];
                algo            = algorithm.Element(0, 0x06);
                m_signaturealgo = ASN1Convert.ToOid(algo);
                parameters      = algorithm [1];
                if (parameters != null)
                {
                    m_signaturealgoparams = parameters.GetBytes();
                }
                else
                {
                    m_signaturealgoparams = null;
                }

                // Certificate / TBSCertificate / issuerUniqueID
                ASN1 issuerUID = tbsCertificate.Element(tbs, 0x81);
                if (issuerUID != null)
                {
                    tbs++;
                    issuerUniqueID = issuerUID.Value;
                }

                // Certificate / TBSCertificate / subjectUniqueID
                ASN1 subjectUID = tbsCertificate.Element(tbs, 0x82);
                if (subjectUID != null)
                {
                    tbs++;
                    subjectUniqueID = subjectUID.Value;
                }

                // Certificate / TBSCertificate / Extensions
                ASN1 extns = tbsCertificate.Element(tbs, 0xA3);
                if ((extns != null) && (extns.Count == 1))
                {
                    extensions = new X509ExtensionCollection(extns [0]);
                }
                else
                {
                    extensions = new X509ExtensionCollection(null);
                }

                // keep a copy of the original data
                m_encodedcert = (byte[])data.Clone();
            }
            catch (Exception ex) {
                throw new CryptographicException(encoding_error, ex);
            }
        }
Exemple #9
0
		private byte[] Build (ASN1 tbs, string hashoid, byte[] signature) 
		{
			ASN1 builder = new ASN1 (0x30);
			builder.Add (tbs);
			builder.Add (PKCS7.AlgorithmIdentifier (hashoid));
			// first byte of BITSTRING is the number of unused bits in the first byte
			byte[] bitstring = new byte [signature.Length + 1];
			Buffer.BlockCopy (signature, 0, bitstring, 1, signature.Length);
			builder.Add (new ASN1 (0x03, bitstring));
			return builder.GetBytes ();
		}
Exemple #10
0
		// Creates an encrypted PKCS#7 ContentInfo with safeBags as its SafeContents.  Used in GetBytes(), above.
		private PKCS7.ContentInfo EncryptedContentInfo(ASN1 safeBags, string algorithmOid)
		{
			byte[] salt = new byte [8];
			RNG.GetBytes (salt);

			ASN1 seqParams = new ASN1 (0x30);
			seqParams.Add (new ASN1 (0x04, salt));
			seqParams.Add (ASN1Convert.FromInt32 (_iterations));

			ASN1 seqPbe = new ASN1 (0x30);
			seqPbe.Add (ASN1Convert.FromOid (algorithmOid));
			seqPbe.Add (seqParams);

			byte[] encrypted = Encrypt (algorithmOid, salt, _iterations, safeBags.GetBytes ());
			ASN1 encryptedContent = new ASN1 (0x80, encrypted);

			ASN1 seq = new ASN1 (0x30);
			seq.Add (ASN1Convert.FromOid (PKCS7.Oid.data));
			seq.Add (seqPbe);
			seq.Add (encryptedContent);

			ASN1 version = new ASN1 (0x02, new byte [1] { 0x00 });
			ASN1 encData = new ASN1 (0x30);
			encData.Add (version);
			encData.Add (seq);

			ASN1 finalContent = new ASN1 (0xA0);
			finalContent.Add (encData);

			PKCS7.ContentInfo bag = new PKCS7.ContentInfo (PKCS7.Oid.encryptedData);
			bag.Content = finalContent;
			return bag;
		}
		private byte[] UniqueIdentifier (byte[] id) 
		{
			// UniqueIdentifier  ::=  BIT STRING
			ASN1 uid = new ASN1 (0x03);
			// first byte in a BITSTRING is the number of unused bits in the first byte
			byte[] v = new byte [id.Length + 1];
			Buffer.BlockCopy (id, 0, v, 1, id.Length);
			uid.Value = v;
			return uid.GetBytes ();
		}
		/* SubjectPublicKeyInfo  ::=  SEQUENCE  {
		 *      algorithm            AlgorithmIdentifier,
		 *      subjectPublicKey     BIT STRING  }
		 */
		private ASN1 SubjectPublicKeyInfo () 
		{
			ASN1 keyInfo = new ASN1 (0x30);
			if (aa is RSA) {
				keyInfo.Add (PKCS7.AlgorithmIdentifier ("1.2.840.113549.1.1.1"));
				RSAParameters p = (aa as RSA).ExportParameters (false);
				/* RSAPublicKey ::= SEQUENCE {
				 *       modulus            INTEGER,    -- n
				 *       publicExponent     INTEGER  }  -- e
				 */
				ASN1 key = new ASN1 (0x30);
				key.Add (ASN1Convert.FromUnsignedBigInteger (p.Modulus));
				key.Add (ASN1Convert.FromUnsignedBigInteger (p.Exponent));
				keyInfo.Add (new ASN1 (UniqueIdentifier (key.GetBytes ())));
			}
			else if (aa is DSA) {
				DSAParameters p = (aa as DSA).ExportParameters (false);
				/* Dss-Parms  ::=  SEQUENCE  {
				 *       p             INTEGER,
				 *       q             INTEGER,
				 *       g             INTEGER  }
				 */
				ASN1 param = new ASN1 (0x30);
				param.Add (ASN1Convert.FromUnsignedBigInteger (p.P));
				param.Add (ASN1Convert.FromUnsignedBigInteger (p.Q));
				param.Add (ASN1Convert.FromUnsignedBigInteger (p.G));
				keyInfo.Add (PKCS7.AlgorithmIdentifier ("1.2.840.10040.4.1", param));
				ASN1 key = keyInfo.Add (new ASN1 (0x03));
				// DSAPublicKey ::= INTEGER  -- public key, y
				key.Add (ASN1Convert.FromUnsignedBigInteger (p.Y));
			}
			else
				throw new NotSupportedException ("Unknown Asymmetric Algorithm " + aa.ToString ());
			return keyInfo;
		}
            internal ASN1 GetASN1()
            {
                if ((key == null) || (hashAlgorithm == null))
                {
                    return(null);
                }
                byte[] ver        = { version };
                ASN1   signerInfo = new ASN1(0x30);

                // version Version -> Version ::= INTEGER
                signerInfo.Add(new ASN1(0x02, ver));
                // issuerAndSerialNumber IssuerAndSerialNumber,
                signerInfo.Add(PKCS7.IssuerAndSerialNumber(x509));
                // digestAlgorithm DigestAlgorithmIdentifier,
                string hashOid = CryptoConfig.MapNameToOID(hashAlgorithm);

                signerInfo.Add(AlgorithmIdentifier(hashOid));
                // authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
                ASN1 aa = null;

                if (authenticatedAttributes.Count > 0)
                {
                    aa = signerInfo.Add(new ASN1(0xA0));
                    authenticatedAttributes.Sort(new SortedSet());
                    foreach (ASN1 attr in authenticatedAttributes)
                    {
                        aa.Add(attr);
                    }
                }
                // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
                if (key is RSA)
                {
                    signerInfo.Add(AlgorithmIdentifier(PKCS7.Oid.rsaEncryption));

                    if (aa != null)
                    {
                        // Calculate the signature here; otherwise it must be set from SignedData
                        RSAPKCS1SignatureFormatter r = new RSAPKCS1SignatureFormatter(key);
                        r.SetHashAlgorithm(hashAlgorithm);
                        byte[] tbs = aa.GetBytes();
                        tbs [0] = 0x31;                         // not 0xA0 for signature
                        HashAlgorithm ha      = HashAlgorithm.Create(hashAlgorithm);
                        byte[]        tbsHash = ha.ComputeHash(tbs);
                        signature = r.CreateSignature(tbsHash);
                    }
                }
                else if (key is DSA)
                {
                    throw new NotImplementedException("not yet");
                }
                else
                {
                    throw new CryptographicException("Unknown assymetric algorithm");
                }
                // encryptedDigest EncryptedDigest,
                signerInfo.Add(new ASN1(0x04, signature));
                // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
                if (unauthenticatedAttributes.Count > 0)
                {
                    ASN1 ua = signerInfo.Add(new ASN1(0xA1));
                    unauthenticatedAttributes.Sort(new SortedSet());
                    foreach (ASN1 attr in unauthenticatedAttributes)
                    {
                        ua.Add(attr);
                    }
                }
                return(signerInfo);
            }
Exemple #14
0
			/*
			 * RSAPrivateKey ::= SEQUENCE {
			 *	version           Version, 
			 *	modulus           INTEGER,  -- n
			 *	publicExponent    INTEGER,  -- e
			 *	privateExponent   INTEGER,  -- d
			 *	prime1            INTEGER,  -- p
			 *	prime2            INTEGER,  -- q
			 *	exponent1         INTEGER,  -- d mod (p-1)
			 *	exponent2         INTEGER,  -- d mod (q-1) 
			 *	coefficient       INTEGER,  -- (inverse of q) mod p
			 *	otherPrimeInfos   OtherPrimeInfos OPTIONAL 
			 * }
			 */
			static public byte[] Encode (RSA rsa) 
			{
				RSAParameters param = rsa.ExportParameters (true);

				ASN1 rsaPrivateKey = new ASN1 (0x30);
				rsaPrivateKey.Add (new ASN1 (0x02, new byte [1] { 0x00 }));
				rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.Modulus));
				rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.Exponent));
				rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.D));
				rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.P));
				rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.Q));
				rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.DP));
				rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.DQ));
				rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.InverseQ));

				return rsaPrivateKey.GetBytes ();
			}
Exemple #15
0
		public virtual byte[] Sign (DSA key) 
		{
			string oid = "1.2.840.10040.4.3";
			ASN1 tbs = ToBeSigned (oid);
			HashAlgorithm ha = HashAlgorithm.Create (hashName);
			if (!(ha is SHA1))
				throw new NotSupportedException ("Only SHA-1 is supported for DSA");
			byte[] hash = ha.ComputeHash (tbs.GetBytes ());

			DSASignatureFormatter dsa = new DSASignatureFormatter (key);
			dsa.SetHashAlgorithm (hashName);
			byte[] rs = dsa.CreateSignature (hash);

			// split R and S
			byte[] r = new byte [20];
			Buffer.BlockCopy (rs, 0, r, 0, 20);
			byte[] s = new byte [20];
			Buffer.BlockCopy (rs, 20, s, 0, 20);
			ASN1 signature = new ASN1 (0x30);
			signature.Add (new ASN1 (0x02, r));
			signature.Add (new ASN1 (0x02, s));

			// dsaWithSha1 (1 2 840 10040 4 3)
			return Build (tbs, oid, signature.GetBytes ());
		}
Exemple #16
0
			// Note: PKCS#8 doesn't define how to generate the key required for encryption
			// so you're on your own. Just don't try to copy the big guys too much ;)
			// Netscape:	http://www.cs.auckland.ac.nz/~pgut001/pubs/netscape.txt
			// Microsoft:	http://www.cs.auckland.ac.nz/~pgut001/pubs/breakms.txt
			public byte[] GetBytes ()
			{
				if (_algorithm == null)
					throw new CryptographicException ("No algorithm OID specified");

				ASN1 encryptionAlgorithm = new ASN1 (0x30);
				encryptionAlgorithm.Add (ASN1Convert.FromOid (_algorithm));

				// parameters ANY DEFINED BY algorithm OPTIONAL
				if ((_iterations > 0) || (_salt != null)) {
					ASN1 salt = new ASN1 (0x04, _salt);
					ASN1 iterations = ASN1Convert.FromInt32 (_iterations);

					ASN1 parameters = new ASN1 (0x30);
					parameters.Add (salt);
					parameters.Add (iterations);
					encryptionAlgorithm.Add (parameters);
				}

				// encapsulates EncryptedData into an OCTET STRING
				ASN1 encryptedData = new ASN1 (0x04, _data);

				ASN1 encryptedPrivateKeyInfo = new ASN1 (0x30);
				encryptedPrivateKeyInfo.Add (encryptionAlgorithm);
				encryptedPrivateKeyInfo.Add (encryptedData);

				return encryptedPrivateKeyInfo.GetBytes ();
			}
Exemple #17
0
		/*
		 * SafeContents ::= SEQUENCE OF SafeBag
		 * 
		 * SafeBag ::= SEQUENCE {
		 *	bagId BAG-TYPE.&id ({PKCS12BagSet}),
		 *	bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
		 *	bagAttributes SET OF PKCS12Attribute OPTIONAL
		 * }
		 */
		public byte[] GetBytes () 
		{
			// TODO (incomplete)
			ASN1 safeBagSequence = new ASN1 (0x30);

			// Sync Safe Bag list since X509CertificateCollection may be updated
			ArrayList scs = new ArrayList ();
			foreach (SafeBag sb in _safeBags) {
				if (sb.BagOID.Equals (certBag)) {
					ASN1 safeBag = sb.ASN1;
					ASN1 bagValue = safeBag [1];
					PKCS7.ContentInfo cert = new PKCS7.ContentInfo (bagValue.Value);
					scs.Add (new X509Certificate (cert.Content [0].Value));
				}
			}

			ArrayList addcerts = new ArrayList ();
			ArrayList removecerts = new ArrayList ();

			foreach (X509Certificate c in Certificates) {
				bool found = false;

				foreach (X509Certificate lc in scs) {
					if (Compare (c.RawData, lc.RawData)) {
						found = true;
					}
				}

				if (!found) {
					addcerts.Add (c);
				}
			}
			foreach (X509Certificate c in scs) {
				bool found = false;

				foreach (X509Certificate lc in Certificates) {
					if (Compare (c.RawData, lc.RawData)) {
						found = true;
					}
				}

				if (!found) {
					removecerts.Add (c);
				}
			}

			foreach (X509Certificate c in removecerts) {
				RemoveCertificate (c);
			}

			foreach (X509Certificate c in addcerts) {
				AddCertificate (c);
			}
			// Sync done

			if (_safeBags.Count > 0) {
				ASN1 certsSafeBag = new ASN1 (0x30);
				foreach (SafeBag sb in _safeBags) {
					if (sb.BagOID.Equals (certBag)) {
						certsSafeBag.Add (sb.ASN1);
					}
				}

				if (certsSafeBag.Count > 0) {
					PKCS7.ContentInfo contentInfo = EncryptedContentInfo (certsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
					safeBagSequence.Add (contentInfo.ASN1);
				}
			}

			if (_safeBags.Count > 0) {
				ASN1 safeContents = new ASN1 (0x30);
				foreach (SafeBag sb in _safeBags) {
					if (sb.BagOID.Equals (keyBag) ||
					    sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
						safeContents.Add (sb.ASN1);
					}
				}
				if (safeContents.Count > 0) {
					ASN1 content = new ASN1 (0xA0);
					content.Add (new ASN1 (0x04, safeContents.GetBytes ()));
				
					PKCS7.ContentInfo keyBag = new PKCS7.ContentInfo (PKCS7.Oid.data);
					keyBag.Content = content;
					safeBagSequence.Add (keyBag.ASN1);
				}
			}

			// Doing SecretBags separately in case we want to change their encryption independently.
			if (_safeBags.Count > 0) {
				ASN1 secretsSafeBag = new ASN1 (0x30);
				foreach (SafeBag sb in _safeBags) {
					if (sb.BagOID.Equals (secretBag)) {
						secretsSafeBag.Add (sb.ASN1);
					}
				}

				if (secretsSafeBag.Count > 0) {
					PKCS7.ContentInfo contentInfo = EncryptedContentInfo (secretsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
					safeBagSequence.Add (contentInfo.ASN1);
				}
			}


			ASN1 encapsulates = new ASN1 (0x04, safeBagSequence.GetBytes ());
			ASN1 ci = new ASN1 (0xA0);
			ci.Add (encapsulates);
			PKCS7.ContentInfo authSafe = new PKCS7.ContentInfo (PKCS7.Oid.data);
			authSafe.Content = ci;
			
			ASN1 macData = new ASN1 (0x30);
			if (_password != null) {
				// only for password based encryption
				byte[] salt = new byte [20];
				RNG.GetBytes (salt);
				byte[] macValue = MAC (_password, salt, _iterations, authSafe.Content [0].Value);
				ASN1 oidSeq = new ASN1 (0x30);
				oidSeq.Add (ASN1Convert.FromOid ("1.3.14.3.2.26"));	// SHA1
				oidSeq.Add (new ASN1 (0x05));

				ASN1 mac = new ASN1 (0x30);
				mac.Add (oidSeq);
				mac.Add (new ASN1 (0x04, macValue));

				macData.Add (mac);
				macData.Add (new ASN1 (0x04, salt));
				macData.Add (ASN1Convert.FromInt32 (_iterations));
			}
			
			ASN1 version = new ASN1 (0x02, new byte [1] { 0x03 });
			
			ASN1 pfx = new ASN1 (0x30);
			pfx.Add (version);
			pfx.Add (authSafe.ASN1);
			if (macData.Count > 0) {
				// only for password based encryption
				pfx.Add (macData);
			}

			return pfx.GetBytes ();
		}