/// <summary>
        /// Build the Pfx structure, protecting it with a MAC calculated against the passed in password.
        /// </summary>
        /// <param name="macCalcFactory">a builder for a Pkcs12 mac calculator.</param>
        /// <returns>A Pfx object.</returns>
        public Pkcs12PfxPdu Build(IMacFactory <Pkcs12MacAlgDescriptor> macCalcFactory)
        {
            AuthenticatedSafe auth = AuthenticatedSafe.GetInstance(new DerSequence(dataVector));

            byte[] encAuth;

            try
            {
                encAuth = auth.GetEncoded();
            }
            catch (IOException e)
            {
                throw new PkcsException("unable to encode AuthenticatedSafe: " + e.Message, e);
            }

            ContentInfo mainInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new DerOctetString(encAuth));
            MacData     mData    = null;

            if (macCalcFactory != null)
            {
                mData = PkcsUtilities.CreateMacData(macCalcFactory, encAuth);
            }

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

            return(new Pkcs12PfxPdu(pfx));
        }
        public override void PerformTest()
        {
            Pfx                 bag   = Pfx.GetInstance(pkcs12);
            ContentInfo         info  = bag.AuthSafe;
            MacData             mData = bag.MacData;
            DigestInfo          dInfo = mData.Mac;
            AlgorithmIdentifier algId = dInfo.AlgorithmID;

            byte[] salt    = mData.GetSalt();
            int    itCount = mData.IterationCount.IntValue;

            Asn1OctetString   content  = Asn1OctetString.GetInstance(info.Content);
            AuthenticatedSafe authSafe = AuthenticatedSafe.GetInstance(content.GetOctets());

            ContentInfo[] c = authSafe.GetContentInfo();

            //
            // private key section
            //
            if (!c[0].ContentType.Equals(PkcsObjectIdentifiers.Data))
            {
                Fail("Failed comparison data test");
            }

            Asn1OctetString authSafeContent = Asn1OctetString.GetInstance(c[0].Content);
            Asn1Sequence    seq             = Asn1Sequence.GetInstance(authSafeContent.GetOctets());

            SafeBag b = SafeBag.GetInstance(seq[0]);

            if (!b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
            {
                Fail("Failed comparison shroudedKeyBag test");
            }

            EncryptedPrivateKeyInfo encInfo = EncryptedPrivateKeyInfo.GetInstance(b.BagValue);

            encInfo = new EncryptedPrivateKeyInfo(encInfo.EncryptionAlgorithm, encInfo.GetEncryptedData());

            b = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, encInfo.ToAsn1Object(), b.BagAttributes);

            byte[] contentOctets = new DerSequence(b).GetEncoded();

            c[0] = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(contentOctets));

            //
            // certificates
            //
            if (!c[1].ContentType.Equals(PkcsObjectIdentifiers.EncryptedData))
            {
                Fail("Failed comparison encryptedData test");
            }

            EncryptedData eData = EncryptedData.GetInstance(c[1].Content);

            c[1] = new ContentInfo(PkcsObjectIdentifiers.EncryptedData, eData);

            //
            // create an octet stream to represent the BER encoding of authSafe
            //
            authSafe = new AuthenticatedSafe(c);

            contentOctets = authSafe.GetEncoded();

            info = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(contentOctets));

            mData = new MacData(new DigestInfo(algId, dInfo.GetDigest()), salt, itCount);

            bag = new Pfx(info, mData);

            //
            // comparison test
            //
            byte[] pfxEncoding = bag.GetEncoded();
            if (!Arrays.AreEqual(pfxEncoding, pkcs12))
            {
                Fail("Failed comparison test");
            }
        }
