private void AddCertsFromSet( IList certs, Asn1Set certSet) { X509CertificateParser cf = new X509CertificateParser(); foreach (Asn1Encodable ae in certSet) { try { Asn1Object obj = ae.ToAsn1Object(); if (obj is Asn1Sequence) { // TODO Build certificate directly from sequence? certs.Add(cf.ReadCertificate(obj.GetEncoded())); } } catch (Exception ex) { throw new CmsException("can't re-encode certificate!", ex); } } }
public void Load(Stream input, char[] password) { if (input == null) { throw new ArgumentNullException("input"); } if (password == null) { throw new ArgumentNullException("password"); } var obj = (Asn1Sequence) Asn1Object.FromStream(input); var bag = new Pfx(obj); ContentInfo info = bag.AuthSafe; bool unmarkedKey = false; bool wrongPkcs12Zero = false; if (bag.MacData != null) // check the mac code { MacData mData = bag.MacData; DigestInfo dInfo = mData.Mac; AlgorithmIdentifier algId = dInfo.AlgorithmID; byte[] salt = mData.GetSalt(); int itCount = mData.IterationCount.IntValue; byte[] data = ((Asn1OctetString) info.Content).GetOctets(); byte[] mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, false, data); byte[] dig = dInfo.GetDigest(); if (!Arrays.ConstantTimeAreEqual(mac, dig)) { if (password.Length > 0) { throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file."); } // Try with incorrect zero length password mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, true, data); if (!Arrays.ConstantTimeAreEqual(mac, dig)) { throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file."); } wrongPkcs12Zero = true; } } _keys.Clear(); _localIds.Clear(); IList chain = Platform.CreateArrayList(); if (info.ContentType.Equals(PkcsObjectIdentifiers.Data)) { byte[] octs = ((Asn1OctetString) info.Content).GetOctets(); var authSafe = new AuthenticatedSafe((Asn1Sequence) Asn1Object.FromByteArray(octs)); ContentInfo[] cis = authSafe.GetContentInfo(); foreach (ContentInfo ci in cis) { DerObjectIdentifier oid = ci.ContentType; if (oid.Equals(PkcsObjectIdentifiers.Data)) { byte[] octets = ((Asn1OctetString) ci.Content).GetOctets(); var seq = (Asn1Sequence) Asn1Object.FromByteArray(octets); foreach (Asn1Sequence subSeq in seq) { var b = new SafeBag(subSeq); if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag)) { EncryptedPrivateKeyInfo eIn = EncryptedPrivateKeyInfo.GetInstance(b.BagValue); PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password, wrongPkcs12Zero, eIn); AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privInfo); // // set the attributes on the key // IDictionary attributes = Platform.CreateHashtable(); var pkcs12Key = new AsymmetricKeyEntry(privKey, attributes); string alias = null; Asn1OctetString localId = null; if (b.BagAttributes != null) { foreach (Asn1Sequence sq in b.BagAttributes) { var aOid = (DerObjectIdentifier) sq[0]; var attrSet = (Asn1Set) sq[1]; Asn1Encodable attr = null; if (attrSet.Count > 0) { // TODO We should be adding all attributes in the set attr = attrSet[0]; // TODO We might want to "merge" attribute sets with // the same OID - currently, differing values give an error if (attributes.Contains(aOid.Id)) { // OK, but the value has to be the same if (!attributes[aOid.Id].Equals(attr)) { throw new IOException("attempt to add existing attribute with different value"); } } else { attributes.Add(aOid.Id, attr); } if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName)) { alias = ((DerBmpString) attr).GetString(); // TODO Do these in a separate loop, just collect aliases here _keys[alias] = pkcs12Key; } else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID)) { localId = (Asn1OctetString) attr; } } } } if (localId != null) { string name = Hex.ToHexString(localId.GetOctets()); if (alias == null) { _keys[name] = pkcs12Key; } else { // TODO There may have been more than one alias _localIds[alias] = name; } } else { unmarkedKey = true; _keys["unmarked"] = pkcs12Key; } } else if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag)) { chain.Add(b); } else { Debug.WriteLine("extra " + b.BagID); Debug.WriteLine("extra " + Asn1Dump.DumpAsString(b)); } } } else if (oid.Equals(PkcsObjectIdentifiers.EncryptedData)) { EncryptedData d = EncryptedData.GetInstance(ci.Content); byte[] octets = CryptPbeData(false, d.EncryptionAlgorithm, password, wrongPkcs12Zero, d.Content.GetOctets()); var seq = (Asn1Sequence) Asn1Object.FromByteArray(octets); foreach (Asn1Sequence subSeq in seq) { var b = new SafeBag(subSeq); if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag)) { chain.Add(b); } else if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag)) { EncryptedPrivateKeyInfo eIn = EncryptedPrivateKeyInfo.GetInstance(b.BagValue); PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password, wrongPkcs12Zero, eIn); AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privInfo); // // set the attributes on the key // IDictionary attributes = Platform.CreateHashtable(); var pkcs12Key = new AsymmetricKeyEntry(privKey, attributes); string alias = null; Asn1OctetString localId = null; foreach (Asn1Sequence sq in b.BagAttributes) { var aOid = (DerObjectIdentifier) sq[0]; var attrSet = (Asn1Set) sq[1]; Asn1Encodable attr = null; if (attrSet.Count > 0) { // TODO We should be adding all attributes in the set attr = attrSet[0]; // TODO We might want to "merge" attribute sets with // the same OID - currently, differing values give an error if (attributes.Contains(aOid.Id)) { // OK, but the value has to be the same if (!attributes[aOid.Id].Equals(attr)) { throw new IOException("attempt to add existing attribute with different value"); } } else { attributes.Add(aOid.Id, attr); } if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName)) { alias = ((DerBmpString) attr).GetString(); // TODO Do these in a separate loop, just collect aliases here _keys[alias] = pkcs12Key; } else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID)) { localId = (Asn1OctetString) attr; } } } // TODO Should we be checking localIds != null here // as for PkcsObjectIdentifiers.Data version above? string name = Hex.ToHexString(localId.GetOctets()); if (alias == null) { _keys[name] = pkcs12Key; } else { // TODO There may have been more than one alias _localIds[alias] = name; } } else if (b.BagID.Equals(PkcsObjectIdentifiers.KeyBag)) { PrivateKeyInfo privKeyInfo = PrivateKeyInfo.GetInstance(b.BagValue); AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privKeyInfo); // // set the attributes on the key // string alias = null; Asn1OctetString localId = null; IDictionary attributes = Platform.CreateHashtable(); var pkcs12Key = new AsymmetricKeyEntry(privKey, attributes); foreach (Asn1Sequence sq in b.BagAttributes) { var aOid = (DerObjectIdentifier) sq[0]; var attrSet = (Asn1Set) sq[1]; Asn1Encodable attr = null; if (attrSet.Count > 0) { // TODO We should be adding all attributes in the set attr = attrSet[0]; // TODO We might want to "merge" attribute sets with // the same OID - currently, differing values give an error if (attributes.Contains(aOid.Id)) { // OK, but the value has to be the same if (!attributes[aOid.Id].Equals(attr)) { throw new IOException("attempt to add existing attribute with different value"); } } else { attributes.Add(aOid.Id, attr); } if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName)) { alias = ((DerBmpString) attr).GetString(); // TODO Do these in a separate loop, just collect aliases here _keys[alias] = pkcs12Key; } else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID)) { localId = (Asn1OctetString) attr; } } } // TODO Should we be checking localIds != null here // as for PkcsObjectIdentifiers.Data version above? string name = Hex.ToHexString(localId.GetOctets()); if (alias == null) { _keys[name] = pkcs12Key; } else { // TODO There may have been more than one alias _localIds[alias] = name; } } else { Debug.WriteLine("extra " + b.BagID); Debug.WriteLine("extra " + Asn1Dump.DumpAsString(b)); } } } else { Debug.WriteLine("extra " + oid); Debug.WriteLine("extra " + Asn1Dump.DumpAsString(ci.Content)); } } } _certs.Clear(); _chainCerts.Clear(); _keyCerts.Clear(); foreach (SafeBag b in chain) { var cb = new CertBag((Asn1Sequence) b.BagValue); byte[] octets = ((Asn1OctetString) cb.CertValue).GetOctets(); X509Certificate cert = new X509CertificateParser().ReadCertificate(octets); // // set the attributes // IDictionary attributes = Platform.CreateHashtable(); Asn1OctetString localId = null; string alias = null; if (b.BagAttributes != null) { foreach (Asn1Sequence sq in b.BagAttributes) { var aOid = (DerObjectIdentifier) sq[0]; var attrSet = (Asn1Set) sq[1]; if (attrSet.Count > 0) { // TODO We should be adding all attributes in the set Asn1Encodable attr = attrSet[0]; // TODO We might want to "merge" attribute sets with // the same OID - currently, differing values give an error if (attributes.Contains(aOid.Id)) { // OK, but the value has to be the same if (!attributes[aOid.Id].Equals(attr)) { throw new IOException("attempt to add existing attribute with different value"); } } else { attributes.Add(aOid.Id, attr); } if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName)) { alias = ((DerBmpString) attr).GetString(); } else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID)) { localId = (Asn1OctetString) attr; } } } } var certId = new CertId(cert.GetPublicKey()); var pkcs12Cert = new X509CertificateEntry(cert, attributes); _chainCerts[certId] = pkcs12Cert; if (unmarkedKey) { if (_keyCerts.Count == 0) { string name = Hex.ToHexString(certId.Id); _keyCerts[name] = pkcs12Cert; object temp = _keys["unmarked"]; _keys.Remove("unmarked"); _keys[name] = temp; } } else { if (localId != null) { string name = Hex.ToHexString(localId.GetOctets()); _keyCerts[name] = pkcs12Cert; } if (alias != null) { // TODO There may have been more than one alias _certs[alias] = pkcs12Cert; } } } }