OCSP PDF 签名嵌入

http://what-when-how.com/itext-5/digital-signatures-ocsp-and-timestamping-part-2-itext-5/

http://www.verypdf.com/document/pdf-format-reference/pg_0740.htm

http://www.adobe.com/devnet-docs/acrobatetk/tools/DigSig/oids.html

http://permalink.gmane.org/gmane.comp.windows.dotnet.itextsharp.general/2662

http://stackoverflow.com/questions/10424968/add-signed-authenticated-attributes-to-cms-signature-using-bouncycastle

https://sourceforge.net/projects/podofo/?source=typ_redirect

加入pdf ocsp 签名属性

package net.netca.pki.keyx.utils;

import net.netca.pki.crypto.android.constant.NetcaPKIConst;
import net.netca.pki.crypto.android.interfaces.NetcaCryptoInterface;
import net.netca.pki.crypto.android.interfaces.SignatureInterface;

import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Enumerated;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.ASN1Set;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
import org.bouncycastle.asn1.cms.SignedData;
import org.bouncycastle.asn1.cms.SignerIdentifier;
import org.bouncycastle.asn1.cms.SignerInfo;
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;

import java.io.ByteArrayInputStream;
import java.security.MessageDigest;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.List;


public class CmsHelper
{
    public static final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1";
    public static final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2";
    public static final String ID_RSA = "1.2.840.113549.1.1.1";
    public static final String ID_SHA1WITHRSA = "1.2.840.113549.1.1.5";
    public static final String ID_DSA = "1.2.840.10040.4.1";
    public static final String ID_ECDSA = "1.2.840.10045.2.1";
    public static final String ID_CONTENT_TYPE = "1.2.840.113549.1.9.3";
    public static final String ID_MESSAGE_DIGEST = "1.2.840.113549.1.9.4";
    public static final String ID_SIGNING_TIME = "1.2.840.113549.1.9.5";
    public static final String ID_ADBE_REVOCATION = "1.2.840.113583.1.1.8";
    public static final String ID_TSA = "1.2.840.113583.1.1.9.1";
    public static final String ID_OCSP = "1.3.6.1.5.5.7.48.1";
    public static final String ID_AA_SIGNING_CERTIFICATE_V1 = "1.2.840.113549.1.9.16.2.12";
    public static final String ID_AA_SIGNING_CERTIFICATE_V2 = "1.2.840.113549.1.9.16.2.47";
	
    static int version = 1;
    static int signerversion = 1;
    static String digestAlgorithmOid = ID_SHA1WITHRSA;
    static String digestEncryptionAlgorithmOid = ID_SHA1WITHRSA;


    public static byte[] SignedData(byte[] data, X509Certificate[] cers, NetcaCryptoInterface netcaCryptoInterface, List<byte[]> ocsps, List<byte[]> crls) throws Exception {
        net.netca.pki.Certificate cert = new net.netca.pki.Certificate(cers[0].getEncoded());
        try {
            byte[] hashData = MessageDigest.getInstance("SHA1").digest(data);
            SignatureInterface signatureInterface = netcaCryptoInterface.getSignatureInterface();
            if ((ocsps == null || ocsps.isEmpty()) && (crls == null || crls.isEmpty())) {
                signatureInterface.init(NetcaPKIConst.Signature.SHA1WITHRSA, cert, null);
                signatureInterface.signUpdate(hashData, 0, hashData.length);
                byte[] signeddata = signatureInterface.sign();
                return ToSignedDataDer(hashData, null, cers, signeddata, true);
            } else {
                DERSet ds = getAuthenticatedAttributeSet(hashData, ocsps, crls);
                byte[] buf = ds.getEncoded(ASN1Encoding.DER);
                signatureInterface.init(NetcaPKIConst.Signature.SHA1WITHRSA, cert, null);
                signatureInterface.signUpdate(buf, 0, buf.length);
                byte[] signeddata = signatureInterface.sign();
                return ToSignedDataDer(hashData, ASN1Set.getInstance(new DERTaggedObject(false, 0, ds), true), cers, signeddata, true);
            }
        }finally {
            cert.free();
        }
    }
	
