Пример #1
0
        /**
         * for when the public key is an encoded object - if the bitstring
         * can't be decoded this routine throws an IOException.
         *
         * @exception IOException - if the bit string doesn't represent a DER
         * encoded object.
         */
        public ASN1Object getPublicKey()
        {
            MemoryStream    bIn = new MemoryStream(keyData.getBytes());
            ASN1InputStream dIn = new ASN1InputStream(bIn);

            return(dIn.readObject());
        }
Пример #2
0
/// <summary>
/// Convert to DER Sequence.
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
        private static ASN1Sequence toDERSequence(byte[] bytes)
        {
            MemoryStream    bIn = new MemoryStream(bytes);
            ASN1InputStream dIn = new ASN1InputStream(bIn);

            return((ASN1Sequence)dIn.readObject());
        }
Пример #3
0
        /**
         * Get the "subject" from the TBSCertificate bytes that are passed in
         * @param enc A TBSCertificate in a byte array
         * @return a DERObject
         */
        private static ASN1Object GetSubject(byte[] enc)
        {
            ASN1InputStream inp = new ASN1InputStream(new MemoryStream(enc));
            ASN1Sequence    seq = (ASN1Sequence)inp.readObject();

            return((ASN1Object)seq.getObjectAt(seq.getObjectAt(0) is DERTaggedObject ? 5 : 4));
        }
Пример #4
0
        /**
         * Convert an inline encoded hex string rendition of an ASN.1
         * object back into its corresponding ASN.1 object.
         *
         * @param str the hex encoded object
         * @param off the index at which the encoding starts
         * @return the decoded object
         */
        protected ASN1Object convertHexEncoded(
            string str,
            int off)
        {
            str = str.ToLower();
            byte[] data = new byte[str.Length / 2];
            for (int index = 0; index != data.Length; index++)
            {
                char left  = str[(index * 2) + off];
                char right = str[(index * 2) + off + 1];

                if (left < 'a')
                {
                    data[index] = (byte)((left - '0') << 4);
                }
                else
                {
                    data[index] = (byte)((left - 'a' + 10) << 4);
                }
                if (right < 'a')
                {
                    data[index] |= (byte)(right - '0');
                }
                else
                {
                    data[index] |= (byte)(right - 'a' + 10);
                }
            }

            ASN1InputStream aIn = new ASN1InputStream(
                new MemoryStream(data));

            return(aIn.readObject());
        }
Пример #5
0
        public PrivateKeyInfo(
            ASN1Sequence seq)
        {
            IEnumerator e = seq.getObjects();

            e.MoveNext();
            BigInteger version = ((DERInteger)e.Current).getValue();

            if (version.intValue() != 0)
            {
                throw new ArgumentException("wrong version for private key info");
            }

            e.MoveNext();
            algId = new AlgorithmIdentifier((ASN1Sequence)e.Current);

            try
            {
                e.MoveNext();
                MemoryStream    bIn = new MemoryStream(((ASN1OctetString)e.Current).getOctets());
                ASN1InputStream aIn = new ASN1InputStream(bIn);

                privKey = aIn.readObject();
            }
            catch (IOException)
            {
                throw new ArgumentException("Error recoverying private key from sequence");
            }
        }
Пример #6
0
        public static void main(string[] args)
        {
            FileStream      fIn = new FileStream(args[0], FileMode.Open);
            ASN1InputStream bIn = new ASN1InputStream(fIn);
            object          obj = null;

            while ((obj = bIn.readObject()) != null)
            {
                Console.WriteLine(ASN1Dump.dumpAsString(obj));
            }
        }
Пример #7
0
        private ASN1Object makeObj(byte[]  encoding)
        {
            if (encoding == null)
            {
                return(null);
            }
            MemoryStream    bIn = new MemoryStream(encoding);
            ASN1InputStream aIn = new ASN1InputStream(bIn);

            return(aIn.readObject());
        }
Пример #8
0
        private BigInteger[] derDecode(byte[]  encoding)
        {
            MemoryStream    bIn = new MemoryStream(encoding);
            ASN1InputStream dIn = new ASN1InputStream(bIn);
            ASN1Sequence    s   = (ASN1Sequence)dIn.readObject();

            BigInteger[] sig = new BigInteger[2];

            sig[0] = ((DERInteger)s.getObjectAt(0)).getValue();
            sig[1] = ((DERInteger)s.getObjectAt(1)).getValue();

            return(sig);
        }
Пример #9
0
        private DigestInfo derDecode(byte[]  encoding)
        {
            if ((int)encoding[0] != ((int)ASN1Tags.CONSTRUCTED | (int)ASN1Tags.SEQUENCE))
            {
                throw new IOException("not a digest info object");
            }

            MemoryStream    bIn = new MemoryStream(encoding);
            ASN1InputStream aIn = new ASN1InputStream(bIn);



            return(new DigestInfo((ASN1Sequence)aIn.readObject()));
        }
