コード例 #1
0
ファイル: PDFSigner.cs プロジェクト: tixsys/esteid
        private byte[] ComputeHash(EstEIDReader estEidReader, byte[] data)
        {
            uint       rc, digest_length = 0;
            const uint hash_length = Digest.SHA1_LENGTH;

            Digest hash = new Digest(estEidReader);

            rc = hash.InitDigest(Digest.HashAlgorithm.SHA1);
            if (rc != EstEIDReader.ESTEID_OK)
            {
                throw new Exception(Resources.CARD_HASH_INIT);
            }

            rc = hash.UpdateDigest(data, (uint)data.Length);
            if (rc != EstEIDReader.ESTEID_OK)
            {
                throw new Exception(Resources.CARD_HASH_UPDATE);
            }

            HGlobalSafeHandle raw       = new HGlobalSafeHandle((int)hash_length);
            IntPtr            hashBytes = raw;

            if (hashBytes == IntPtr.Zero)
            {
                throw new OutOfMemoryException(Resources.OUT_OF_MEMORY);
            }

            rc = hash.FinalizeDigest(ref hashBytes, ref digest_length);
            if (rc != EstEIDReader.ESTEID_OK)
            {
                throw new Exception(Resources.CARD_HASH_FINALIZE);
            }

            return(raw.ToByteArray());
        }
コード例 #2
0
ファイル: PDFSigner.cs プロジェクト: tixsys/esteid
        private byte[] TimestampAuthorityResponse(EstEIDReader estEidReader, byte[] signedPkcs)
        {
            ArrayList newSigners = new ArrayList();

            CmsSignedData sd = new CmsSignedData(signedPkcs);

            foreach (SignerInformation si in sd.GetSignerInfos().GetSigners())
            {
                // possible TSA URLs
                //string TsaServerUrl = "http://www.edelweb.fr/cgi-bin/service-tsp";
                //string TsaServerUrl = "http://dse200.ncipher.com/TSS/HttpTspServer";

                byte[] signedDigest  = si.GetSignature();
                byte[] timeStampHash = ComputeHash(estEidReader, signedDigest);

                string TsaServerUrl = stamp.Url;
                string TsaUser      = stamp.User;
                string TsaPassword  = stamp.Password;
                string error        = string.Empty;

                byte[] timeStampToken = X509Utils.GetTimestampToken(TsaServerUrl,
                                                                    TsaUser,
                                                                    TsaPassword,
                                                                    timeStampHash,
                                                                    ref error);

                if (timeStampToken == null)
                {
                    throw new Exception(Resources.TSA_ERROR + error);
                }

                Hashtable  ht     = new Hashtable();
                Asn1Object derObj = new Asn1InputStream(timeStampToken).ReadObject();
                DerSet     derSet = new DerSet(derObj);

                Org.BouncyCastle.Asn1.Cms.Attribute unsignAtt = new Org.BouncyCastle.Asn1.Cms.Attribute(
                    new DerObjectIdentifier(X509Utils.ID_TIME_STAMP_TOKEN), derSet);

                ht.Add(X509Utils.ID_TIME_STAMP_TOKEN, unsignAtt);

                Org.BouncyCastle.Asn1.Cms.AttributeTable unsignedAtts = new Org.BouncyCastle.Asn1.Cms.AttributeTable(ht);

                newSigners.Add(SignerInformation.ReplaceUnsignedAttributes(si, unsignedAtts));
            }

            SignerInformationStore newSignerInformationStore = new SignerInformationStore(newSigners);

            CmsSignedData newSd = CmsSignedData.ReplaceSigners(sd, newSignerInformationStore);

            // Encode the CMS/PKCS #7 message
            return(newSd.GetEncoded());
        }
