Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Itext通过客户端的64进制字符串签名对pdf进行签名_Java_Pdf_Itext_Sign - Fatal编程技术网

Java Itext通过客户端的64进制字符串签名对pdf进行签名

Java Itext通过客户端的64进制字符串签名对pdf进行签名,java,pdf,itext,sign,Java,Pdf,Itext,Sign,我正在尝试使用来自整个客户端的签名(格式为base 64)对pdf文档进行签名 服务请求从文档计算哈希值 我从文档的pdf中获取内容,根据算法计算哈希值 服务接受接收到的散列并对其签名,发送接收到的签名以及要签名的文档的字节 我得到一个以64为基数的字符串和要签名的pdf字节 有可能吗?我给出一个代码示例 public byte[] insertSignature(byte[] document, String signature) { try (InputStream inputStr

我正在尝试使用来自整个客户端的签名(格式为base 64)对pdf文档进行签名

  • 服务请求从文档计算哈希值
  • 我从文档的pdf中获取内容,根据算法计算哈希值
  • 服务接受接收到的散列并对其签名,发送接收到的签名以及要签名的文档的字节
  • 我得到一个以64为基数的字符串和要签名的pdf字节
  • 有可能吗?我给出一个代码示例

    public byte[] insertSignature(byte[] document, String signature) {
        try (InputStream inputStream = new ByteArrayInputStream(document);
             ByteArrayOutputStream os = new ByteArrayOutputStream();
             ByteArrayOutputStream result = new ByteArrayOutputStream()) {
            byte[] decodeSignature = Base64.decodeBase64(signature);
            CAdESSignature cades = new CAdESSignature(decodeSignature, null, null);
            var certificate = cades.getCAdESSignerInfo(0).getSignerCertificate();
            var subject = new Subject(certificate.getSubjectX500Principal().getEncoded());
            List<String> names = getSignaturesFields(document);
            String sigFieldName = String.format("Signature %s", names.size() + 1);
            PdfName filter = PdfName.Adobe_PPKLite;
            PdfName subFilter = PdfName.ETSI_CAdES_DETACHED;
            int estimatedSize = 8192;
    
            PdfReader reader = new PdfReader(inputStream);
            StampingProperties stampingProperties = new StampingProperties();
            if (names.size() > 1) {
                stampingProperties.useAppendMode();
            }
            PdfSigner signer = new PdfSigner(reader, os, stampingProperties);
            signer.setCertificationLevel(PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED);
            PdfSignatureAppearance appearance = signer.getSignatureAppearance();
            appearance
                    .setContact(subject.email().orElse(""))
                    .setSignatureCreator(subject.organizationName().orElse(""))
                    .setLocation(subject.country())
                    .setReuseAppearance(false)
                    .setPageNumber(1);
    
            signer.setFieldName(sigFieldName);
            ContainerForPrepareSignedDocument external = new ContainerForPrepareSignedDocument(filter, subFilter);
            signer.signExternalContainer(external, estimatedSize);
            byte[] preSignedBytes = os.toByteArray();
    
            ContainerReadyToSignedDocument extSigContainer = new ContainerReadyToSignedDocument(decodeSignature);
            PdfDocument docToSign = new PdfDocument(new PdfReader(new ByteArrayInputStream(preSignedBytes)));
            PdfSigner.signDeferred(docToSign, sigFieldName, result, extSigContainer);
            docToSign.close();
            return result.toByteArray();
        }
        catch (IOException e) {
            throw new InternalException("IO exception by insert signature to document:", e);
        }
        catch (GeneralSecurityException e) {
            throw new InternalException("General security by insert signature to document:", e);
        }
        catch (CAdESException e) {
            throw new InternalException("CAdESException by insert signature to document:", e);
        }
    }
    
    private List<String> getSignaturesFields(byte[] document)
            throws IOException {
        try (InputStream inputStream = new ByteArrayInputStream(document);
             PdfReader reader = new PdfReader(inputStream);
             PdfDocument pdfDocument = new PdfDocument(reader)) {
            SignatureUtil signUtil = new SignatureUtil(pdfDocument);
            return signUtil.getSignatureNames();
        }
    }
    
    static class ContainerForPrepareSignedDocument implements IExternalSignatureContainer {
        private final PdfName filter;
        private final PdfName subFilter;
    
        public ContainerForPrepareSignedDocument(PdfName filter,
                                                 PdfName subFilter) {
            this.filter = filter;
            this.subFilter = subFilter;
        }
    
        public byte[] sign(InputStream docBytes) {
            return new byte[0];
        }
    
        public void modifySigningDictionary(PdfDictionary signDic) {
            signDic.put(PdfName.Filter, filter);
            signDic.put(PdfName.SubFilter, subFilter);
        }
    }
    
    
    static class ContainerReadyToSignedDocument implements IExternalSignatureContainer {
        private byte[] cmsSignatureContents;
    
        public ContainerReadyToSignedDocument(byte[] cmsSignatureContents) {
            this.cmsSignatureContents = cmsSignatureContents;
        }
    
    
        public byte[] sign(InputStream docBytes) {
            return cmsSignatureContents;
        }
    
        public void modifySigningDictionary(PdfDictionary signDic) {
        }
    }
    
    public byte[]插入签名(byte[]文档,字符串签名){
    try(InputStream-InputStream=newbytearrayinputstream(文档);
    ByteArrayOutputStream os=新建ByteArrayOutputStream();
    ByteArrayOutputStream结果=新建ByteArrayOutputStream()){
    字节[]decodeSignature=Base64.decodesbase64(签名);
    CAdESSignature cades=新的CAdESSignature(decodeSignature,null,null);
    var certificate=cades.getCAdESSignerInfo(0.getSignerCertificate();
    var subject=new subject(certificate.getSubjectX500Principal().getEncoded());
    列表名称=GetSignatures字段(文档);
    String sigFieldName=String.format(“签名%s”,names.size()+1);
    PdfName filter=PdfName.Adobe\u PPKLite;
    PdfName subFilter=PdfName.ETSI_CAdES_;
    int estimatedSize=8192;
    PdfReader reader=新PdfReader(inputStream);
    StampingProperties StampingProperties=新的StampingProperties();
    如果(names.size()>1){
    stampingProperties.UseAmpendMode();
    }
    PdfSigner signer=新的PdfSigner(读卡器、操作系统、冲压属性);
    签名者设置认证级别(PdfSigner.CERTIFIED不允许更改);
    PdfSignatureAppearance外观=signer.getSignatureAppearance();
    外观
    .setContact(subject.email().orElse(“”)
    .setSignatureCreator(subject.organizationName().orElse(“”)
    .setLocation(subject.country())
    .SetReuseApearance(false)
    .设置页码(1);
    signer.setFieldName(sigFieldName);
    ContainerFormReparesignedDocument external=新的ContainerFormReparesignedDocument(过滤器、子过滤器);
    signer.signExternalContainer(外部,估计大小);
    byte[]preSignedBytes=os.toByteArray();
    ContainerReadyToSignedDocument extSigContainer=新的ContainerReadyToSignedDocument(decodeSignature);
    PdfDocument docToSign=新PdfDocument(新PDF阅读器(新ByteArrayInputStream(预签名字节));
    signDeferred(docToSign、sigFieldName、result、extSigContainer);
    docToSign.close();
    返回result.toByteArray();
    }
    捕获(IOE异常){
    抛出新的InternalException(“通过向文档插入签名引发IO异常:”,e);
    }
    捕获(一般安全性例外e){
    抛出新的InternalException(“通过在文档中插入签名的一般安全性:”,e);
    }
    渔获物(e){
    抛出新的InternalException(“CAdESException,通过在文档中插入签名:”,e);
    }
    }
    私有列表getSignaturesFields(字节[]文档)
    抛出IOException{
    try(InputStream-InputStream=newbytearrayinputstream(文档);
    PdfReader reader=新PdfReader(inputStream);
    PdfDocument PdfDocument=新PdfDocument(读卡器)){
    SignatureUtil signUtil=新的SignatureUtil(pdfDocument);
    返回signUtil.getSignatureNames();
    }
    }
    静态类ContainerForpRepresignedDocument实现IExternalSignatureContainer{
    专用最终PdfName过滤器;
    专用最终PdfName子筛选器;
    public ContainerFormReparesignedDocument(PdfName筛选器,
    PdfName子筛选器){
    this.filter=过滤器;
    this.subFilter=subFilter;
    }
    公共字节[]符号(InputStream docBytes){
    返回新字节[0];
    }
    公共无效修改签名字典(PdfDictionary signDic){
    signDic.put(PdfName.Filter,Filter);
    signDic.put(PdfName.SubFilter,SubFilter);
    }
    }
    静态类ContainerReadyToSignedDocument实现IExternalSignatureContainer{
    专用字节[]cmsSignatureContents;
    公共容器ReadyToSignedDocument(字节[]cmsSignatureContents){
    this.cmsSignatureContents=cmsSignatureContents;
    }
    公共字节[]符号(InputStream docBytes){
    返回cmsSignatureContents;
    }
    公共无效修改签名字典(PdfDictionary signDic){
    }
    }
    
    “我从文档的pdf中获取内容,然后计算散列”-您是否对原始pdf进行散列?或者你已经准备好签字了吗?签署PDF要求您首先通过将值设置为以前存在的或新的PDF AcroForm签名字段来准备原始PDF;此值包含一个占位符,稍后将在其中嵌入签名容器。详情请阅读。在这个准备好的PDF中,除了占位符,你必须散列所有内容。你的意思是,在任何情况下,你都需要在文件中为签名创建一个容器,并从字节数组中获取散列,比如这个例子:test calchashandoccreationthendeferredsigntest01严格地说,这不是一个例子,但是这些是一些单元测试,它们测试延迟签名的某些方面,但是是的,在开始散列之前,您必须以类似于某些测试中显示的方式准备PDF。我是否正确理解,在这种情况下,每次散列都是不同的。例如,我们取一个文件,在其中添加一个用于签名的容器,然后从/ByteRange计算哈希值,结果,我得到哈希值1,如果我第二次执行相同的操作,那么即使使用相同的算法,也会有一个不同的哈希值?通常是的,因为其中有创建/修改时间、签名时间和唯一文档ID等条目