Пример #10
0
        private X509Certificate readPKCS7Certificate()
        {
            ASN1InputStream dIn = new ASN1InputStream(inStr);
            ASN1Sequence    seq = (ASN1Sequence)dIn.readObject();

            if (seq.size() > 1 && seq.getObjectAt(0) is DERObjectIdentifier)
            {
                if (seq.getObjectAt(0).Equals(PKCSObjectIdentifiers.signedData))
                {
                    sData = new SignedData(ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(1), true));
                    return(new X509Certificate(ASN1Sequence.getInstance(sData.getCertificates().getObjectAt(sDataObjectCount++))));
                }
            }
            return(new X509Certificate(ASN1Sequence.getInstance(seq)));
        }
Пример #11
0
        /// <summary>
        /// Get a key usage guidlines.
        /// </summary>
        /// <returns>A DER it string or null if they are not specified.</returns>
        public KeyUsage getKeyUsage()
        {
            byte[] bytes = this.getExtensionBytes("2.5.29.15");
            if (bytes != null)
            {
                try
                {
                    ASN1InputStream dIn = new ASN1InputStream(new MemoryStream(bytes));
                    return(new KeyUsage(DERBitString.getInstance(dIn.readObject())));
                }
                catch
                {
                    throw new Exception("error processing key usage extension");
                }
            }

            return(null);
        }
Пример #12
0
        public static PrivateKeyInfo createPrivateKeyInfo(
            char[] passPhrase,
            EncryptedPrivateKeyInfo encInfo)
        {
            CipherParameters keyParameters = PBEUtil.generateCipherParameters(encInfo.getEncryptionAlgorithm().getObjectId(), passPhrase, encInfo.getEncryptionAlgorithm().getParameters());
            Object           engine        = PBEUtil.createEngine(encInfo.getEncryptionAlgorithm().getObjectId());

            byte[] encoding = null;

            if (engine is BufferedBlockCipher)
            {
                BufferedBlockCipher cipher = (BufferedBlockCipher)engine;

                cipher.init(false, keyParameters);

                byte[] keyBytes = encInfo.getEncryptedData();

                int encLen = cipher.getOutputSize(keyBytes.Length);

                encoding = new byte[encLen];

                int off = cipher.processBytes(keyBytes, 0, keyBytes.Length, encoding, 0);

                cipher.doFinal(encoding, off);
            }
            else if (engine is StreamCipher)
            {
                StreamCipher cipher = (StreamCipher)engine;

                cipher.init(false, keyParameters);

                byte[] keyBytes = encInfo.getEncryptedData();

                encoding = new byte[keyBytes.Length];

                cipher.processBytes(keyBytes, 0, keyBytes.Length, encoding, 0);
            }

            ASN1InputStream aIn = new ASN1InputStream(new MemoryStream(encoding));

            return(PrivateKeyInfo.getInstance(aIn.readObject()));
        }
Пример #13
0
        ASN1Sequence decryptData(
            AlgorithmIdentifier algId,
            byte[]                data,
            char[]                password)
        {
            PKCS12PBEParams  pbeParams     = PKCS12PBEParams.getInstance(algId.getParameters());
            CipherParameters keyParameters = PBEUtil.generateCipherParameters(algId.getObjectId(), password, pbeParams);

            byte[] encoding = null;
            Object engine   = PBEUtil.createEngine(algId.getObjectId());

            if (engine is BufferedBlockCipher)
            {
                BufferedBlockCipher cipher = (BufferedBlockCipher)engine;

                cipher.init(false, keyParameters);

                int encLen = cipher.getOutputSize(data.Length);

                encoding = new byte[encLen];

                int off = cipher.processBytes(data, 0, data.Length, encoding, 0);

                cipher.doFinal(encoding, off);
            }
            else if (engine is StreamCipher)
            {
                StreamCipher cipher = (StreamCipher)engine;

                cipher.init(false, keyParameters);

                encoding = new byte[data.Length];

                cipher.processBytes(data, 0, data.Length, encoding, 0);
            }

            ASN1InputStream bIn = new ASN1InputStream(new MemoryStream(encoding));

            return((ASN1Sequence)bIn.readObject());
        }