	//SHA1withRSA
	private static byte[] ToSignedDataDer(byte[] content, ASN1Set signedAttr, X509Certificate[] cers, byte[] signature, boolean isAttached) throws Exception
	{
		//digestAlgorithms
		DERSet digestAlgorithms= new DERSet(
				new AlgorithmIdentifier[]{new AlgorithmIdentifier(X509ObjectIdentifiers.id_SHA1)});
		//contentInfo
		ContentInfo contentInfo= null;
		if(isAttached)
			contentInfo= new ContentInfo(CMSObjectIdentifiers.data,new DEROctetString(content));
		else
			contentInfo= new ContentInfo(CMSObjectIdentifiers.data,null);
		//certificates
		Certificate[] bcCert = new Certificate[cers.length];
		
		for(int i = 0;i <cers.length;i++){
			X509Certificate cer = cers[i];
			ASN1Sequence seq= ASN1Sequence.getInstance(cer.getEncoded());
			bcCert[i] = Certificate.getInstance(seq);
		}
		DERSet certificates= new DERSet(
				bcCert);
		IssuerAndSerialNumber sid = new IssuerAndSerialNumber(bcCert[bcCert.length-1]);

		
		SignerInfo sinfo= new SignerInfo(
				new SignerIdentifier(sid),
				new AlgorithmIdentifier(X509ObjectIdentifiers.id_SHA1),
				signedAttr,
				new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption,DERNull.INSTANCE),
				new DEROctetString(signature),
				null);
		DERSet signerInfos= new DERSet(new SignerInfo[]{sinfo});
		
		
		//SignedData
		SignedData signeddata= new SignedData(
				digestAlgorithms,
				contentInfo,
				certificates,
				null,
				signerInfos);
		//cms
	    ContentInfo data= new ContentInfo(
				CMSObjectIdentifiers.signedData,
				signeddata);
		return data.getEncoded(ASN1Encoding.DER);
	}

    
    private static DERSet getAuthenticatedAttributeSet(byte[] secondDigest, Collection<byte[]> ocspBytes, Collection<byte[]> crlBytes) throws Exception {
        
        ASN1EncodableVector attribute = new ASN1EncodableVector();
        ASN1EncodableVector v = new ASN1EncodableVector();
        v.add(new ASN1ObjectIdentifier(ID_CONTENT_TYPE));
        v.add(new DERSet(new ASN1ObjectIdentifier(ID_PKCS7_DATA)));
        attribute.add(new DERSequence(v));
        v = new ASN1EncodableVector();
        v.add(new ASN1ObjectIdentifier(ID_MESSAGE_DIGEST));
        v.add(new DERSet(new DEROctetString(secondDigest)));
        attribute.add(new DERSequence(v));
        boolean haveCrl = false;
        if (crlBytes != null) {
            for (byte[] bCrl : crlBytes) {
                if (bCrl != null) {
                    haveCrl = true;
                    break;
                }
            }
        }
        if (ocspBytes != null || haveCrl) {
            v = new ASN1EncodableVector();
            v.add(new ASN1ObjectIdentifier(ID_ADBE_REVOCATION));

            ASN1EncodableVector revocationV = new ASN1EncodableVector();

            if (haveCrl) {
                ASN1EncodableVector v2 = new ASN1EncodableVector();
                for (byte[] bCrl : crlBytes) {
                    if (bCrl == null){
                        continue;
                    }
                    ASN1InputStream t = new ASN1InputStream(new ByteArrayInputStream(bCrl));
                    v2.add(t.readObject());
                }
                revocationV.add(new DERTaggedObject(true, 0, new DERSequence(v2)));
            }

            if (ocspBytes != null&&!ocspBytes.isEmpty()) {
            	ASN1EncodableVector vo1 = new ASN1EncodableVector();
            	for(byte[] o:ocspBytes){
            		if(o==null){
            			continue;
            		}
	                DEROctetString doctet = new DEROctetString(o);
	                ASN1EncodableVector v2 = new ASN1EncodableVector();
	                v2.add(OCSPObjectIdentifiers.id_pkix_ocsp_basic);
	                v2.add(doctet);
	                ASN1Enumerated den = new ASN1Enumerated(0);
	                ASN1EncodableVector v3 = new ASN1EncodableVector();
	                v3.add(den);
	                v3.add(new DERTaggedObject(true, 0, new DERSequence(v2)));
	                vo1.add(new DERSequence(v3));
	                
            	}
            	revocationV.add(new DERTaggedObject(true, 1, new DERSequence(vo1)));
            }

            v.add(new DERSet(new DERSequence(revocationV)));
            attribute.add(new DERSequence(v));
        }
       

        return new DERSet(attribute);
    
}
	
	 
}


			Attributes signedAttr = null;
			byte[] signedAttrData = null;
			if((ocspList!=null&&!ocspList.isEmpty())||(crlList!=null&&!crlList.isEmpty())){
				MessageDigest md = MessageDigest.getInstance("SHA-1");
				md.update(data);
				byte[] secondDigest = md.digest();
				signedAttr = Attributes.getInstance(CmsHelper.getAuthenticatedAttributeSet(secondDigest, ocspList, crlList));
				signedAttrData = signedAttr.getEncoded(ASN1Encoding.DER);
			}else{
				signedAttrData = data;
			}
			signResult = sign(certInfo, "SHA1WithRSA", signedAttrData )
			byte[] retData = CmsHelper.ToSignedDataDer(data, signedAttr, certs, signResult, true);