Esempio n. 3
0
        public void Load(
            Stream input,
            char[]      password)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            Pfx         bag             = Pfx.GetInstance(Asn1Object.FromStream(input));
            ContentInfo info            = bag.AuthSafe;
            bool        wrongPkcs12Zero = false;

            if (bag.MacData != null) // check the mac code
            {
                if (password == null)
                {
                    throw new ArgumentNullException("password", "no password supplied when one expected");
                }

                MacData             mData = bag.MacData;
                DigestInfo          dInfo = mData.Mac;
                AlgorithmIdentifier algId = dInfo.AlgorithmID;
                byte[] salt    = mData.GetSalt();
                int    itCount = mData.IterationCount.IntValue;

                byte[] data = Asn1OctetString.GetInstance(info.Content).GetOctets();

                byte[] mac = CalculatePbeMac(algId.Algorithm, 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.Algorithm, 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;
                }
            }
            else if (password != null)
            {
                string ignoreProperty = Platform.GetEnvironmentVariable(IgnoreUselessPasswordProperty);
                bool   ignore         = ignoreProperty != null && Platform.EqualsIgnoreCase("true", ignoreProperty);

                if (!ignore)
                {
                    throw new IOException("password supplied for keystore that does not require one");
                }
            }

            keys.Clear();
            localIds.Clear();
            unmarkedKeyEntry = null;

            IList certBags = Platform.CreateArrayList();

            if (info.ContentType.Equals(PkcsObjectIdentifiers.Data))
            {
                Asn1OctetString   content  = Asn1OctetString.GetInstance(info.Content);
                AuthenticatedSafe authSafe = AuthenticatedSafe.GetInstance(content.GetOctets());
                ContentInfo[]     cis      = authSafe.GetContentInfo();

                foreach (ContentInfo ci in cis)
                {
                    DerObjectIdentifier oid = ci.ContentType;

                    byte[] octets = null;
                    if (oid.Equals(PkcsObjectIdentifiers.Data))
                    {
                        octets = Asn1OctetString.GetInstance(ci.Content).GetOctets();
                    }
                    else if (oid.Equals(PkcsObjectIdentifiers.EncryptedData))
                    {
                        if (password != null)
                        {
                            EncryptedData d = EncryptedData.GetInstance(ci.Content);
                            octets = CryptPbeData(false, d.EncryptionAlgorithm,
                                                  password, wrongPkcs12Zero, d.Content.GetOctets());
                        }
                    }
                    else
                    {
                        // TODO Other data types
                    }

                    if (octets != null)
                    {
                        Asn1Sequence seq = Asn1Sequence.GetInstance(octets);

                        foreach (Asn1Sequence subSeq in seq)
                        {
                            SafeBag b = new SafeBag(subSeq);

                            if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag))
                            {
                                certBags.Add(b);
                            }
                            else if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
                            {
                                LoadPkcs8ShroudedKeyBag(EncryptedPrivateKeyInfo.GetInstance(b.BagValue),
                                                        b.BagAttributes, password, wrongPkcs12Zero);
                            }
                            else if (b.BagID.Equals(PkcsObjectIdentifiers.KeyBag))
                            {
                                LoadKeyBag(PrivateKeyInfo.GetInstance(b.BagValue), b.BagAttributes);
                            }
                            else
                            {
                                // TODO Other bag types
                            }
                        }
                    }
                }
            }

            certs.Clear();
            chainCerts.Clear();
            keyCerts.Clear();

            foreach (SafeBag b in certBags)
            {
                CertBag         certBag = new CertBag((Asn1Sequence)b.BagValue);
                byte[]          octets  = ((Asn1OctetString)certBag.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)
                    {
                        DerObjectIdentifier aOid    = DerObjectIdentifier.GetInstance(sq[0]);
                        Asn1Set             attrSet = Asn1Set.GetInstance(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;
                            }
                        }
                    }
                }

                CertId certId = new CertId(cert.GetPublicKey());
                X509CertificateEntry certEntry = new X509CertificateEntry(cert, attributes);

                chainCerts[certId] = certEntry;

                if (unmarkedKeyEntry != null)
                {
                    if (keyCerts.Count == 0)
                    {
                        string name = Hex.ToHexString(certId.Id);

                        keyCerts[name] = certEntry;
                        keys[name]     = unmarkedKeyEntry;
                    }
                    else
                    {
                        keys["unmarked"] = unmarkedKeyEntry;
                    }
                }
                else
                {
                    if (localId != null)
                    {
                        string name = Hex.ToHexString(localId.GetOctets());

                        keyCerts[name] = certEntry;
                    }

                    if (alias != null)
                    {
                        // TODO There may have been more than one alias
                        certs[alias] = certEntry;
                    }
                }
            }
        }