Пример #14
0
        /**
         * Verifies a signature using the sub-filter adbe.x509.rsa_sha1.
         * @param contentsKey the /Contents key
         * @param certsKey the /Cert key
         * @param provider the provider or <code>null</code> for the default provider
         * @throws SecurityException on error
         * @throws CRLException on error
         * @throws InvalidKeyException on error
         * @throws CertificateException on error
         * @throws NoSuchProviderException on error
         * @throws NoSuchAlgorithmException on error
         * @throws IOException on error
         */
        public PdfPKCS7(byte[] contentsKey, byte[] certsKey)
        {
            X509CertificateParser cf = new X509CertificateParser(certsKey);

            certs    = new ArrayList();
            signCert = cf.ReadCertificate();
            certs.Add(signCert);
            while (true)
            {
                X509Certificate cc = cf.ReadCertificate();
                if (cc == null)
                {
                    break;
                }
                certs.Add(cc);
            }
            crls = new ArrayList();
            ASN1InputStream inp = new ASN1InputStream(new MemoryStream(contentsKey));

            digest = ((DEROctetString)inp.readObject()).getOctets();
            sig    = SignerUtil.getSigner("SHA1withRSA");
            sig.init(false, signCert.getPublicKey());
        }
Пример #15
0
        public Object getResponseObject()
        {
            ResponseBytes rb = this.resp.getResponseBytes();

            if (rb == null)
            {
                return(null);
            }

            if (rb.getResponseType().Equals(OCSPObjectIdentifiers.id_pkix_ocsp_basic))
            {
                try
                {
                    ASN1InputStream aIn = new ASN1InputStream(new MemoryStream(rb.getResponse().getOctets()));
                    return(new BasicOCSPResp(BasicOCSPResponse.getInstance(aIn.readObject())));
                }
                catch (Exception e)
                {
                    throw new OCSPException("problem decoding object: " + e, e);
                }
            }

            return(rb.getResponse());
        }
Пример #16
0
        /**
         * Gets the bytes for the PKCS7SignedData object. Optionally the authenticatedAttributes
         * in the signerInfo can also be set. If either of the parameters is <CODE>null</CODE>, none will be used.
         * @param secondDigest the digest in the authenticatedAttributes
         * @param signingTime the signing time in the authenticatedAttributes
         * @return the bytes for the PKCS7SignedData object
         */
        public byte[] GetEncodedPKCS7(byte[] secondDigest, DateTime signingTime)
        {
            if (externalDigest != null)
            {
                digest = externalDigest;
                if (RSAdata != null)
                {
                    RSAdata = externalRSAdata;
                }
            }
            else if (externalRSAdata != null && RSAdata != null)
            {
                RSAdata = externalRSAdata;
                sig.update(RSAdata, 0, RSAdata.Length);
                digest = sig.generateSignature();
            }
            else
            {
                if (RSAdata != null)
                {
                    RSAdata = new byte[messageDigest.getDigestSize()];
                    messageDigest.doFinal(RSAdata, 0);
                    sig.update(RSAdata, 0, RSAdata.Length);
                }
                digest = sig.generateSignature();
            }

            // Create the set of Hash algorithms
            ASN1EncodableVector digestAlgorithms = new ASN1EncodableVector();

            foreach (string dal in digestalgos.Keys)
            {
                ASN1EncodableVector algos = new ASN1EncodableVector();
                algos.add(new DERObjectIdentifier(dal));
                algos.add(new DERNull());
                digestAlgorithms.add(new DERSequence(algos));
            }

            // Create the contentInfo.
            ASN1EncodableVector v = new ASN1EncodableVector();

            v.add(new DERObjectIdentifier(ID_PKCS7_DATA));
            if (RSAdata != null)
            {
                v.add(new DERTaggedObject(0, new DEROctetString(RSAdata)));
            }
            DERSequence contentinfo = new DERSequence(v);

            // Get all the certificates
            //
            v = new ASN1EncodableVector();
            foreach (X509Certificate xcert in certs)
            {
                ASN1InputStream tempstream = new ASN1InputStream(new MemoryStream(xcert.getEncoded()));
                v.add(tempstream.readObject());
            }

            DERSet dercertificates = new DERSet(v);

            // Create signerinfo structure.
            //
            ASN1EncodableVector signerinfo = new ASN1EncodableVector();

            // Add the signerInfo version
            //
            signerinfo.add(new DERInteger(signerversion));

            v = new ASN1EncodableVector();
            v.add(GetIssuer(signCert.getTBSCertificate()));
            v.add(new DERInteger(signCert.getSerialNumber()));
            signerinfo.add(new DERSequence(v));

            // Add the digestAlgorithm
            v = new ASN1EncodableVector();
            v.add(new DERObjectIdentifier(digestAlgorithm));
            v.add(new DERNull());
            signerinfo.add(new DERSequence(v));

            // add the authenticated attribute if present
            if (secondDigest != null /*&& signingTime != null*/)
            {
                ASN1EncodableVector attribute = new ASN1EncodableVector();
                v = new ASN1EncodableVector();
                v.add(new DERObjectIdentifier(ID_CONTENT_TYPE));
                v.add(new DERSet(new DERObjectIdentifier(ID_PKCS7_DATA)));
                attribute.add(new DERSequence(v));
                v = new ASN1EncodableVector();
                v.add(new DERObjectIdentifier(ID_SIGNING_TIME));
                v.add(new DERSet(new DERUTCTime(signingTime)));
                attribute.add(new DERSequence(v));
                v = new ASN1EncodableVector();
                v.add(new DERObjectIdentifier(ID_MESSAGE_DIGEST));
                v.add(new DERSet(new DEROctetString(secondDigest)));
                attribute.add(new DERSequence(v));
                signerinfo.add(new DERTaggedObject(false, 0, new DERSet(attribute)));
            }
            // Add the digestEncryptionAlgorithm
            v = new ASN1EncodableVector();
            v.add(new DERObjectIdentifier(digestEncryptionAlgorithm));
            v.add(new DERNull());
            signerinfo.add(new DERSequence(v));

            // Add the digest
            signerinfo.add(new DEROctetString(digest));


            // Finally build the body out of all the components above
            ASN1EncodableVector body = new ASN1EncodableVector();

            body.add(new DERInteger(version));
            body.add(new DERSet(digestAlgorithms));
            body.add(contentinfo);
            body.add(new DERTaggedObject(false, 0, dercertificates));

//                if (crls.Count > 0) {
//                    v = new ASN1EncodableVector();
//                    for (Iterator i = crls.iterator();i.hasNext();) {
//                        ASN1InputStream t = new ASN1InputStream(new ByteArrayInputStream((((X509CRL)i.next()).getEncoded())));
//                        v.add(t.readObject());
//                    }
//                    DERSet dercrls = new DERSet(v);
//                    body.add(new DERTaggedObject(false, 1, dercrls));
//                }

            // Only allow one signerInfo
            body.add(new DERSet(new DERSequence(signerinfo)));

            // Now we have the body, wrap it in it's PKCS7Signed shell
            // and return it
            //
            ASN1EncodableVector whole = new ASN1EncodableVector();

            whole.add(new DERObjectIdentifier(ID_PKCS7_SIGNED_DATA));
            whole.add(new DERTaggedObject(0, new DERSequence(body)));

            MemoryStream bOut = new MemoryStream();

            ASN1OutputStream dout = new ASN1OutputStream(bOut);

            dout.writeObject(new DERSequence(whole));
            dout.Close();

            return(bOut.ToArray());
        }