コード例 #3
0
ファイル: PDFSigner.cs プロジェクト: tixsys/esteid
        private byte[] ComputeHash(EstEIDReader estEidReader, PdfSignatureAppearance sap)
        {
            Digest     hash          = new Digest(estEidReader);
            const uint hash_length   = Digest.SHA1_LENGTH;
            uint       digest_length = 0;
            uint       rc;

            rc = hash.InitDigest(Digest.HashAlgorithm.SHA1);
            if (rc != EstEIDReader.ESTEID_OK)
            {
                throw new Exception(Resources.CARD_HASH_INIT);
            }

            Stream       s    = sap.RangeStream;
            MemoryStream ss   = new MemoryStream();
            int          read = 0;

            byte[] buff = new byte[8192];
            while ((read = s.Read(buff, 0, 8192)) > 0)
            {
                ss.Write(buff, 0, read);
                rc = hash.UpdateDigest(buff, (uint)read);
                if (rc != EstEIDReader.ESTEID_OK)
                {
                    throw new Exception(Resources.CARD_HASH_UPDATE);
                }
            }

            HGlobalSafeHandle raw       = new HGlobalSafeHandle((int)hash_length);
            IntPtr            hashBytes = raw;

            if (hashBytes == IntPtr.Zero)
            {
                throw new OutOfMemoryException(Resources.OUT_OF_MEMORY);
            }

            rc = hash.FinalizeDigest(ref hashBytes, ref digest_length);
            if (rc != EstEIDReader.ESTEID_OK)
            {
                throw new Exception(Resources.CARD_HASH_FINALIZE);
            }

            return(raw.ToByteArray());
        }
コード例 #4
0
ファイル: PDFSigner.cs プロジェクト: tixsys/esteid
        private void SignUsingEstEIDCard2(string filename, string outfile)
        {
            statusHandler(Resources.VERIFYING_DOCUMENT, false);

            AcroFields af           = this.reader.AcroFields;
            ArrayList  names        = af.GetSignatureNames();
            bool       nextRevision = ((names != null) && (names.Count > 0));

            // already signed ?
            if (nextRevision)
            {
                // pick always first signature
                string   name   = (string)names[0];
                PdfPKCS7 pkc7   = af.VerifySignature(name);
                bool     verify = pkc7.Verify();
                if (!verify)
                {
                    string who = PdfPKCS7.GetSubjectFields(pkc7.SigningCertificate).GetField("CN");
                    throw new DocVerifyException(Resources.DOC_VERIFY_FAILED + who);
                }
            }

            statusHandler(Resources.CONNECTING_SMARTCARD, false);

            // open EstEID
            EstEIDReader estEidReader = new EstEIDReader();
            string       pkcs11_lib   = conf.PKCS11DriverPath;
            bool         b            = estEidReader.Open(pkcs11_lib);

            if (b == false)
            {
                throw new Exception(Resources.PKCS11_OPEN);
            }

            statusHandler(Resources.READ_CERTS, false);
            PKCS11Signer signer = LocateSigner(estEidReader);

            Org.BouncyCastle.X509.X509Certificate[] chain = X509Utils.LoadCertificate(signer.Cert.RawData);

            statusHandler(Resources.VERIFYING_OCSP, false);
            OCSPClientEstEID ocspClient = OCSPClient(chain[0]);

            if (ocspClient == null)
            {
                throw new Exception(this.lastError);
            }

            byte[] ocsp = ocspClient.GetEncoded();
            if (ocsp == null)
            {
                throw new RevocationException(ocspClient.lastError);
            }

            X509Certificate2 card = signer.Cert;
            Oid oid = card.SignatureAlgorithm;

            if (oid.Value != PkcsObjectIdentifiers.Sha1WithRsaEncryption.Id)
            {
                throw new Exception(Resources.INVALID_CERT);
            }

            PdfReader  reader   = new PdfReader(filename);
            Document   document = new Document(reader.GetPageSizeWithRotation(1));
            PdfStamper stp      = PdfStamper.CreateSignature(reader, new FileStream(outfile, FileMode.Create), '\0', null, nextRevision);

            if (metadata != null)
            {
                stp.XmpMetadata = metadata.getStreamedMetaData();
            }
            PdfSignatureAppearance sap = stp.SignatureAppearance;

            if (appearance.Visible)
            {
                if (appearance.SigLocation.UseSector)
                {
                    appearance.SigLocation.Bounds = document.PageSize;
                }
                sap.SetVisibleSignature(appearance.SigLocation, (int)appearance.Page, null);
            }
            sap.SignDate = DateTime.Now;
            sap.SetCrypto(null, chain, null, null);
            sap.Reason      = (appearance.Reason.Length > 0) ? appearance.Reason : null;
            sap.Location    = (appearance.Location.Length > 0) ? appearance.Location : null;
            sap.Contact     = (appearance.Contact.Length > 0) ? appearance.Contact : null;
            sap.Acro6Layers = true;
            sap.Render      = appearance.SignatureRender;
            sap.Layer2Text  = appearance.SignatureText(sap.SignDate, chain[0]);
            PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_SHA1);

            dic.Date = new PdfDate(sap.SignDate);
            dic.Name = PdfPKCS7.GetSubjectFields(chain[0]).GetField("CN");
            if (sap.Reason != null)
            {
                dic.Reason = sap.Reason;
            }
            if (sap.Location != null)
            {
                dic.Location = sap.Location;
            }
            if (sap.Contact != null)
            {
                dic.Contact = sap.Contact;
            }
            sap.CryptoDictionary = dic;
            sap.SetExternalDigest(new byte[SIGNATURE_LENGTH], new byte[Digest.SHA1_LENGTH], "RSA");

            // expect 6K to be enough if TSA response, else 2K ?
            int       csize = (stamp != null) ? 1024 * 6 : 1024 * 2;
            Hashtable exc   = new Hashtable();

            exc[PdfName.CONTENTS] = csize * 2 + 2;
            sap.PreClose(exc);

            // compute hash based on PDF bytes
            byte[] digest = ComputeHash(estEidReader, sap);

            statusHandler(Resources.ADD_SIGNATURE, false);
            // sign hash
            byte[] rsadata = EstEIDCardSign(estEidReader, signer, digest);
            // if null, user requested Cancel
            if (rsadata == null)
            {
                throw new Exception(Resources.CARD_INTERNAL_ERROR);
            }

            // create PKCS#7 envelope
            PdfPKCS7 pk7 = new PdfPKCS7(null, chain, null, "SHA1", true);

            pk7.SetExternalDigest(rsadata, digest, "RSA");

            byte[] pk = pk7.GetEncodedPKCS7();

            // user wants to add TSA response ?
            if (stamp != null && pk != null)
            {
                statusHandler(Resources.TSA_REQUEST, false);
                pk = TimestampAuthorityResponse(estEidReader, pk);
            }

            // PKCS#7 bytes too large ?
            if (pk.Length >= csize)
            {
                throw new Exception(Resources.MEMORY_ERROR);
            }

            byte[] outc = new byte[csize];

            PdfDictionary dic2 = new PdfDictionary();

            Array.Copy(pk, 0, outc, 0, pk.Length);

            dic2.Put(PdfName.CONTENTS, new PdfString(outc).SetHexWriting(true));
            sap.Close(dic2);
        }