获取ocsp 和crl地址

	public static String getOCSPURL(X509Certificate certificate) {
		try {
			ASN1Primitive obj = getExtensionValue(certificate,
					Extension.authorityInfoAccess.getId());
			if (obj == null) {
				return null;
			}
			ASN1Sequence AccessDescriptions = (ASN1Sequence) obj;
			for (int i = 0; i < AccessDescriptions.size(); i++) {
				ASN1Sequence AccessDescription = (ASN1Sequence) AccessDescriptions
						.getObjectAt(i);
				if (AccessDescription.size() == 2) {
					if ((AccessDescription.getObjectAt(0) instanceof ASN1ObjectIdentifier)) {
						ASN1ObjectIdentifier id = (ASN1ObjectIdentifier) AccessDescription
								.getObjectAt(0);
						if ("1.3.6.1.5.5.7.48.1".equals(id.getId())) {
							ASN1Primitive description = (ASN1Primitive) AccessDescription
									.getObjectAt(1);
							String AccessLocation = getStringFromGeneralName(description);
							if (AccessLocation == null) {
								return "";
							}
							return AccessLocation;
						}
					}
				}
			}
		} catch (IOException e) {
			return null;
		}
		return null;
	}

	public static String getCRLURL(X509Certificate certificate)
			throws CertificateParsingException {
		ASN1Primitive obj;
		try {
			obj = getExtensionValue(certificate,
					Extension.cRLDistributionPoints.getId());
		} catch (IOException e) {
			obj = null;
		}
		if (obj == null) {
			return null;
		}
		CRLDistPoint dist = CRLDistPoint.getInstance(obj);
		DistributionPoint[] dists = dist.getDistributionPoints();
		for (DistributionPoint p : dists) {
			DistributionPointName distributionPointName = p
					.getDistributionPoint();
			if (0 == distributionPointName.getType()) {
				GeneralNames generalNames = (GeneralNames) distributionPointName
						.getName();
				GeneralName[] names = generalNames.getNames();
				for (GeneralName name : names) {
					if (name.getTagNo() == 6) {
						DERIA5String derStr = DERIA5String.getInstance(
								(ASN1TaggedObject) name.toASN1Primitive(),
								false);
						return derStr.getString();
					}
				}
			}
		}
		return null;
	}

	private static String getStringFromGeneralName(ASN1Primitive names)
			throws IOException {
		ASN1TaggedObject taggedObject = (ASN1TaggedObject) names;
		return new String(ASN1OctetString.getInstance(taggedObject, false)
				.getOctets(), "ISO-8859-1");
	}

	private static ASN1Primitive getExtensionValue(X509Certificate certificate,
			String oid) throws IOException {
		byte[] bytes = certificate.getExtensionValue(oid);
		if (bytes == null) {
			return null;
		}
		ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(
				bytes));
		ASN1OctetString octs = (ASN1OctetString) aIn.readObject();
		aIn = new ASN1InputStream(new ByteArrayInputStream(octs.getOctets()));
		return aIn.readObject();
	}