Пример #17
0
        public X509CertificateEntry[] getCertificateChain(
            String alias)
        {
            if (alias == null)
            {
                throw new ArgumentException("null alias passed to getCertificateChain.");
            }

            X509CertificateEntry c = getCertificate(alias);

            if (c != null)
            {
                ArrayList cs = new ArrayList();

                while (c != null)
                {
                    X509Certificate      x509c = c.getCertificate();
                    X509CertificateEntry nextC = null;

                    X509Extension ext = x509c.getExtensionValue(X509Extensions.AuthorityKeyIdentifier.getId());
                    if (ext != null)
                    {
                        ASN1InputStream aIn = new ASN1InputStream(new MemoryStream(ext.getValue().getOctets()));

                        AuthorityKeyIdentifier id = new AuthorityKeyIdentifier((ASN1Sequence)aIn.readObject());
                        if (id.getKeyIdentifier() != null)
                        {
                            nextC = (X509CertificateEntry)chainCerts[new CertId(id.getKeyIdentifier())];
                        }
                    }

                    if (nextC == null)
                    {
                        //
                        // no authority key id, try the Issuer DN
                        //
                        X509Name i = x509c.getIssuerDN();
                        X509Name s = x509c.getSubjectDN();

                        if (!i.Equals(s))
                        {
                            IEnumerator e = chainCerts.Keys.GetEnumerator();

                            while (e.MoveNext())
                            {
                                X509Certificate crt = ((X509CertificateEntry)chainCerts[e.Current]).getCertificate();
                                X509Name        sub = crt.getSubjectDN();
                                if (sub.Equals(i))
                                {
                                    try
                                    {
                                        x509c.verify(crt.getPublicKey());
                                        nextC = ((X509CertificateEntry)chainCerts[e.Current]);
                                        break;
                                    }
                                    catch
                                    {
                                        // continue
                                    }
                                }
                            }
                        }
                    }

                    cs.Add(c);
                    if (nextC != c)     // self signed - end of the chain
                    {
                        c = nextC;
                    }
                    else
                    {
                        c = null;
                    }
                }

                X509CertificateEntry[] certChain = new X509CertificateEntry[cs.Count];

                for (int i = 0; i != certChain.Length; i++)
                {
                    certChain[i] = (X509CertificateEntry)cs[i];
                }

                return(certChain);
            }

            return(null);
        }