コード例 #5
0
ファイル: PDFSigner.cs プロジェクト: tixsys/esteid
        private PKCS11Signer LocateSigner(EstEIDReader estEidReader)
        {
            uint slots;
            uint i, rc;
            X509Certificate2Collection col = null;
            Mechanism        mech          = null;
            PKCS11Signer     signer        = null;
            X509Certificate2 cert          = null;
            ArrayList        signers       = null;

            slots = estEidReader.GetSlotCount(1);
            if (slots == 0)
            {
                throw new Exception(Resources.CARD_MISSING);
            }

            col     = new X509Certificate2Collection();
            mech    = new Mechanism(Mechanism.CKF_SIGN | Mechanism.CKF_HW);
            signers = new ArrayList((int)slots);

            for (i = 0; i < slots; i++)
            {
                rc = estEidReader.IsMechanismSupported(i, mech);
                // can't use this slot mechanism for signing
                if (rc != EstEIDReader.ESTEID_OK)
                {
                    // Mechanism not supported ?
                    if (rc == EstEIDReader.ESTEID_ERR)
                    {
                        continue;
                    }
                    throw new PKCS11Exception(rc);
                }

                TokenInfo token = new TokenInfo(estEidReader);
                rc = token.ReadInfo(i);
                if (rc != EstEIDReader.ESTEID_OK)
                {
                    throw new PKCS11Exception(rc);
                }

                PKCS11Cert pkcs11Cert = new PKCS11Cert();
                rc = estEidReader.LocateCertificate(i, pkcs11Cert);
                if (rc != EstEIDReader.ESTEID_OK)
                {
                    // did we find a certificate ?
                    if (rc == EstEIDReader.ESTEID_ERR)
                    {
                        continue;
                    }
                    throw new PKCS11Exception(rc);
                }

                byte[] raw = pkcs11Cert.CertificateToByteArray();

                // can we use this cert for signing ?
                string s = X509Utils.GetSubjectFields(raw, "OU");
                if (!s.Equals("digital signature"))
                {
                    continue;
                }

                cert = new X509Certificate2(raw);
                col.Add(cert);

                signer = new PKCS11Signer(i, cert, token);
                signers.Add(signer);
            }

            // no valid certs found ?
            if (col.Count == 0)
            {
                throw new Exception(Resources.CERTS_MISSING);
            }

            X509Certificate2Collection sel = X509CertificateUI.SelectFromCollection(col,
                                                                                    Resources.UI_CERTIFICATES, Resources.UI_PICK_CERTIFICATE);

            // user requested Cancel or there are no certs ?
            if (sel == null || sel.Count == 0)
            {
                throw new CancelException(Resources.ACTION_CANCELED);
            }

            X509Certificate2Enumerator en = sel.GetEnumerator();

            en.MoveNext();
            cert = en.Current;
            byte[] s1 = cert.PublicKey.EncodedKeyValue.RawData;

            IEnumerator enumerator = signers.GetEnumerator();

            while (enumerator.MoveNext())
            {
                signer = (PKCS11Signer)enumerator.Current;

                byte[] s2 = signer.Cert.PublicKey.EncodedKeyValue.RawData;
                if (Arrays.AreEqual(s1, s2))
                {
                    return(signer);
                }
            }

            // didn't find any match ?
            // data is being altered in memory ?
            throw new Exception(Resources.CERT_DONT_MATCH);
        }