itext

	public static  void signPdfByiText(ExternalSignature externalSignature, String pdfFile,String bitmapFilePath, String savePath,int pageIndex, RectF rect,X509Certificate[] chain,List<byte[]>crlBytes,List<byte[]>ocsp, int estimatedSize) throws Exception{
        PdfReader reader = new PdfReader(pdfFile);
        File file = new File(savePath);
        file.delete();
        file.createNewFile();
        FileOutputStream fos = new FileOutputStream(file);
        PdfStamper pdfStamper = PdfStamper.createSignature(reader, fos, '\0', null, true);
        PdfSignatureAppearance sap = pdfStamper.getSignatureAppearance();
        sap.setVisibleSignature(new Rectangle(rect.left, rect.top, rect.right, rect.bottom), pageIndex+1, UUID.randomUUID().toString());
        if(!TextUtils.isEmpty(bitmapFilePath)){
            sap.setSignatureGraphic(com.itextpdf.text.Image.getInstance(bitmapFilePath));
            sap.setRenderingMode(RenderingMode.GRAPHIC);
        }else{
        	sap.setRenderingMode(RenderingMode.DESCRIPTION);
        }

        BouncyCastleDigest externalDigest = new BouncyCastleDigest();
        byte[] ocspData = null;
        if (estimatedSize == 0) {
            estimatedSize = 8192;
            if (crlBytes != null) {
                for (byte[] element : crlBytes) {
                    if(element == null){
                        continue;
                    }
                    estimatedSize += element.length + 10;
                }
            }
            if (ocsp != null) {
                for (byte[] element : ocsp) {
                    if(element == null){
                        continue;
                    }
                    estimatedSize += 4192;
                    ocspData = element;
                }
            }
        }
        String displayData = chain[0].getSubjectDN().toString();
        sap.setCertificate(chain[0]);
        Font font = new Font(BaseFont.createFont(Constant.FONT,BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED));
        sap.setLayer2Font(font);
        sap.setSignatureCreator(StringUtil.getCertDN(displayData, "CN="));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String layer2Text = String.format("%s 签名日期:%s", StringUtil.getCertDN(displayData, "CN="), sdf.format(new Date()));
        sap.setLayer2Text(layer2Text);
        PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE,PdfName.ADBE_PKCS7_SHA1);
        dic.setSignatureCreator(sap.getSignatureCreator());
        dic.setDate(new PdfDate(sap.getSignDate()));
        sap.setCryptoDictionary(dic); 

        HashMap<PdfName, Integer> exc = new HashMap();
        exc.put(PdfName.CONTENTS, new Integer(estimatedSize * 2 + 2));
        sap.preClose(exc);

        String hashAlgorithm = DigestAlgorithms.SHA1;
        PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null,
                externalDigest, true);
        InputStream data = sap.getRangeStream();
        byte[] hash = DigestAlgorithms.digest(data,
                externalDigest.getMessageDigest(hashAlgorithm));
        byte[]secondDigest = DigestAlgorithms.digest(new ByteArrayInputStream(hash),
                externalDigest.getMessageDigest(hashAlgorithm));
        byte[] sh = sgn.getAuthenticatedAttributeBytes(secondDigest, ocspData, crlBytes,
                CryptoStandard.CMS);
        byte[] extSignature = externalSignature.sign(sh);
        sgn.setExternalDigest(extSignature, hash,
                externalSignature.getEncryptionAlgorithm());

        byte[] encodedSig = sgn.getEncodedPKCS7(secondDigest, null, ocspData,
                crlBytes, CryptoStandard.CMS);
        if (estimatedSize < encodedSig.length) {
            throw new IOException("Not enough space");
        }
        byte[] paddedSig = new byte[estimatedSize];
        System.arraycopy(encodedSig, 0, paddedSig, 0, encodedSig.length);

        PdfDictionary dic2 = new PdfDictionary();
        dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
        sap.close(dic2);


    }

转载于:https://my.oschina.net/zdglf/blog/800651

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值