Пример #18
0
        /**
         * Verifies a signature using the sub-filter adbe.pkcs7.detached or
         * adbe.pkcs7.sha1.
         * @param contentsKey the /Contents key
         * @param provider the provider or <code>null</code> for the default provider
         * @throws SecurityException on error
         * @throws CRLException on error
         * @throws InvalidKeyException on error
         * @throws CertificateException on error
         * @throws NoSuchProviderException on error
         * @throws NoSuchAlgorithmException on error
         */
        public PdfPKCS7(byte[] contentsKey)
        {
            ASN1InputStream din = new ASN1InputStream(new MemoryStream(contentsKey));

            //
            // Basic checks to make sure it's a PKCS#7 SignedData Object
            //
            ASN1Object pkcs;

            try {
                pkcs = din.readObject();
            }
            catch  {
                throw new ArgumentException("can't decode PKCS7SignedData object");
            }
            if (!(pkcs is ASN1Sequence))
            {
                throw new ArgumentException("Not a valid PKCS#7 object - not a sequence");
            }
            ASN1Sequence        signedData = (ASN1Sequence)pkcs;
            DERObjectIdentifier objId      = (DERObjectIdentifier)signedData.getObjectAt(0);

            if (!objId.getId().Equals(ID_PKCS7_SIGNED_DATA))
            {
                throw new ArgumentException("Not a valid PKCS#7 object - not signed data");
            }
            ASN1Sequence content = (ASN1Sequence)((DERTaggedObject)signedData.getObjectAt(1)).getObject();

            // the positions that we care are:
            //     0 - version
            //     1 - digestAlgorithms
            //     2 - possible ID_PKCS7_DATA
            //     (the certificates and crls are taken out by other means)
            //     last - signerInfos

            // the version
            version = ((DERInteger)content.getObjectAt(0)).getValue().intValue();

            // the digestAlgorithms
            digestalgos = new Hashtable();
            IEnumerator e = ((ASN1Set)content.getObjectAt(1)).getObjects();

            while (e.MoveNext())
            {
                ASN1Sequence        s = (ASN1Sequence)e.Current;
                DERObjectIdentifier o = (DERObjectIdentifier)s.getObjectAt(0);
                digestalgos[o.getId()] = null;
            }

            // the certificates and crls
            X509CertificateParser cf = new X509CertificateParser(contentsKey);

            certs = new ArrayList();
            while (true)
            {
                X509Certificate cc = cf.ReadCertificate();
                if (cc == null)
                {
                    break;
                }
                certs.Add(cc);
            }
            crls = new ArrayList();

            // the possible ID_PKCS7_DATA
            ASN1Sequence rsaData = (ASN1Sequence)content.getObjectAt(2);

            if (rsaData.size() > 1)
            {
                DEROctetString rsaDataContent = (DEROctetString)((DERTaggedObject)rsaData.getObjectAt(1)).getObject();
                RSAdata = rsaDataContent.getOctets();
            }

            // the signerInfos
            int next = 3;

            while (content.getObjectAt(next) is DERTaggedObject)
            {
                ++next;
            }
            ASN1Set signerInfos = (ASN1Set)content.getObjectAt(next);

            if (signerInfos.size() != 1)
            {
                throw new ArgumentException("This PKCS#7 object has multiple SignerInfos - only one is supported at this time");
            }
            ASN1Sequence signerInfo = (ASN1Sequence)signerInfos.getObjectAt(0);

            // the positions that we care are
            //     0 - version
            //     1 - the signing certificate serial number
            //     2 - the digest algorithm
            //     3 or 4 - digestEncryptionAlgorithm
            //     4 or 5 - encryptedDigest
            signerversion = ((DERInteger)signerInfo.getObjectAt(0)).getValue().intValue();
            // Get the signing certificate
            ASN1Sequence issuerAndSerialNumber = (ASN1Sequence)signerInfo.getObjectAt(1);
            BigInteger   serialNumber          = ((DERInteger)issuerAndSerialNumber.getObjectAt(1)).getValue();

            foreach (X509Certificate cert in certs)
            {
                if (serialNumber.Equals(cert.getSerialNumber()))
                {
                    signCert = cert;
                    break;
                }
            }
            if (signCert == null)
            {
                throw new ArgumentException("Can't find signing certificate with serial " + serialNumber.ToString(16));
            }
            digestAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(2)).getObjectAt(0)).getId();
            next            = 3;
            if (signerInfo.getObjectAt(next) is ASN1TaggedObject)
            {
                ASN1TaggedObject tagsig = (ASN1TaggedObject)signerInfo.getObjectAt(next);
                ASN1Sequence     sseq   = (ASN1Sequence)tagsig.getObject();
                MemoryStream     bOut   = new MemoryStream();
                ASN1OutputStream dout   = new ASN1OutputStream(bOut);
                try {
                    ASN1EncodableVector attribute = new ASN1EncodableVector();
                    for (int k = 0; k < sseq.size(); ++k)
                    {
                        attribute.add(sseq.getObjectAt(k));
                    }
                    dout.writeObject(new DERSet(attribute));
                    dout.Close();
                }
                catch (IOException) {}
                sigAttr = bOut.ToArray();

                for (int k = 0; k < sseq.size(); ++k)
                {
                    ASN1Sequence seq2 = (ASN1Sequence)sseq.getObjectAt(k);
                    if (((DERObjectIdentifier)seq2.getObjectAt(0)).getId().Equals(ID_MESSAGE_DIGEST))
                    {
                        ASN1Set sset = (ASN1Set)seq2.getObjectAt(1);
                        digestAttr = ((DEROctetString)sset.getObjectAt(0)).getOctets();
                        break;
                    }
                }
                if (digestAttr == null)
                {
                    throw new ArgumentException("Authenticated attribute is missing the digest.");
                }
                ++next;
            }
            digestEncryptionAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(next++)).getObjectAt(0)).getId();
            digest = ((DEROctetString)signerInfo.getObjectAt(next)).getOctets();
            if (RSAdata != null || digestAttr != null)
            {
                messageDigest = GetHashClass();
            }
            sig = SignerUtil.getSigner(GetDigestAlgorithm());
            sig.init(false, signCert.getPublicKey());
        }