コード例 #6
0
ファイル: PDFSigner.cs プロジェクト: tixsys/esteid
        private byte[] EstEIDCardSign(EstEIDReader estEidReader, PKCS11Signer signer, Byte[] digest)
        {
            uint       rc, slot;
            const uint rsa_length    = SIGNATURE_LENGTH;
            uint       digest_length = rsa_length;
            string     pin           = string.Empty;
            TokenInfo  token         = null;

            HGlobalSafeHandle raw      = new HGlobalSafeHandle((int)rsa_length);
            IntPtr            rsaBytes = raw;

            if (rsaBytes == IntPtr.Zero)
            {
                throw new OutOfMemoryException(Resources.OUT_OF_MEMORY);
            }

            token = signer.Token;
            slot  = signer.Slot;

            if (token.LoginRequired && token.PinIsSet)
            {
                if (!token.PinPadPresent)
                {
                    pin = ReadPin(token);

                    // redraw window: single-threaded UI
                    Application.DoEvents();

                    // user requested Cancel ?
                    if (pin == null)
                    {
                        throw new CancelException(Resources.ACTION_CANCELED);
                    }
                    // no pin supplied ?
                    else if (pin == string.Empty)
                    {
                        throw new Exception(Resources.NO_PIN_SUPPLIED);
                    }
                }
                else
                {
                    // we have a PINPAD present
                    pin = null;
                    statusHandler(string.Format(Resources.UI_ENTER_PIN_ONTHE_PINPAD, token.Label), false);
                }
            }

            rc = estEidReader.Sign(slot, pin, digest, (uint)digest.Length, ref rsaBytes, ref digest_length);
            // failure ?
            if (rc != EstEIDReader.ESTEID_OK)
            {
                // signing cancelled or timed out
                if (rc == PKCS11Error.CKR_FUNCTION_CANCELED)
                {
                    throw new CancelException(Resources.ACTION_CANCELED);
                }

                throw new PKCS11Exception(rc);
            }

            return(raw.ToByteArray());
        }