我的编程空间,编程开发者的网络收藏夹
学习永远不晚

ava中怎么对PDF文件进行电子签章

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

ava中怎么对PDF文件进行电子签章

这篇文章将为大家详细讲解有关ava中怎么对PDF文件进行电子签章,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

    一、 概述

    印章是我国特有的历史文化产物,古代主要用作身份凭证和行驶职权的工具。它的起源是由于社会生活的实际需要。早在商周时代,印章就已经产生。如今的印章已成为一种独特的,融实用性和艺术性为一体的艺术瑰宝。传统的印章容易被坏人、小人私刻;从而新闻鲜有报道某某私刻公章,侵吞国家财产。随着计算机技术、加密技术及图像处理技术的发展,出现了电子签章。电子签章是电子签名的一种表现形式,利用图像处理技术、数字加密技术将电子签名操作转化为与纸质文件盖章操作相同的可视效果,同时利用电子签名技术保障电子信息的真实性和完整性以及签名人的不可否认性。

    电子签章与数字证书一样是身份验证的一种手段,泛指所有以电子形式存在,依附在电子文件并与其逻辑关联,可用以辨识电子文件签署者身份,保证文件的完整性,并表示签署者同意电子文件所陈述事实的内容。一般来说对电子签章的认定都是从技术角度而言的。主要是指通过特定的技术方案来鉴别当事人的身份及确保电子资料内容不被篡改的安全保障措施。电子签章常于发送安全电子邮件、访问安全站点、网上招标投标、网上签约、安全网上公文传送、公司合同、电子处方笺等。

    电子签章是一个很复杂的问题,大到有相关的电子签章系统;今天分享一下如何把电子签章应用到电子处方笺的PDF文件里。

    二、 技术选型

    目前主流处理PDF文件两个jar包分别是:

    • 开源组织Apache的PDFBox,官网https://pdfbox.apache.org/

    • 大名鼎鼎adobe公司的iText,官网https://itextpdf.com/tags/adobe,其中iText又分为iText5和iText7

    如何在PDFBox、iText5和iText7选出合适自己项目的技术呢?

    对比PDFBox、iText5和iText7这三者:

    1. PDFBox的功能相对较弱,iText5和iText7的功能非常强悍;

    2. iText5的资料网上相对较多,如果出现问题容易找到解决方案;PDFBox和iText7的网上资料相对较少,如果出现问题不易找到相关解决方案;

    3. 通过阅读PDFBox代码目前PDFBox还没提供自定义签章的相关接口;iText5和iText7提供了处理自定义签章的相关实现;

    4. PDFBox只能实现把签章图片加签到PDF文件;iText5和iText7除了可以把签章图片加签到PDF文件,还可以实现直接对签章进行绘制,把文件绘制到签章上。

    5. PDFBox和iText5/iText7使用的协议不一样。PDFBox使用的是APACHE LICENSE VERSION 2.0(https://www.apache.org/licenses/);iText5/iText7使用的是AGPL(https://itextpdf.com/agpl)。PDFBox免费使用,AGPL商用收费

    本分享JAVA对PDF文件进行电子签章需要实现的功能:

    1. 生成证书。与PDFBox、iText5和iText7技术无关

    2. 按模板输出PDF文件:PDFBox、iText5和iText7都可以完成,但是PDFBox会遇到中文乱码比较棘手的问题

    3. 在PDF文件中实现把签章图片加签到PDF文件:PDFBox、iText5和iText7都可以实现,没有很多的区别

    4. 在PDF文件中绘制签章:iText5和iText7都可以实现,PDFBox目前不支持

    5. 在PDF文件中生成高清签章:iText5和iText7都可以实现,PDFBox目前不支持

    6. 在PDF文件中进行多次签名::PDFBox、iText5和iText7都可以完成,没有区别

    通过相关技术分析和要实现的功能分析,采用iText5进行开发,唯一遗憾的是iText商用收费;但是这不是做技术需要关心的!!选用iText5的理由:

    • 使用iText5能实现全部的功能

    • 如何在开发中遇到相关问题,容易找到相应解决方案

    三、 生成一个图片签章

    1. 生成一个如下图的签章图片

    ava中怎么对PDF文件进行电子签章

    2. 相关代码

    import java.awt.Color;    import java.awt.Font;    import java.awt.FontMetrics;    import java.awt.Graphics2D;    import java.awt.RenderingHints;    import java.awt.image.BufferedImage;    import java.io.FileOutputStream;    import java.io.IOException;    import sun.font.FontDesignMetrics;     import com.sun.image.codec.jpeg.JPEGCodec;    import com.sun.image.codec.jpeg.JPEGEncodeParam;    import com.sun.image.codec.jpeg.JPEGImageEncoder;     public class SignImage {         public static boolean createSignTextImg(            String doctorName, //            String hospitalName, //            String date,             String jpgname) {        int width = 255;        int height = 100;        FileOutputStream out = null;        //背景色        Color bgcolor = Color.WHITE;        //字色        Color fontcolor = Color.RED;        Font doctorNameFont = new Font(null, Font.BOLD, 20);        Font othorTextFont = new Font(null, Font.BOLD, 18);        try { // 宽度 高度            BufferedImage bimage = new BufferedImage(width, height,                    BufferedImage.TYPE_INT_RGB);            Graphics2D g = bimage.createGraphics();            g.setColor(bgcolor); // 背景色            g.fillRect(0, 0, width, height); // 画一个矩形            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,                    RenderingHints.VALUE_ANTIALIAS_ON); // 去除锯齿(当设置的字体过大的时候,会出现锯齿)             g.setColor(Color.RED);            g.fillRect(0, 0, 8, height);            g.fillRect(0, 0, width, 8);            g.fillRect(0, height - 8, width, height);            g.fillRect(width - 8, 0, width, height);             g.setColor(fontcolor); // 字的颜色            g.setFont(doctorNameFont); // 字体字形字号            FontMetrics fm = FontDesignMetrics.getMetrics(doctorNameFont);            int font1_Hight = fm.getHeight();            int strWidth = fm.stringWidth(doctorName);            int y = 35;            int x = (width - strWidth) / 2;            g.drawString(doctorName, x, y); // 在指定坐标除添加文字             g.setFont(othorTextFont); // 字体字形字号             fm = FontDesignMetrics.getMetrics(othorTextFont);            int font2_Hight = fm.getHeight();            strWidth = fm.stringWidth(hospitalName);            x = (width - strWidth) / 2;            g.drawString(hospitalName, x, y + font1_Hight); // 在指定坐标除添加文字             strWidth = fm.stringWidth(date);            x = (width - strWidth) / 2;            g.drawString(date, x, y + font1_Hight + font2_Hight); // 在指定坐标除添加文字             g.dispose();            out = new FileOutputStream(jpgname); // 指定输出文件            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);            JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage);            param.setQuality(50f, true);            encoder.encode(bimage, param); // 存盘            out.flush();            return true;        } catch (Exception e) {            return false;        }finally{            if(out!=null){                try {                    out.close();                } catch (IOException e) {                }            }        }    }    public static void main(String[] args) {        createSignTextImg("华佗", "在线医院", "2018.01.01",   "sign.jpg");    }}

    四、 如何按模板生成PDF文件

    1. 制作PDF模板

    目前PDF模板工具别无他物,只能使用伟大的Adobe公司提供的Adobe Acrobatpro DC软件进行制作。如何使用该软件这里就不多说了,如果在使用中遇到什么可以另外咨询。

    2. 制作一个如下图的PDF模板,该模板是带有PDF的表单域的

    ava中怎么对PDF文件进行电子签章

    五、 如何生成PKCS12证书

    1. PKCS的简单介绍

    PKCS:The Public-Key Cryptography Standards (简称PKCS)是由美国RSA数据安全公司及其合作伙伴制定的一组公钥密码学标准,其中包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。

    到1999年底,PKCS已经公布了以下标准:

    • PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封[22]。

    • PKCS#3:定义Diffie-Hellman密钥交换协议[23]。

    • PKCS#5:描述一种利用从口令派生出来的安全密钥加密字符串的方法。使用MD2或MD5 从口令中派生密钥,并采用DES-CBC模式加密。主要用于加密从一个计算机传送到另一个计算机的私人密钥,不能用于加密消息[24]。

    • PKCS#6:描述了公钥证书的标准语法,主要描述X.509证书的扩展格式[25]。

    • PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息[26]。

    • PKCS#8:描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等[27]。

    • PKCS#9:定义一些用于PKCS#6证书扩展、PKCS#7数字签名和PKCS#8私钥加密信息的属性类型[28]。

    • PKCS#10:描述证书请求语法[29]。

    • PKCS#11:称为Cyptoki,定义了一套独立于技术的程序设计接口,用于智能卡和PCMCIA卡之类的加密设备[30]。

    • PKCS#12:描述个人信息交换语法标准。描述了将用户公钥、私钥、证书和其他相关信息打包的语法[31]。

    • PKCS#13:椭圆曲线密码体制标准[32]。

    • PKCS#14:伪随机数生成标准。

    • PKCS#15:密码令牌信息格式标准[33]。

    PKCS12也就是以上标准的PKCS#12,主要用来描述个人身份信息;本次分享中要进行签章操作的是医生和药师,他们就是一个个人主体,给他们分配一个PKCS12的证书,就等于给他们分配了一个用于盖章的印章。

    2. 使用JAVA生成一个PKCS12证书并进行存贮,相关分析见代码注解

    public class Extension {         private String oid;         private boolean critical;         private byte[] value;         public String getOid() {            return oid;        }         public byte[] getValue() {            return value;        }        public boolean isCritical() {            return critical;        }    }      import java.io.ByteArrayInputStream;    import java.io.ByteArrayOutputStream;    import java.io.File;    import java.io.FileOutputStream;    import java.io.IOException;    import java.math.BigInteger;    import java.security.KeyPair;    import java.security.KeyPairGenerator;    import java.security.KeyStore;    import java.security.NoSuchAlgorithmException;    import java.security.PrivateKey;    import java.security.PublicKey;    import java.security.SecureRandom;    import java.security.cert.Certificate;    import java.security.cert.CertificateFactory;    import java.security.cert.X509Certificate;    import java.text.SimpleDateFormat;    import java.util.Calendar;    import java.util.Date;    import java.util.HashMap;    import java.util.List;    import java.util.Map;    import java.util.Random;     import org.bouncycastle.asn1.ASN1ObjectIdentifier;    import org.bouncycastle.asn1.ASN1Primitive;    import org.bouncycastle.asn1.x500.X500Name;    import org.bouncycastle.asn1.x509.BasicConstraints;    import org.bouncycastle.asn1.x509.CRLDistPoint;    import org.bouncycastle.asn1.x509.DistributionPoint;    import org.bouncycastle.asn1.x509.DistributionPointName;    import org.bouncycastle.asn1.x509.GeneralName;    import org.bouncycastle.asn1.x509.GeneralNames;    import org.bouncycastle.asn1.x509.KeyUsage;    import org.bouncycastle.cert.X509CertificateHolder;    import org.bouncycastle.cert.X509v3CertificateBuilder;    import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;    import org.bouncycastle.jce.provider.BouncyCastleProvider;    import org.bouncycastle.operator.ContentSigner;    import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;     public class Pkcs {     private static KeyPair getKey() throws NoSuchAlgorithmException {        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA",                new BouncyCastleProvider());        generator.initialize(1024);        // 证书中的密钥 公钥和私钥        KeyPair keyPair = generator.generateKeyPair();        return keyPair;    }         public static Map<String, byte[]> createCert(String password,            String issuerStr, String subjectStr, String certificateCRL) {        Map<String, byte[]> result = new HashMap<String, byte[]>();        ByteArrayOutputStream out = null;        try {            // 生成JKS证书            // KeyStore keyStore = KeyStore.getInstance("JKS");            // 标志生成PKCS12证书            KeyStore keyStore = KeyStore.getInstance("PKCS12",                    new BouncyCastleProvider());            keyStore.load(null, null);            KeyPair keyPair = getKey();            // issuer与 subject相同的证书就是CA证书            Certificate cert = generateCertificateV3(issuerStr, subjectStr,                    keyPair, result, certificateCRL, null);            // cretkey随便写,标识别名            keyStore.setKeyEntry("cretkey", keyPair.getPrivate(),                    password.toCharArray(), new Certificate[] { cert });            out = new ByteArrayOutputStream();            cert.verify(keyPair.getPublic());            keyStore.store(out, password.toCharArray());            byte[] keyStoreData = out.toByteArray();            result.put("keyStoreData", keyStoreData);            return result;        } catch (Exception e) {            e.printStackTrace();        } finally {            if (out != null) {                try {                    out.close();                } catch (IOException e) {                }            }        }        return result;    }         public static Certificate generateCertificateV3(String issuerStr,            String subjectStr, KeyPair keyPair, Map<String, byte[]> result,            String certificateCRL, List<Extension> extensions) {        ByteArrayInputStream bout = null;        X509Certificate cert = null;        try {            PublicKey publicKey = keyPair.getPublic();            PrivateKey privateKey = keyPair.getPrivate();            Date notBefore = new Date();            Calendar rightNow = Calendar.getInstance();            rightNow.setTime(notBefore);            // 日期加1年            rightNow.add(Calendar.YEAR, 1);            Date notAfter = rightNow.getTime();            // 证书序列号            BigInteger serial = BigInteger.probablePrime(256, new Random());            X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(                    new X500Name(issuerStr), serial, notBefore, notAfter,                    new X500Name(subjectStr), publicKey);            JcaContentSignerBuilder jBuilder = new JcaContentSignerBuilder(                    "SHA1withRSA");            SecureRandom secureRandom = new SecureRandom();            jBuilder.setSecureRandom(secureRandom);            ContentSigner singer = jBuilder.setProvider(                    new BouncyCastleProvider()).build(privateKey);            // 分发点            ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier(                    "2.5.29.31");            GeneralName generalName = new GeneralName(                    GeneralName.uniformResourceIdentifier, certificateCRL);            GeneralNames seneralNames = new GeneralNames(generalName);            DistributionPointName distributionPoint = new DistributionPointName(                    seneralNames);            DistributionPoint[] points = new DistributionPoint[1];            points[0] = new DistributionPoint(distributionPoint, null, null);            CRLDistPoint cRLDistPoint = new CRLDistPoint(points);            builder.addExtension(cRLDistributionPoints, true, cRLDistPoint);            // 用途            ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier(                    "2.5.29.15");            // | KeyUsage.nonRepudiation | KeyUsage.keyCertSign            builder.addExtension(keyUsage, true, new KeyUsage(                    KeyUsage.digitalSignature | KeyUsage.keyEncipherment));            // 基本限制 X509Extension.java            ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier(                    "2.5.29.19");            builder.addExtension(basicConstraints, true, new BasicConstraints(                    true));            // privKey:使用自己的私钥进行签名,CA证书            if (extensions != null)                for (Extension ext : extensions) {                    builder.addExtension(                            new ASN1ObjectIdentifier(ext.getOid()),                            ext.isCritical(),                            ASN1Primitive.fromByteArray(ext.getValue()));                }            X509CertificateHolder holder = builder.build(singer);            CertificateFactory cf = CertificateFactory.getInstance("X.509");            bout = new ByteArrayInputStream(holder.toASN1Structure()                    .getEncoded());            cert = (X509Certificate) cf.generateCertificate(bout);            byte[] certBuf = holder.getEncoded();            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");            // 证书数据            result.put("certificateData", certBuf);            //公钥            result.put("publicKey", publicKey.getEncoded());            //私钥            result.put("privateKey", privateKey.getEncoded());            //证书有效开始时间            result.put("notBefore", format.format(notBefore).getBytes("utf-8"));            //证书有效结束时间            result.put("notAfter", format.format(notAfter).getBytes("utf-8"));        } catch (Exception e) {            e.printStackTrace();        } finally {            if (bout != null) {                try {                    bout.close();                } catch (IOException e) {                }            }        }        return cert;    }     public static void main(String[] args) throws Exception{        // CN: 名字与姓氏    OU : 组织单位名称        // O :组织名称  L : 城市或区域名称  E : 电子邮件        // ST: 州或省份名称  C: 单位的两字母国家代码         String issuerStr = "CN=在线医院,OU=gitbook研发部,O=gitbook有限公司,C=CN,E=gitbook@sina.com,L=北京,ST=北京";        String subjectStr = "CN=huangjinjin,OU=gitbook研发部,O=gitbook有限公司,C=CN,E=huangjinjin@sina.com,L=北京,ST=北京";        String certificateCRL  = "https://gitbook.cn";        Map<String, byte[]> result = createCert("123456", issuerStr, subjectStr, certificateCRL);         FileOutputStream outPutStream = new FileOutputStream("c:/keystore.p12"); // ca.jks        outPutStream.write(result.get("keyStoreData"));        outPutStream.close();        FileOutputStream fos = new FileOutputStream(new File("c:/keystore.cer"));        fos.write(result.get("certificateData"));        fos.flush();        fos.close();    }    }

    六、 如何生成一个高清晰的签章

    1. 由PDF模板生成一个PDF文件,见代码注解

    import java.io.FileOutputStream;    import java.io.IOException;    import java.io.OutputStream;    import java.util.ArrayList;    import java.util.HashMap;    import java.util.Iterator;    import java.util.List;    import java.util.Map;    import com.itextpdf.text.DocumentException;    import com.itextpdf.text.pdf.AcroFields;    import com.itextpdf.text.pdf.AcroFields.Item;    import com.itextpdf.text.pdf.BaseFont;    import com.itextpdf.text.pdf.PdfReader;    import com.itextpdf.text.pdf.PdfStamper;     public class PDFUtils {          private static void fillData(AcroFields fields, Map<String, String> data) throws IOException, DocumentException {        List<String> keys = new ArrayList<String>();        Map<String, Item> formFields = fields.getFields();        for (String key : data.keySet()) {            if(formFields.containsKey(key)){                String value = data.get(key);                fields.setField(key, value); // 为字段赋值,注意字段名称是区分大小写的                keys.add(key);            }        }        Iterator<String> itemsKey = formFields.keySet().iterator();        while(itemsKey.hasNext()){            String itemKey = itemsKey.next();            if(!keys.contains(itemKey)){                fields.setField(itemKey, " ");            }        }    }         public static String generatePDF(String templatePdfPath, String generatePdfPath, Map<String, String> data) {        OutputStream fos = null;        ByteArrayOutputStream bos = null;        try {            PdfReader reader = new PdfReader(templatePdfPath);            bos = new ByteArrayOutputStream();                        PdfStamper ps = new PdfStamper(reader, bos);                        BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);            ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();            fontList.add(bf);                        AcroFields fields = ps.getAcroFields();            fields.setSubstitutionFonts(fontList);            fillData(fields, data);                        ps.setFormFlattening(true);            ps.close();            fos = new FileOutputStream(generatePdfPath);            fos.write(bos.toByteArray());            fos.flush();            return generatePdfPath;        } catch (Exception e) {            e.printStackTrace();        } finally {            if (fos != null) {                try {                    fos.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if (bos != null) {                try {                    bos.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }        return null;    }     public static void main(String[] args) {        Map<String, String> data = new HashMap<String, String>();        //key为pdf模板的form表单的名字,value为需要填充的值        data.put("title", "在线医院");        data.put("case", "123456789");        data.put("date", "2018.12.07");        data.put("name", "gitbook");        data.put("sex", "男");        data.put("age", "29");        data.put("phone", "13711645814");        data.put("office", "内科");        data.put("cert", "身痒找打");        data.put("drug", "1、奥美拉唑肠溶胶囊             0.25g10粒×2板 ");        data.put("dose", "×2盒");        data.put("cons", "用法用量:口服 一日两次 一次2粒");        data.put("tips", "温馨提示");        data.put("desc", "尽量呆在通风较好的地方,保持空气流通,有利于病情康复。尽量呆在通风较好的地方");        generatePDF("C:\\Users\\zhilin\\Desktop\\chat\\tpl.pdf",                 "C:\\Users\\zhilin\\Desktop\\chat\\filled.pdf", data );    }    }

    ava中怎么对PDF文件进行电子签章

    2. 对PDF文件进行签章

    经过过上面的代码可以生成一个名为sign.jpg的签章图片,生成一个keystore.p12的证书文件,还有一个已经通过模板填充了表单的名为filled.pdf的pdf文件。下面就可通过以上材料生成一个签名的PDF文件。

    import java.io.File;    import java.io.FileInputStream;    import java.io.FileOutputStream;    import java.io.IOException;    import java.security.KeyStore;    import java.security.PrivateKey;    import java.security.Security;    import java.security.cert.Certificate;    import java.util.UUID;     import org.bouncycastle.jce.provider.BouncyCastleProvider;     import com.itextpdf.text.Image;    import com.itextpdf.text.Rectangle;    import com.itextpdf.text.pdf.PdfReader;    import com.itextpdf.text.pdf.PdfSignatureAppearance;    import com.itextpdf.text.pdf.PdfSignatureAppearance.RenderingMode;    import com.itextpdf.text.pdf.PdfStamper;    import com.itextpdf.text.pdf.security.BouncyCastleDigest;    import com.itextpdf.text.pdf.security.DigestAlgorithms;    import com.itextpdf.text.pdf.security.ExternalDigest;    import com.itextpdf.text.pdf.security.ExternalSignature;    import com.itextpdf.text.pdf.security.MakeSignature;    import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;    import com.itextpdf.text.pdf.security.PrivateKeySignature;      public class SignPdf {        public static byte[] sign(String password, String keyStorePath, String signPdfclass="lazy" data-src, String signImage,            float x, float y) {        File signPdfclass="lazy" data-srcFile = new File(signPdfclass="lazy" data-src);        PdfReader reader = null;        ByteArrayOutputStream signPDFData = null;        PdfStamper stp = null;        FileInputStream fos = null;        try {            BouncyCastleProvider provider = new BouncyCastleProvider();            Security.addProvider(provider);            KeyStore ks = KeyStore.getInstance("PKCS12", new BouncyCastleProvider());            fos = new FileInputStream(keyStorePath);            // 私钥密码 为Pkcs生成证书是的私钥密码 123456            ks.load(fos, password.toCharArray());             String alias = (String) ks.aliases().nextElement();            PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());            Certificate[] chain = ks.getCertificateChain(alias);            reader = new PdfReader(signPdfclass="lazy" data-src);            signPDFData = new ByteArrayOutputStream();            // 临时pdf文件            File temp = new File(signPdfclass="lazy" data-srcFile.getParent(), System.currentTimeMillis() + ".pdf");            stp = PdfStamper.createSignature(reader, signPDFData, '\0', temp, true);             stp.setFullCompression();            PdfSignatureAppearance sap = stp.getSignatureAppearance();            sap.setReason("数字签名,不可改变");            // 使用png格式透明图片            Image image = Image.getInstance(signImage);            sap.setImageScale(0);            sap.setSignatureGraphic(image);            sap.setRenderingMode(RenderingMode.GRAPHIC);            // 是对应x轴和y轴坐标            sap.setVisibleSignature(new Rectangle(x, y, x + 185, y + 68), 1,                    UUID.randomUUID().toString().replaceAll("-", ""));            stp.getWriter().setCompressionLevel(5);            ExternalDigest digest = new BouncyCastleDigest();            ExternalSignature signature = new PrivateKeySignature(key, DigestAlgorithms.SHA512, provider.getName());            MakeSignature.signDetached(sap, digest, signature, chain, null, null, null, 0, CryptoStandard.CADES);            stp.close();            reader.close();            return signPDFData.toByteArray();        } catch (Exception e) {            e.printStackTrace();        } finally {             if (signPDFData != null) {                try {                    signPDFData.close();                } catch (IOException e) {                }            }             if (fos != null) {                try {                    fos.close();                } catch (IOException e) {                }            }        }        return null;    }     public static void main(String[] args) throws Exception {        byte[] fileData = sign("123456", "C:\\Users\\zhilin\\Desktop\\chat\\keystore.p12", //                "C:\\Users\\zhilin\\Desktop\\chat\\filled.pdf",//                "C:\\Users\\zhilin\\Desktop\\chat\\sign.jpg", 100, 290);        FileOutputStream f = new FileOutputStream(new File("C:\\Users\\zhilin\\Desktop\\chat\\signed.pdf"));        f.write(fileData);        f.close();    }    }

    ava中怎么对PDF文件进行电子签章

    3. 高清签章

    高清签章是通过iText的绘制功能来完成。主要直接在PDF文件中绘制签章,代码实现如下:

    import java.io.File;    import java.io.FileInputStream;    import java.io.FileOutputStream;    import java.io.IOException;    import java.security.KeyStore;    import java.security.PrivateKey;    import java.security.Security;    import java.security.cert.Certificate;    import org.bouncycastle.jce.provider.BouncyCastleProvider;     import com.itextpdf.awt.AsianFontMapper;    import com.itextpdf.text.BaseColor;    import com.itextpdf.text.Element;    import com.itextpdf.text.Font;    import com.itextpdf.text.Paragraph;    import com.itextpdf.text.Rectangle;    import com.itextpdf.text.pdf.BaseFont;    import com.itextpdf.text.pdf.ColumnText;    import com.itextpdf.text.pdf.PdfReader;    import com.itextpdf.text.pdf.PdfSignatureAppearance;    import com.itextpdf.text.pdf.PdfStamper;    import com.itextpdf.text.pdf.PdfStream;    import com.itextpdf.text.pdf.PdfTemplate;    import com.itextpdf.text.pdf.security.BouncyCastleDigest;    import com.itextpdf.text.pdf.security.DigestAlgorithms;    import com.itextpdf.text.pdf.security.ExternalDigest;    import com.itextpdf.text.pdf.security.ExternalSignature;    import com.itextpdf.text.pdf.security.MakeSignature;    import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;    import com.itextpdf.text.pdf.security.PrivateKeySignature;      public class SignHighPdf {         public static byte[] sign(String password, String keyStorePath, String signPdfclass="lazy" data-src,             float x, float y,            String signText) {        File signPdfclass="lazy" data-srcFile = new File(signPdfclass="lazy" data-src);        PdfReader reader = null;        ByteArrayOutputStream signPDFData = null;        PdfStamper stp = null;        FileInputStream fos = null;        try {            BouncyCastleProvider provider = new BouncyCastleProvider();            Security.addProvider(provider);            KeyStore ks = KeyStore.getInstance("PKCS12", new BouncyCastleProvider());            fos = new FileInputStream(keyStorePath);            ks.load(fos, password.toCharArray()); // 私钥密码            String alias = (String) ks.aliases().nextElement();            PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());            Certificate[] chain = ks.getCertificateChain(alias);            reader = new PdfReader(signPdfclass="lazy" data-src);            signPDFData = new ByteArrayOutputStream();            // 临时pdf文件            File temp = new File(signPdfclass="lazy" data-srcFile.getParent(), System.currentTimeMillis() + ".pdf");            stp = PdfStamper.createSignature(reader, signPDFData, '\0', temp, true);            PdfSignatureAppearance sap = stp.getSignatureAppearance();            sap.setReason("数字签名,不可改变");            // 是对应x轴和y轴坐标            sap.setVisibleSignature(new Rectangle(x, y, x + 150, y + 65), 1,                    "sr"+String.valueOf(System.nanoTime()));            /layer 0 Creating the appearance for layer 0            PdfTemplate n0 = sap.getLayer(0);            n0.reset();            float lx = n0.getBoundingBox().getLeft();            float by = n0.getBoundingBox().getBottom();            float width = n0.getBoundingBox().getWidth();            float height = n0.getBoundingBox().getHeight();            n0.setRGBColorFill(255, 0, 0);            n0.rectangle(lx, by, 5, height);            n0.rectangle(lx, by, width, 5);            n0.rectangle(lx, by+height-5, width, 5);            n0.rectangle(lx+width-5, by, 5, height);            n0.fill();            ///layer 2            PdfTemplate n2 = sap.getLayer(2);            n2.setCharacterSpacing(0.0f);            ColumnText ct = new ColumnText(n2);            ct.setSimpleColumn(n2.getBoundingBox());            n2.setRGBColorFill(255, 0, 0);            //做一个占位的动作            Paragraph p1 = new Paragraph(" ");            BaseFont bf = BaseFont.createFont(AsianFontMapper.ChineseSimplifiedFont, AsianFontMapper.ChineseSimplifiedEncoding_H,                     BaseFont.NOT_EMBEDDED);            Font font1 = new Font(bf, 5, Font.BOLD, BaseColor.RED);            Font font2 = new Font(bf, 13, Font.BOLD, BaseColor.RED);            p1.setFont(font1);            ct.addElement(p1);            Paragraph p = new Paragraph(signText);            p.setAlignment(Element.ALIGN_CENTER);            p.setFont(font2);            ct.addElement(p);            ct.go();            stp.getWriter().setCompressionLevel(PdfStream.BEST_COMPRESSION);            ExternalDigest digest = new BouncyCastleDigest();            ExternalSignature signature = new PrivateKeySignature(key, DigestAlgorithms.SHA512, provider.getName());            MakeSignature.signDetached(sap, digest, signature, chain, null, null, null, 0, CryptoStandard.CADES);            stp.close();            reader.close();            return signPDFData.toByteArray();        } catch (Exception e) {            e.printStackTrace();        } finally {            if (signPDFData != null) {                try {                    signPDFData.close();                } catch (IOException e) {                }            }            if (fos != null) {                try {                    fos.close();                } catch (IOException e) {                }            }        }        return null;    }     public static void main(String[] args) throws Exception {        //对已经签章的signed.pdf文件再次签章,这次是高清签章        byte[] fileData = sign("123456", "C:\\Users\\zhilin\\Desktop\\chat\\keystore.p12",//                "C:\\Users\\zhilin\\Desktop\\chat\\signed.pdf", 350, 290, "华佗\n2017-12-20");        FileOutputStream f = new FileOutputStream(new File("C:\\Users\\zhilin\\Desktop\\chat\\signed2.pdf"));        f.write(fileData);        f.close();    }     }

    可以分析下下面这两个签章的区别,发现左边的签章很模糊,右边的特别清晰。

    ava中怎么对PDF文件进行电子签章

    七、 如何进行多次PDF签名

    生成多个签章重点代码,已在SignPdf.java类进行标注说明;如果想进行多次签名,就只需对已经进行过签名的PDF文件再次调用sign方法进行再次签名即可(第六点有张图片就有两个签章,这就是多次签名的结果)。

    PdfStamper.createSignature(reader, signPDFData, '\0', temp, true);

    关于ava中怎么对PDF文件进行电子签章就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    ava中怎么对PDF文件进行电子签章

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    ava中怎么对PDF文件进行电子签章

    这篇文章将为大家详细讲解有关ava中怎么对PDF文件进行电子签章,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、 概述印章是我国特有的历史文化产物,古代主要用作身份凭证和行驶职权的工具。它
    2023-06-20

    Android应用中怎么对本地pdf文件进行加载

    这篇文章给大家介绍Android应用中怎么对本地pdf文件进行加载,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。大部分app打开pdf文件是通过intent调起手机中能打开pdf文件的工具,来查看pdf文件,如果需求是
    2023-05-31

    PHP中怎么对文章列表进行操作

    本篇文章给大家分享的是有关PHP中怎么对文章列表进行操作,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。PHP操作文章列表实现代码:< ?php $title = "http:
    2023-06-17

    VB.NET中怎么对文件进行合并

    本篇文章给大家分享的是有关VB.NET中怎么对文件进行合并,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。VB.NET文件合并代码实现示例:Private Sub MergeFi
    2023-06-17

    Python中怎么对文件进行操作

    Python中怎么对文件进行操作,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。编码方式编码方式的历史大致为ASCII ->gb2312->unicode->utf-8,期间具体
    2023-06-16

    VBScript 中怎么对文件进行操作

    这期内容当中小编将会给大家带来有关VBScript 中怎么对文件进行操作,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。创建文本文件 复制代码 代码如下:Set objFSO = CreateObject(
    2023-06-08

    Python中怎么对文件进行处理

    本篇文章给大家分享的是有关Python中怎么对文件进行处理,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。建议一:使用 pathlib 模块如果你需要在 Python 里进行文件
    2023-06-15

    VB.NET中怎么对二进制文件进行操作

    今天就跟大家聊聊有关VB.NET中怎么对二进制文件进行操作,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。VB.NET二进制文件操作主要应用的方法和函数有:Open,Close,Get
    2023-06-17

    Java 7中怎么对文件进行操作

    这篇文章将为大家详细讲解有关Java 7中怎么对文件进行操作,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。创建和删除文件下面的代码片段向你展示的是用 Files.createFile(Pat
    2023-06-17

    Laravel中怎么对大文件进行加密

    小编给大家分享一下Laravel中怎么对大文件进行加密,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!我已经搜索过用于解决此问题的软件包或解决方案,并遇到了这个 Stack Overflow 回答和这个 PHP 解决方案,该
    2023-06-15

    Golang:如何对电子邮件中的主题标头和正文进行 UTF8 编码?

    积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《Golang:如何对电子邮件中的主题标头和正文进行 UTF8 编码?》,就带
    Golang:如何对电子邮件中的主题标头和正文进行 UTF8 编码?
    2024-04-04

    vbs中怎么对文本文件内容进行排序

    vbs中怎么对文本文件内容进行排序,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。问:您好,脚本专家!我有一个包含计算机名称列表的文本文件。如何按照字母顺序对该文件进行排序?--
    2023-06-08

    linux怎么对文件中的数据进行排序

    在Linux中,可以使用`sort`命令对文件中的数据进行排序。`sort`命令的基本语法如下:```sort [OPTION]... [FILE]...```其中,`OPTION`是可选的排序选项,`FILE`是要排序的文件名。以下是一些
    2023-09-11

    C#中怎么对文本文件进行添加文本操作

    本篇文章给大家分享的是有关C#中怎么对文本文件进行添加文本操作,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。using System; using System.IO;
    2023-06-17

    Linux中怎么对文件进行批量重命名

    Linux中怎么对文件进行批量重命名,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。当你想要重命名多个文件的时候,rename 工具或许是最简单、最安全和最强大的
    2023-06-13

    Python中怎么对docx文件进行读写操作

    这期内容当中小编将会给大家带来有关Python中怎么对docx文件进行读写操作,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。演示文本为了方便理解,我们以 python-docx.docx 文件为例,演示如
    2023-06-16

    Android应用中怎么对SDCARD文件进行遍历

    今天就跟大家聊聊有关Android应用中怎么对SDCARD文件进行遍历,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Android 遍历SDCARD的文件夹并显示目录信息privat
    2023-05-31

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录