Пример #19
0
        public PKCS12Store(
            Stream input,
            char[] password)
        {
            if (password == null)
            {
                throw new ArgumentException("No password supplied for PKCS12Store.");
            }

            ASN1InputStream bIn         = new ASN1InputStream(input);
            ASN1Sequence    obj         = (ASN1Sequence)bIn.readObject();
            Pfx             bag         = new Pfx(obj);
            ContentInfo     info        = bag.getAuthSafe();
            ArrayList       chain       = new ArrayList();
            bool            unmarkedKey = false;

            if (bag.getMacData() != null)           // check the mac code
            {
                MemoryStream        bOut   = new MemoryStream();
                BEROutputStream     berOut = new BEROutputStream(bOut);
                MacData             mData  = bag.getMacData();
                DigestInfo          dInfo  = mData.getMac();
                AlgorithmIdentifier algId  = dInfo.getAlgorithmId();
                byte[] salt    = mData.getSalt();
                int    itCount = mData.getIterationCount().intValue();

                berOut.writeObject(info);

                byte[] data = ((ASN1OctetString)info.getContent()).getOctets();

                try
                {
                    ASN1Encodable    parameters    = PBEUtil.generateAlgorithmParameters(algId.getObjectId(), mData.getSalt(), mData.getIterationCount().intValue());
                    CipherParameters keyParameters = PBEUtil.generateCipherParameters(algId.getObjectId(), password, parameters);
                    Mac mac = (Mac)PBEUtil.createEngine(algId.getObjectId());

                    mac.init(keyParameters);

                    mac.update(data, 0, data.Length);

                    byte[] res = new byte[mac.getMacSize()];

                    mac.doFinal(res, 0);

                    byte[] dig = dInfo.getDigest();

                    if (res.Length != dig.Length)
                    {
                        throw new Exception("PKCS12 key store mac invalid - wrong password or corrupted file.");
                    }

                    for (int i = 0; i != res.Length; i++)
                    {
                        if (res[i] != dig[i])
                        {
                            throw new Exception("PKCS12 key store mac invalid - wrong password or corrupted file.");
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new Exception("error constructing MAC: " + e.Message);
                }
            }

            keys     = new Hashtable();
            localIds = new Hashtable();

            if (info.getContentType().Equals(PKCSObjectIdentifiers.data))
            {
                bIn = new ASN1InputStream(new MemoryStream(((ASN1OctetString)info.getContent()).getOctets()));

                AuthenticatedSafe authSafe = new AuthenticatedSafe((ASN1Sequence)bIn.readObject());
                ContentInfo[]     c        = authSafe.getContentInfo();

                for (int i = 0; i != c.Length; i++)
                {
                    if (c[i].getContentType().Equals(PKCSObjectIdentifiers.data))
                    {
                        ASN1InputStream dIn = new ASN1InputStream(new MemoryStream(((ASN1OctetString)c[i].getContent()).getOctets()));
                        ASN1Sequence    seq = (ASN1Sequence)dIn.readObject();

                        for (int j = 0; j != seq.size(); j++)
                        {
                            SafeBag b = new SafeBag((ASN1Sequence)seq.getObjectAt(j));
                            if (b.getBagId().Equals(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag))
                            {
                                EncryptedPrivateKeyInfo eIn      = EncryptedPrivateKeyInfo.getInstance(b.getBagValue());
                                PrivateKeyInfo          privInfo = PrivateKeyInfoFactory.createPrivateKeyInfo(password, eIn);
                                AsymmetricKeyParameter  privKey  = PrivateKeyFactory.CreateKey(privInfo);

                                //
                                // set the attributes on the key
                                //
                                Hashtable          attributes = new Hashtable();
                                AsymmetricKeyEntry pkcs12Key  = new AsymmetricKeyEntry(privKey, attributes);
                                String             alias      = null;
                                ASN1OctetString    localId    = null;

                                if (b.getBagAttributes() != null)
                                {
                                    IEnumerator e = b.getBagAttributes().getObjects();
                                    while (e.MoveNext())
                                    {
                                        ASN1Sequence        sq      = (ASN1Sequence)e.Current;
                                        DERObjectIdentifier aOid    = (DERObjectIdentifier)sq.getObjectAt(0);
                                        ASN1Set             attrSet = (ASN1Set)sq.getObjectAt(1);
                                        ASN1Encodable       attr    = null;

                                        if (attrSet.size() > 0)
                                        {
                                            attr = attrSet.getObjectAt(0);

                                            attributes.Add(aOid.getId(), attr);
                                        }

                                        if (aOid.Equals(PKCSObjectIdentifiers.pkcs_9_at_friendlyName))
                                        {
                                            alias = ((DERBMPString)attr).getString();
                                            keys.Add(alias, pkcs12Key);
                                        }
                                        else if (aOid.Equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId))
                                        {
                                            localId = (ASN1OctetString)attr;
                                        }
                                    }
                                }

                                if (localId != null)
                                {
                                    String name = byteArrayToString(Hex.encode(localId.getOctets()));

                                    if (alias == null)
                                    {
                                        keys.Add(name, pkcs12Key);
                                    }
                                    else
                                    {
                                        localIds.Add(alias, name);
                                    }
                                }
                                else
                                {
                                    unmarkedKey = true;
                                    keys.Add("unmarked", privKey);
                                }
                            }
                            else if (b.getBagId().Equals(PKCSObjectIdentifiers.certBag))
                            {
                                chain.Add(b);
                            }
                            else
                            {
                                Console.WriteLine("extra " + b.getBagId());
                                Console.WriteLine("extra " + ASN1Dump.dumpAsString(b));
                            }
                        }
                    }
                    else if (c[i].getContentType().Equals(PKCSObjectIdentifiers.encryptedData))
                    {
                        EncryptedData d   = new EncryptedData((ASN1Sequence)c[i].getContent());
                        ASN1Sequence  seq = decryptData(d.getEncryptionAlgorithm(), d.getContent().getOctets(), password);

                        for (int j = 0; j != seq.size(); j++)
                        {
                            SafeBag b = new SafeBag((ASN1Sequence)seq.getObjectAt(j));

                            if (b.getBagId().Equals(PKCSObjectIdentifiers.certBag))
                            {
                                chain.Add(b);
                            }
                            else if (b.getBagId().Equals(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag))
                            {
                                EncryptedPrivateKeyInfo eIn      = EncryptedPrivateKeyInfo.getInstance(b.getBagValue());
                                PrivateKeyInfo          privInfo = PrivateKeyInfoFactory.createPrivateKeyInfo(password, eIn);
                                AsymmetricKeyParameter  privKey  = PrivateKeyFactory.CreateKey(privInfo);

                                //
                                // set the attributes on the key
                                //
                                Hashtable          attributes = new Hashtable();
                                AsymmetricKeyEntry pkcs12Key  = new AsymmetricKeyEntry(privKey, attributes);
                                String             alias      = null;
                                ASN1OctetString    localId    = null;

                                IEnumerator e = b.getBagAttributes().getObjects();
                                while (e.MoveNext())
                                {
                                    ASN1Sequence        sq      = (ASN1Sequence)e.Current;
                                    DERObjectIdentifier aOid    = (DERObjectIdentifier)sq.getObjectAt(0);
                                    ASN1Set             attrSet = (ASN1Set)sq.getObjectAt(1);
                                    ASN1Encodable       attr    = null;

                                    if (attrSet.size() > 0)
                                    {
                                        attr = attrSet.getObjectAt(0);

                                        attributes.Add(aOid.getId(), attr);
                                    }

                                    if (aOid.Equals(PKCSObjectIdentifiers.pkcs_9_at_friendlyName))
                                    {
                                        alias = ((DERBMPString)attr).getString();
                                        keys.Add(alias, pkcs12Key);
                                    }
                                    else if (aOid.Equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId))
                                    {
                                        localId = (ASN1OctetString)attr;
                                    }
                                }

                                String name = byteArrayToString(Hex.encode(localId.getOctets()));

                                if (alias == null)
                                {
                                    keys.Add(name, pkcs12Key);
                                }
                                else
                                {
                                    localIds.Add(alias, name);
                                }
                            }
                            else if (b.getBagId().Equals(PKCSObjectIdentifiers.keyBag))
                            {
                                PrivateKeyInfo         pIn     = PrivateKeyInfo.getInstance(b.getBagValue());
                                AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(pIn);

                                //
                                // set the attributes on the key
                                //
                                String             alias      = null;
                                ASN1OctetString    localId    = null;
                                Hashtable          attributes = new Hashtable();
                                AsymmetricKeyEntry pkcs12Key  = new AsymmetricKeyEntry(privKey, attributes);

                                IEnumerator e = b.getBagAttributes().getObjects();
                                while (e.MoveNext())
                                {
                                    ASN1Sequence        sq      = (ASN1Sequence)e.Current;
                                    DERObjectIdentifier aOid    = (DERObjectIdentifier)sq.getObjectAt(0);
                                    ASN1Set             attrSet = (ASN1Set)sq.getObjectAt(1);
                                    ASN1Encodable       attr    = null;

                                    if (attrSet.size() > 0)
                                    {
                                        attr = attrSet.getObjectAt(0);

                                        attributes.Add(aOid.getId(), attr);
                                    }

                                    if (aOid.Equals(PKCSObjectIdentifiers.pkcs_9_at_friendlyName))
                                    {
                                        alias = ((DERBMPString)attr).getString();
                                        keys.Add(alias, pkcs12Key);
                                    }
                                    else if (aOid.Equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId))
                                    {
                                        localId = (ASN1OctetString)attr;
                                    }
                                }

                                String name = byteArrayToString(Hex.encode(localId.getOctets()));

                                if (alias == null)
                                {
                                    keys.Add(name, pkcs12Key);
                                }
                                else
                                {
                                    localIds.Add(alias, name);
                                }
                            }
                            else
                            {
                                Console.WriteLine("extra " + b.getBagId());
                                Console.WriteLine("extra " + ASN1Dump.dumpAsString(b));
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("extra " + c[i].getContentType().getId());
                        Console.WriteLine("extra " + ASN1Dump.dumpAsString(c[i].getContent()));
                    }
                }
            }

            certs      = new Hashtable();
            chainCerts = new Hashtable();
            keyCerts   = new Hashtable();

            for (int i = 0; i != chain.Count; i++)
            {
                SafeBag         b    = (SafeBag)chain[i];
                CertBag         cb   = new CertBag((ASN1Sequence)b.getBagValue());
                X509Certificate cert = new X509Certificate(((ASN1OctetString)cb.getCertValue()).getOctets());

                //
                // set the attributes
                //
                Hashtable            attributes = new Hashtable();
                X509CertificateEntry pkcs12cert = new X509CertificateEntry(cert, attributes);
                ASN1OctetString      localId    = null;
                String alias = null;

                if (b.getBagAttributes() != null)
                {
                    IEnumerator e = b.getBagAttributes().getObjects();
                    while (e.MoveNext())
                    {
                        ASN1Sequence        sq      = (ASN1Sequence)e.Current;
                        DERObjectIdentifier aOid    = (DERObjectIdentifier)sq.getObjectAt(0);
                        ASN1Set             attrSet = (ASN1Set)sq.getObjectAt(1);

                        if (attrSet.size() > 0)
                        {
                            ASN1Encodable attr = attrSet.getObjectAt(0);

                            attributes.Add(aOid.getId(), attr);

                            if (aOid.Equals(PKCSObjectIdentifiers.pkcs_9_at_friendlyName))
                            {
                                alias = ((DERBMPString)attr).getString();
                            }
                            else if (aOid.Equals(PKCSObjectIdentifiers.pkcs_9_at_localKeyId))
                            {
                                localId = (ASN1OctetString)attr;
                            }
                        }
                    }
                }

                chainCerts.Add(new CertId(cert.getPublicKey()), pkcs12cert);

                if (unmarkedKey)
                {
                    if (keyCerts.Count == 0)
                    {
                        String name = byteArrayToString(Hex.encode(new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(cert.getPublicKey())).getKeyIdentifier()));

                        keyCerts.Add(name, pkcs12cert);
                        keys.Add(name, keys["unmarked"]);

                        keys.Remove("unmarked");
                    }
                }
                else
                {
                    if (alias == null)
                    {
                        if (localId != null)
                        {
                            String name = byteArrayToString(Hex.encode(localId.getOctets()));

                            keyCerts.Add(name, pkcs12cert);
                        }
                    }
                    else
                    {
                        certs.Add(alias, pkcs12cert);
                    }
                }
            }
        }