精华内容
下载资源
问答
  • Java实现数字签名

    千次阅读 2021-02-13 00:53:45
    一 数字签名算法带有秘钥(公钥,私钥)的消息摘要算法验证数据完整性,认证数据来源,抗否认OSI参考模型私钥签名,公钥验证RSA,DSA,ECDSA二 数字签名算法RSA经典算法MD,SHA两类例子:jdkRSA 算法1 packagecom.dzj.rsa;...

    一 数字签名算法

    带有秘钥(公钥,私钥)的消息摘要算法

    验证数据完整性,认证数据来源,抗否认

    OSI参考模型

    私钥签名,公钥验证

    RSA,DSA,ECDSA

    二 数字签名算法RSA

    经典算法

    MD,SHA两类

    例子:jdkRSA 算法

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    1 packagecom.dzj.rsa;2

    3 importjava.security.KeyFactory;4 importjava.security.KeyPair;5 importjava.security.KeyPairGenerator;6 importjava.security.PrivateKey;7 importjava.security.PublicKey;8 importjava.security.Signature;9 importjava.security.interfaces.RSAPrivateKey;10 importjava.security.interfaces.RSAPublicKey;11 importjava.security.spec.PKCS8EncodedKeySpec;12 importjava.security.spec.X509EncodedKeySpec;13

    14 importorg.apache.commons.codec.binary.Hex;15

    16 public classRSA {17 private static String src = "imooc security rsa";18

    19 public static voidmain(String[] args) {20 jdkRSA();21 }22

    23 public static voidjdkRSA() {24 try{25 //1 初始化密钥

    26 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");27 keyPairGenerator.initialize(512);28 KeyPair keyPair =keyPairGenerator.generateKeyPair();29

    30 RSAPublicKey rsaPublicKey =(RSAPublicKey) keyPair.getPublic();31 RSAPrivateKey rsaPrivateKey =(RSAPrivateKey) keyPair.getPrivate();32

    33 //2 私钥加密、公钥解密——加密34 //用私钥进行签名

    35 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = newPKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());36

    37 KeyFactory keyFactory = KeyFactory.getInstance("RSA");38 //执行key的转化

    39 PrivateKey privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec);40

    41 //声明一个签名对象 使用JDK实现

    42 Signature signature = Signature.getInstance("MD5withRSA");43 signature.initSign(privateKey);44 signature.update(src.getBytes());45 byte[] sign =signature.sign();46 System.out.println("私钥加密、公钥解密——加密:" +Hex.encodeHexString(sign));47

    48 //3私钥加密、公钥解密——解密

    49 X509EncodedKeySpec x509EncodedKeySpec = newX509EncodedKeySpec(rsaPublicKey.getEncoded());50 keyFactory = KeyFactory.getInstance("RSA");51 PublicKey publicKey =keyFactory.generatePublic(x509EncodedKeySpec);52 //创建签名对象

    53 signature = Signature.getInstance("MD5withRSA");54 signature.initVerify(publicKey);55 signature.update(src.getBytes());56 boolean verify =signature.verify(sign);57 System.out.println("私钥加密、公钥解密——解密:" +verify);58

    59 } catch(Exception e) {60 //TODO Auto-generated catch block

    61 e.printStackTrace();62 }63

    64 }65

    66 }

    View Code

    数字签名算法----过程

    056916a6b13b128123de8ef9995e2423.png

    三 数字签名算法DSA

    DSS(Digital Signature Standard)数字签名标准

    DSA(Digital Signature Algorithm)数字签名算法

    DSA仅包含数字签名,没有办法进行加密通讯

    RSA即包括加解密,又包括数字签名的算法

    例子

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    1 packagecom.dzj.dsa;2

    3 importjava.security.KeyFactory;4 importjava.security.KeyPair;5 importjava.security.KeyPairGenerator;6 importjava.security.PrivateKey;7 importjava.security.PublicKey;8 importjava.security.Signature;9 importjava.security.interfaces.DSAPrivateKey;10 importjava.security.interfaces.DSAPublicKey;11 importjava.security.spec.PKCS8EncodedKeySpec;12 importjava.security.spec.X509EncodedKeySpec;13

    14 importorg.apache.commons.codec.binary.Hex;15

    16 public classDSA {17

    18 private static String src = "imooc security dsa";19

    20 public static voidmain(String[] args) {21 jdkDSA();22 }23

    24 public static voidjdkDSA() {25 try{26 //1.初始化密钥

    27 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");28 keyPairGenerator.initialize(512);29 KeyPair keyPair =keyPairGenerator.generateKeyPair();30 DSAPublicKey dsaPublicKey =(DSAPublicKey) keyPair.getPublic();31 DSAPrivateKey dsaPrivateKey =(DSAPrivateKey) keyPair.getPrivate();32

    33 //2.执行签名 私钥进行签名

    34 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = newPKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());35 KeyFactory keyFactory = KeyFactory.getInstance("DSA");36 PrivateKey privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec);37 Signature signature = Signature.getInstance("SHA1withDSA");38 signature.initSign(privateKey);39 signature.update(src.getBytes());40 byte[] result =signature.sign();41 System.out.println("jdk dsa sign : " +Hex.encodeHexString(result));42

    43 //3.验证签名

    44 X509EncodedKeySpec x509EncodedKeySpec = newX509EncodedKeySpec(dsaPublicKey.getEncoded());45 keyFactory = KeyFactory.getInstance("DSA");46 PublicKey publicKey =keyFactory.generatePublic(x509EncodedKeySpec);47 signature = Signature.getInstance("SHA1withDSA");48 signature.initVerify(publicKey);49 signature.update(src.getBytes());50 boolean bool =signature.verify(result);51 System.out.println("jdk dsa verify : " +bool);52 } catch(Exception e) {53 e.printStackTrace();54 }55 }56

    57 }

    View Code

    四 数字签名算法ECDSA

    微软

    Ellipticc Curve Digital Signature Algorithm,椭圆曲线数字签名算法

    速度快,强度高,签名短

    例子:

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    1 packagecom.dzj.ecdsa;2

    3 importjava.security.KeyFactory;4 importjava.security.KeyPair;5 importjava.security.KeyPairGenerator;6 importjava.security.PrivateKey;7 importjava.security.PublicKey;8 importjava.security.Signature;9 importjava.security.interfaces.ECPrivateKey;10 importjava.security.interfaces.ECPublicKey;11 importjava.security.spec.PKCS8EncodedKeySpec;12 importjava.security.spec.X509EncodedKeySpec;13

    14 importorg.apache.commons.codec.binary.Hex;15

    16 public classECDSA {17 private static String src = "imooc security ecdsa";18

    19 public static voidmain(String[] args) {20

    21 jdkECDSA();22

    23 }24

    25 public static voidjdkECDSA() {26 try{27 //1 初始化密钥

    28 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");29 keyPairGenerator.initialize(256);30 KeyPair keyPair =keyPairGenerator.generateKeyPair();31 ECPublicKey ecPublicKey =(ECPublicKey) keyPair.getPublic();32 ECPrivateKey ecPrivateKey =(ECPrivateKey) keyPair.getPrivate();33

    34 //2 执行签名

    35 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = newPKCS8EncodedKeySpec(ecPrivateKey.getEncoded());36 KeyFactory keyFactory = KeyFactory.getInstance("EC");37 PrivateKey privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec);38 Signature signature = Signature.getInstance("SHA1withECDSA");39 signature.initSign(privateKey);40 signature.update(src.getBytes());41 byte[] sign =signature.sign();42 System.out.println("jdk ecdsa sign:" +Hex.encodeHexString(sign));43

    44 //3验证

    45 X509EncodedKeySpec x509EncodedKeySpec = newX509EncodedKeySpec(ecPublicKey.getEncoded());46 keyFactory = KeyFactory.getInstance("EC");47 PublicKey publicKey =keyFactory.generatePublic(x509EncodedKeySpec);48 signature = Signature.getInstance("SHA1withECDSA");49 signature.initVerify(publicKey);50 signature.update(src.getBytes());51 boolean verify =signature.verify(sign);52 System.out.println("jdk ecdsa verify:" +verify);53 } catch(Exception e) {54 //TODO Auto-generated catch block

    55 e.printStackTrace();56 }57

    58 }59

    60 }

    View Code

    展开全文
  • java生成电子签章

    2018-11-29 16:41:11
    通过java代码先生成html,然后再将html转换成所需要的pdf文件,并加盖印章。
  • h5实现电子签名

    2021-03-22 18:29:42
    } java 后台实现: @RequestMapping("/upload") @ResponseBody // imgStr就是前台发送的data[1] public String upload(HttpServletRequest request){ try{ String imgStr=request.getParameter("imgStr");...

    前端需要引入:jSignature.min.js ,jquery-1.9.1.min.js

    前端 部分写法:

    body内加

    Js :

    $(document).ready(function() {

    var arguments = {

    width: '100%',

    height: '40%',

    color:'#000',

    "decor-color": "transparent",//去除默认画布上那条横线

    lineWidth: '3'

    };

    $("#signature").jSignature(arguments);

    });

    //重写

    function btnCleanUp(){

    $("#signature").jSignature("clear");

    $("#img").attr("src", "");

    }

    //保存为图片

    function btnGenerateImg() {

    if( $("#signature").jSignature('getData', 'native').length === 0) {

    alert("请签名后再保存图片!");

    return;

    }

    var sig = $("#signature").jSignature('getData');

    $("#img").attr("src", sig);

    }

    //上传到服务器

    function btnUpload(){

    if( $("#signature").jSignature('getData', 'native').length === 0) {

    alert("请签名后再提交!");

    return;

    }

    var datapair = $("#signature").jSignature("getData", "image");

    $.ajax({

    url:'https://xxxx/upload',

    data:{"imgStr":datapair[1]},

    type:'POST',

    success:function (data){

    alert(data);

    },

    error:function (data){}

    });

    }

    java 后台实现:

    @RequestMapping("/upload")

    @ResponseBody // imgStr就是前台发送的data[1]

    public String upload(HttpServletRequest request){

    try{

    String imgStr=request.getParameter("imgStr");

    if(StringUtils.isBlank(imgStr)){

    return new RespBody(RespBody.Status.ERROR, "未找到需要保存的图片内容");

    }

    // 文件名称

    String s = PKGenerator.generateId();

    String fileName = s + ".png";

    // 获取路径

    String ctxPath = "D:autograph/";

    // 创建文件

    File dirPath = new File(ctxPath);

    if (!dirPath.exists()) {

    dirPath.mkdirs();

    }

    //Base64解码,生成.png图片

    BASE64Decoder decoder = new BASE64Decoder();

    byte[] decoderBytes = decoder.decodeBuffer(imgStr);

    FileOutputStream out = new FileOutputStream(new File(ctxPath+fileName));

    out.write(decoderBytes);

    out.close();

    return fileName; // 返回保存后的文件名称

    } catch (Exception e){

    logger.error("上传保存图片时报错:{}",e);

    return "上传保存图片失败。";

    }

    }

    效果:

    展开全文
  • java实现电子合同签名

    千次阅读 2021-03-04 10:15:53
    但debug日志会提示找不到docx4j配置文件在src下创建docx4j.properties配置文件,maven项目请放在resources文件夹下```java# Page size: use a value from org.docx4j....

    1.引入docx4j

    使用maven仓库引入jar包

    ```java

    org.docx4j

    docx4j

    6.1.2

    ```

    2.docx4j配置

    可以不添加配置文件,但debug日志会提示找不到docx4j配置文件

    在src下创建docx4j.properties配置文件,maven项目请放在resources文件夹下

    ```java

    # Page size: use a value from org.docx4j.model.structure.PageSizePaper enum

    # eg A4, LETTER

    docx4j.PageSize=LETTER

    # Page size: use a value from org.docx4j.model.structure.MarginsWellKnown enum

    docx4j.PageMargins=NORMAL

    docx4j.PageOrientationLandscape=false

    # Page size: use a value from org.pptx4j.model.SlideSizesWellKnown enum

    # eg A4, LETTER

    pptx4j.PageSize=LETTER

    pptx4j.PageOrientationLandscape=false

    # These will be injected into docProps/app.xml

    # if App.Write=true

    docx4j.App.write=true

    docx4j.Application=docx4j

    docx4j.AppVersion=6.1.2

    # of the form XX.YYYY where X and Y represent numerical values

    # These will be injected into docProps/core.xml

    docx4j.dc.write=true

    docx4j.dc.creator.value=docx4j

    docx4j.dc.lastModifiedBy.value=docx4j

    #

    #docx4j.McPreprocessor=true

    # If you haven't configured log4j yourself

    # docx4j will autoconfigure it. Set this to true to disable that

    docx4j.Log4j.Configurator.disabled=false

    ```

    3.构建WordProcessingMlPackage对象

    docx格式文档可以理解为一个压缩包,若将其解压可看到一个类似前端的工程项目,其中document.xml用于全文的配置,详细解说请自行查阅资料

    WordprocessingMLPackage是操作word文档包对象;

    创建新的word文档

    ```java

    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

    /**

    * 构建新word文件

    */

    public static WordprocessingMLPackage build() throws Exception{

    return WordprocessingMLPackage.createPackage();

    }

    加载存在的word文档

    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

    /**

    * 读取存在的word文件

    * @param wordFilePath word文件路径

    */

    public static WordprocessingMLPackage load(String wordFilePath) throws Exception{

    return WordprocessingMLPackage.load(new File(wordFilePath));

    }

    ```

    4.获取书签

    书签:CTBookmark对象

    ```java

    import org.docx4j.TraversalUtil;

    import org.docx4j.dml.wordprocessingDrawing.Inline;

    import org.docx4j.finders.RangeFinder;

    import org.docx4j.jaxb.Context;

    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

    import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;

    import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;

    import org.docx4j.org.apache.poi.util.IOUtils;

    import org.docx4j.wml.*;

    public static void main(String[] args) throws Exception {

    String wordFilePath = "";

    WordprocessingMLPackage wordMLPackage = load(wordFilePath);

    // 提取正文

    MainDocumentPart main = wordMLPackage.getMainDocumentPart();

    Document doc = main.getContents();

    Body body = doc.getBody();

    // 获取段落

    List paragraphs = body.getContent();

    // 提取书签并获取书签的游标

    RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");

    new TraversalUtil(paragraphs, rt);

    // 遍历书签

    for (CTBookmark bm : rt.getStarts()) {

    System.out.println("name:"+bm.getName());

    }

    }

    ```

    5.在书签位置加入图片

    ```java

    import org.docx4j.TraversalUtil;

    import org.docx4j.dml.wordprocessingDrawing.Inline;

    import org.docx4j.finders.RangeFinder;

    import org.docx4j.jaxb.Context;

    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

    import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;

    import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;

    import org.docx4j.org.apache.poi.util.IOUtils;

    import org.docx4j.wml.*;

    public static void addImage(WordprocessingMLPackage wPackage,CTBookmark bm) throws Exception{

    P p = (P) (bm.getParent());

    ObjectFactory factory = Context.getWmlObjectFactory();

    R run = factory.createR();

    // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片

    // byte[] bytes = IOUtils.toByteArray(new FileInputStream("图片路径"));

    byte[] bytes = getFileBytes("图片路径");

    // 开始创建一个行内图片

    BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);

    // 最后一个是限制图片的宽度,缩放的依据

    Inline inline = imagePart.createImageInline(null, null, 0, 1, false, 0);

    // 构建绘图

    Drawing drawing = factory.createDrawing();

    // 加入图片段落

    drawing.getAnchorOrInline().add(inline);

    run.getContent().add(drawing);

    // 清理书签所在数据

    // p.getContent().clear();

    // 加入图片信息

    p.getContent().add(run);

    }

    public static byte[] getFileBytes(String filePath) throws Exception{

    File file = new File(filePath);

    if(!file.exists()){

    throw new Exception("文件不存在!");

    }

    byte[] data = null;

    try(FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream baos = new ByteArrayOutputStream()){

    int len;

    byte[] buffer = new byte[1024];

    while ((len = fis.read(buffer)) != -1) {

    baos.write(buffer, 0, len);

    }

    data = baos.toByteArray();

    }

    return data;

    }

    ```

    6.保存文件

    必须调用保存,否则更改无效

    // 保存

    // 方式一

    ```java

    wordMLPackage.save(new File(wordFilePath));

    ```

    // 方式二

    ```java

    Docx4J.save(wordMLPackage, new File(wordFilePath));

    ```

    7.完整代码

    ```java

    import org.docx4j.TraversalUtil;

    import org.docx4j.dml.wordprocessingDrawing.Inline;

    import org.docx4j.finders.RangeFinder;

    import org.docx4j.jaxb.Context;

    import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

    import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;

    import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;

    import org.docx4j.org.apache.poi.util.IOUtils;

    import org.docx4j.wml.*;

    import javax.xml.bind.JAXBElement;

    import java.io.ByteArrayOutputStream;

    import java.io.File;

    import java.io.FileInputStream;

    import java.util.ArrayList;

    import java.util.HashMap;

    import java.util.List;

    import java.util.Map;

    public class WordTest {

    public static void main(String[] args) throws Exception {

    String wordFilePath = "word文档路径";

    WordprocessingMLPackage wordMLPackage = load(wordFilePath);

    // 提取正文

    MainDocumentPart main = wordMLPackage.getMainDocumentPart();

    Document doc = main.getContents();

    Body body = doc.getBody();

    // 获取段落

    List paragraphs = body.getContent();

    // 提取书签并获取书签的游标

    RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");

    new TraversalUtil(paragraphs, rt);

    // 遍历书签

    for (CTBookmark bm : rt.getStarts()) {

    System.out.println("name:"+bm.getName());

    // 替换image

    if ("sign".equals(bm.getName())){

    addImage(wordMLPackage, bm);

    break;

    }

    }

    save(wordMLPackage,wordFilePath);

    }

    public static void addImage(WordprocessingMLPackage wPackage,CTBookmark bm) throws Exception{

    P p = (P) (bm.getParent());

    ObjectFactory factory = Context.getWmlObjectFactory();

    R run = factory.createR();

    // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片

    // byte[] bytes = IOUtils.toByteArray(new FileInputStream("图片文件路径"));

    byte[] bytes = getFileBytes("图片文件路径");

    // 开始创建一个行内图片

    BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);

    // 最后一个是限制图片的宽度,缩放的依据

    Inline inline = imagePart.createImageInline(null, null, 0, 1, false, 0);

    // 构建绘图

    Drawing drawing = factory.createDrawing();

    // 加入图片段落

    drawing.getAnchorOrInline().add(inline);

    run.getContent().add(drawing);

    // 清理书签所在数据

    // p.getContent().clear();

    // 加入图片信息

    p.getContent().add(run);

    }

    /**

    * 构建文件

    */

    public static WordprocessingMLPackage build() throws Exception{

    return WordprocessingMLPackage.createPackage();

    }

    /**

    * 读取存在的word文件

    * @param wordFilePath word文件路径

    */

    public static WordprocessingMLPackage load(String wordFilePath) throws Exception{

    return WordprocessingMLPackage.load(new File(wordFilePath));

    }

    /**

    * 保存

    * @param wordMLPackage word

    */

    public static void save(WordprocessingMLPackage wordMLPackage,String wordFilePath) throws Exception{

    wordMLPackage.save(new File(wordFilePath));

    }

    public static byte[] getFileBytes(String filePath) throws Exception{

    File file = new File(filePath);

    if(!file.exists()){

    throw new Exception("文件不存在!");

    }

    byte[] data = null;

    try(FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream baos = new ByteArrayOutputStream()){

    int len;

    byte[] buffer = new byte[1024];

    while ((len = fis.read(buffer)) != -1) {

    baos.write(buffer, 0, len);

    }

    data = baos.toByteArray();

    }

    return data;

    }

    }

    ```

    展开全文
  • 一、需求描述 实现合同模板自动生成合同,再添加电子签名。如图:使用html的合

    一、需求描述
    实现合同模板自动生成合同,再添加电子签名。如图:
    在这里插入图片描述
    在这里插入图片描述
    二、实现步骤
    使用java开源itext库对pdf进行操作,主要分为:
    1 html模板+model数据,通过freemarker进行渲染,生成pdf1。
    2 查找指定电子签名的位置,然后再在指定位置插入签名图片,生成最终pdf。
    备注:模板使用的是html形式,电子签名格式使用的是Base64格式。

    1. 准备html合同模板
      合同模板,在公众中获取。
    2. 添加java后端依赖
      完整的依赖包,点击蓝字,在公众号中获取。
    3. html模板+model数据,生成pdf的工具类
      注:
      ① FONT是黑体,每个window电脑基本上都有,目录都是一样的。FONT需要使用fontResolver.addFont(FONT…添加进去,不然可能汉字一偏空白。
      ② freeMarkDir是合同模板放置的位置,根据自己情况修改。
      ③ 使用的编码最好是"UTF-8",换一套环境后可能乱码。
    public class JavaToPdfHtmlFreeMarker {
    
        private final static Logger logger = LoggerFactory.getLogger(JavaToPdfHtmlFreeMarker.class);
    
        private static final String FONT = "C:\\Windows\\Fonts\\simhei.ttf";
        private static final String freeMarkDir = "D:\\app\\contractTemplate\\";
    
        private static Configuration freemarkerCfg = null;
    
        static {
            freemarkerCfg =new Configuration();
            //freemarker的模板目录
            try {
                freemarkerCfg.setDirectoryForTemplateLoading(new File(freeMarkDir));
                freemarkerCfg.setEncoding(Locale.CHINA, "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void createPdf1(String content,String dest) throws IOException, DocumentException, com.lowagie.text.DocumentException {
            // String LOGO_PATH = "file:///C:/Users/86132/Desktop/";
            ITextRenderer render = new ITextRenderer();
            ITextFontResolver fontResolver = render.getFontResolver();
            fontResolver.addFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            // 解析html生成pdf
            render.setDocumentFromString(content);
            //解决图片相对路径的问题
            // render.getSharedContext().setBaseURL(LOGO_PATH);
    
            render.layout();
            render.createPDF(new FileOutputStream(dest));
        }
        
        /**
         * freemarker渲染html
         */
        public static String freeMarkerRender(Map<String, Object> data, String htmlTmp) {
            Writer out = new StringWriter();
            try {
                // 获取模板,并设置编码方式
                Template template = freemarkerCfg.getTemplate(htmlTmp,"UTF-8");
                template.setEncoding("UTF-8");
    //            logger.info("template info --->" + template);
                // 合并数据模型与模板
                template.process(data, out); //将合并后的数据和模板写入到流中,这里使用的字符流
    //            logger.info("template info --->" + template);
    //            logger.info("out info --->" + out);
                out.flush();
                return out.toString();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    out.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            return null;
        }
    }
    
    1. 调用工具类生成pdf
    
    // 模板名称
    String HTML = "contract.html";
    // 生成的pdf存放路径
    String DEST = "D:\\app\\user_contract\\";
    // 生成的pdf名称
    String fileName = "合同D20210511SDNQB1.pdf"
    
    public static void main(String[] args) throws IOException, DocumentException, InterruptedException {
        Map<String,Object> data = new HashMap();
        data.put("合同编号","D20210511SDNQB");
        data.put("甲方姓名","小哈");
        data.put("签字日期","2021.05.13");
        String content = JavaToPdfHtmlFreeMarker.freeMarkerRender(data,HTML);
        JavaToPdfHtmlFreeMarker.createPdf(content,DEST);
    }
    
    1. 找指定电子签名的位置,然后再在指定位置插入签名图片工具类
    package weixin.charging.mercurius.weixin.service.impl.e_contractUtils;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import com.itextpdf.awt.geom.Rectangle2D.Float;
    import com.itextpdf.text.pdf.PdfDictionary;
    import com.itextpdf.text.pdf.PdfName;
    import com.itextpdf.text.pdf.PdfReader;
    import com.itextpdf.text.pdf.parser.*;
    
    public class PdfKeywordFinder {
    
    
        /**
         * @description: 查找插入签名图片的最终位置,因为是插入签名图片,所以之前的关键字应只会出现一次
         * 这里直接使用了第一次查找到关键字的位置,并返回该关键字之后的坐标位置
         * @return: float[0]:页码,float[1]:最后一个字的x坐标,float[2]:最后一个字的y坐标
         */
        public static float[] getAddImagePositionXY(String pdfName, String keyword) throws IOException {
            float[] temp = new float[3];
            List<float[]> positions = PdfKeywordFinder.findKeywordPostions(pdfName, keyword);
    //        PdfReader pdfReader = new PdfReader(pdfName);
    //        Rectangle pageSize = pdfReader.getPageSize(1);
    //        temp[0]=positions.get(0)[0];
    //        temp[1]=positions.get(0)[1]*pageSize.getWidth();
    //        temp[2]=positions.get(0)[2]*pageSize.getHeight();
            temp[0] = positions.get(0)[0];
            temp[1] = positions.get(0)[1] + (keyword.length() * positions.get(0)[3]);
            temp[2] = positions.get(0)[2] - positions.get(0)[3];
    
            return temp;
        }
    
        /**
         * findKeywordPostions
         *  返回查找到关键字的首个文字的左上角坐标值
         *
         * @param pdfName
         * @param keyword
         * @return List<float [ ]> : float[0]:pageNum float[1]:x float[2]:y
         * @throws IOException
         */
        public static List<float[]> findKeywordPostions(String pdfName, String keyword) throws IOException {
            File pdfFile = new File(pdfName);
            byte[] pdfData = new byte[(int) pdfFile.length()];
            FileInputStream inputStream = new FileInputStream(pdfFile);
            //从输入流中读取pdfData.length个字节到字节数组中,返回读入缓冲区的总字节数,若到达文件末尾,则返回-1
            inputStream.read(pdfData);
            inputStream.close();
    
            List<float[]> result = new ArrayList<>();
            List<PdfPageContentPositions> pdfPageContentPositions = getPdfContentPostionsList(pdfData);
    
            for (PdfPageContentPositions pdfPageContentPosition : pdfPageContentPositions) {
                List<float[]> charPositions = findPositions(keyword, pdfPageContentPosition);
                if (charPositions == null || charPositions.size() < 1) {
                    continue;
                }
                result.addAll(charPositions);
            }
            return result;
        }
    
        private static List<PdfPageContentPositions> getPdfContentPostionsList(byte[] pdfData) throws IOException {
            PdfReader reader = new PdfReader(pdfData);
    
            List<PdfPageContentPositions> result = new ArrayList<>();
            int pages = reader.getNumberOfPages();
            for (int pageNum = 1; pageNum <= pages; pageNum++) {
                float width = reader.getPageSize(pageNum).getWidth();
                float height = reader.getPageSize(pageNum).getHeight();
    
                PdfRenderListener pdfRenderListener = new PdfRenderListener(pageNum, width, height);
    
    //解析pdf,定位位置
                PdfContentStreamProcessor processor = new PdfContentStreamProcessor(pdfRenderListener);
                PdfDictionary pageDic = reader.getPageN(pageNum);
                PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);
                try {
                    processor.processContent(ContentByteUtils.getContentBytesForPage(reader, pageNum), resourcesDic);
                } catch (IOException e) {
                    reader.close();
                    throw e;
                }
                String content = pdfRenderListener.getContent();
                List<CharPosition> charPositions = pdfRenderListener.getcharPositions();
    
                List<float[]> positionsList = new ArrayList<>();
                for (CharPosition charPosition : charPositions) {
                    float[] positions = new float[]{charPosition.getPageNum(), charPosition.getX(), charPosition.getY(), charPosition.getCharWidth()};
                    positionsList.add(positions);
                }
    
                PdfPageContentPositions pdfPageContentPositions = new PdfPageContentPositions();
                pdfPageContentPositions.setContent(content);
                pdfPageContentPositions.setPostions(positionsList);
    
                result.add(pdfPageContentPositions);
            }
            reader.close();
            return result;
        }
    
    
        private static List<float[]> findPositions(String keyword, PdfPageContentPositions pdfPageContentPositions) {
    
            List<float[]> result = new ArrayList<>();
    
            String content = pdfPageContentPositions.getContent();
            List<float[]> charPositions = pdfPageContentPositions.getPositions();
    
            for (int pos = 0; pos < content.length(); ) {
                int positionIndex = content.indexOf(keyword, pos);
                if (positionIndex == -1) {
                    break;
                }
                float[] postions = charPositions.get(positionIndex);
                result.add(postions);
                pos = positionIndex + 1;
            }
            return result;
        }
    
        private static class PdfPageContentPositions {
            private String content;
            private List<float[]> positions;
    
            public String getContent() {
                return content;
            }
    
            public void setContent(String content) {
                this.content = content;
            }
    
            public List<float[]> getPositions() {
                return positions;
            }
    
            public void setPostions(List<float[]> positions) {
                this.positions = positions;
            }
        }
    
        private static class PdfRenderListener implements RenderListener {
            private int pageNum;
            private float pageWidth;
            private float pageHeight;
            private StringBuilder contentBuilder = new StringBuilder();
            private List<CharPosition> charPositions = new ArrayList<>();
    
            public PdfRenderListener(int pageNum, float pageWidth, float pageHeight) {
                this.pageNum = pageNum;
                this.pageWidth = pageWidth;
                this.pageHeight = pageHeight;
            }
    
            @Override
            public void beginTextBlock() {
    
            }
    
            @Override
            public void renderText(TextRenderInfo textRenderInfo) {
                List<TextRenderInfo> characterRenderInfos = textRenderInfo.getCharacterRenderInfos();
                for (TextRenderInfo renderInfo : characterRenderInfos) {
                    String word = renderInfo.getText();
                    if (word.length() > 1) {
                        word = word.substring(word.length() - 1, word.length());
                    }
                    Float rectangle = renderInfo.getAscentLine().getBoundingRectange();
                    float x = (float) rectangle.getMinX();
                    float y = (float) rectangle.getMinY();
                    float charWidth = (float) (rectangle.getMaxX() - rectangle.getMinX());
                    //也可以返回坐标相对于pdf页面大小的百分比
                    float xPercent = Math.round(x / pageWidth * 10000) / 10000f;
                    float yPercent = Math.round((1 - y / pageHeight) * 10000) / 10000f;
    
                    CharPosition charPosition = new CharPosition(pageNum, x, y, charWidth);
                    charPositions.add(charPosition);
                    contentBuilder.append(word);
                }
            }
    
            @Override
            public void endTextBlock() {
    
            }
    
            @Override
            public void renderImage(ImageRenderInfo renderInfo) {
    
            }
    
            public String getContent() {
                return contentBuilder.toString();
            }
    
            public List<CharPosition> getcharPositions() {
                return charPositions;
            }
        }
    
        private static class CharPosition {
            private int pageNum = 0;
            private float x = 0;
            private float y = 0;
            private float charWidth = 0;//单个文字的宽度
    
            public CharPosition(int pageNum, float x, float y, float charWidth) {
                this.pageNum = pageNum;
                this.x = x;
                this.y = y;
                this.charWidth = charWidth;
            }
    
            public int getPageNum() {
                return pageNum;
            }
    
            public float getX() {
                return x;
            }
    
            public float getY() {
                return y;
            }
    
            public float getCharWidth() {
                return charWidth;
            }
    
            @Override
            public String toString() {
                return "[pageNum=" + this.pageNum + ",x=" + this.x + ",y=" + this.y + "]";
            }
        }
    }
    
    
    1. 在pdf上添加签名
    public static void main(String[] args) throws IOException {
                // base64格式的图片
                String signData = 'data:image/png;base64,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';
            // 生成电子签字
                String oldPdfUrl= DEST+"合同D20210511SDNQB1.pdf";
                String newPdfUrl= DEST+"合同D20210511SDNQB.pdf";
                //查找签名位置
                float[] position= PdfKeywordFinder.getAddImagePositionXY(oldPdfUrl,"承租人(乙方)签章:");
                //Read file using PdfReader
                PdfReader pdfReader = new PdfReader(oldPdfUrl);
                System.out.println("x:"+position[1]+" y:"+position[2]);
                PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(newPdfUrl));
                String imgUrl = Base64ImgConvert.convertBase64ToPng(signData, contractNo);
                Image image = Image.getInstance(imgUrl);
                //Fixed Positioning
                image.scaleAbsolute(100, 50);
                //Scale to new height and new width of image
                image.setAbsolutePosition(position[1], position[2]);
    
                System.out.println("pages:"+pdfReader.getNumberOfPages());
                PdfContentByte content = pdfStamper.getUnderContent((int) position[0]);
                content.addImage(image);
                pdfStamper.close();
        }
    

    如有错误,欢迎指正!
    微信公众号,欢迎关注交流!
    在这里插入图片描述

    展开全文
  • java 制作签名电子合同

    千次阅读 2020-04-07 16:57:26
    根据项目需求,需要生成一个带电子签名的合同,即客户在手机进行签名后,将签名图片合成到合同中。 目前方案有两个,使用docx4j插件根据书签生成word版电子合同 或者 使用itext插件根据PDF模版生成PDF版电子合同。 ...
  • 手写签名SDK支持:动态时间包装(DTW),扩展回归(ER),签名采样,方向哈希和功能提取:有关更多信息,请参见Wiki。
  • java pdf 实现电子签章下载

    热门讨论 2017-10-07 21:35:44
    java pdf 实现电子签章,包含两种实现itextpdf,pdfbox.
  • http://download.oracle.com/javase/tutorial/security/apisign/examples/GenSig.java. How can I sign a pdf file using this digital signature? That is: how...
  • 电子签名API是e签宝提供的一种电子签名开放服务能力,e签宝提供了丰富的API接口,为用户提供一套完整的全生态电子签名服务,为客户提供具有法律效力的电子合同全生命周期服务,将原本需要耗费数日之久的文件签署环节...
  • 开发相关电子书籍(PDF),目前主要是Android开发,其次包含:Kotlin、Java、网络等 Kotlin 书名 链接 分享者 kotlin官方参考文档-中文版 - Android 书名 链接 分享者 Android开发艺术探索 - Android群英传 - Android ...
  • 本资源用于java实现在网页上手写笔迹进行生成图片保存,例如在网页上用鼠标写出自己的名字,生成图片,保存名字。
  • 这里是想说明自己在开发工程中遇到的坑,有这么一个需求,就是利用java 实现生成电子表单,里面用到了openoffice中间件,同时将电子表单内容生成excel后转为pdf 后生成图片,里面实现了动态签名,盖章等效果,
  • 本论文介绍了基于java带数字签名电子邮件系统,对使用的相关的技术进行了详细的阐述。按照软件开发的生命周期论述了系统分析、概要设计、详细设计和代码实现。具体论述了数字签名在邮件系统中的实现原理。以及邮件...
  • 《实验项目1 Java开发环境与语言基础》由会员分享,可在线阅读,更多相关《实验项目1 Java开发环境与语言基础(14页珍藏版)》请在人人文库网上搜索。1、实验项目1 Java开发环境与语言基础第1部分 Java程序开发环境...
  • Java数字签名提供XML安全众所周知,XML在产品和项目开发中起着非常重要的作用。通过XML文档可以获取很多信息,还可以使用XML文件进行CRUD(增加、查询、更新和 删除)操作。然而值得注意的是,我们如何确保XML中的...
  • Android 画布使用之电子签名

    千次阅读 2016-12-19 22:10:22
    所以毫无疑问,电子签名又是公司最近需要开发的新功能。 应用场景:以前去银行办理业务都得去柜台,填N张表格,写N多个签名。随着智能机的普及、移动终端app的使用场景越来越广泛。手机银行app也给越来越多的人办理...
  • java操作pdf制作电子签章

    万次阅读 热门讨论 2017-10-07 21:40:32
    java操作pdf制作电子签章电子签章简介电子签章,与我们所使用的数字证书一样,是用来做为身份验证的一种手段,泛指所有以电子形式存在,依附在电子文件并与其逻辑关联,可用以辨识电子文件签署者身份,保证文件的...
  • java中编程实现数字签名系统

    千次阅读 2018-11-21 09:49:01
    一个数字签名系统主要分为三个部分:  ...生成密钥对可用java提供的类KeyPairGenerator,用其中的getInstance方法创建KeypairGenerator对象,在用initialize进行初始化,最后用generateKeyPair生成密钥...
  • OpenSSL和keytool 先说一下两个重要的工具 OpenSSL:OpenSSL整个软件包大概可以分成三个主要的功能部分:SSL...两者都是可以用来生成加密密钥的工具,keytool出自Java体系,它可以直接操作KeyStore,而OpenSSL不支持
  • 我在使用受信任的时间戳与BouncyCastle创建有效的CMS签名时遇到问题。签名创建工作良好(我想将签名包括到PDF文件中),签名有效。但是,当我在签名的未签名属性表中添加可信时间戳后,签名仍然保持有效,但是Reader会...
  • 简介众所周知,XML在产品和项目开发中起着非常重要的作用。通过XML文档可以获取很多信息,还可以使用XML文件进行CRUD(增加、查询、更新和删除)操作。然而值得注意的是,我们如何确保XML中的数据是来自经过认证的可信...
  • 电子签名,盖章实例

    2017-02-18 18:58:49
    java jQuery html5 电子签名 盖章实例,需要研发整合才行。本人开发已实现 电子签名盖章 安全认证领域。。方法有很多,看需求,看知识面有多广。
  • 作者:coyota666来源:...虽然电子签名多年来合法性一直遭到质疑,但其在企业工作流审批、请柬、单据保全等场景应用广泛,最近的项目中就有这样一个手写签名并生成PDF文件的需求。实现思路使用canva...
  • 如何用 Java 对 PDF 文件进行电子签章

    万次阅读 多人点赞 2018-02-11 00:49:03
    一、 概述二、 技术选型三、 生成一个图片签章四、 如何按模板生成PDF文件五、 如何生成PKCS12证书六、 如何生成一个高清晰的签章七、 如何进行多次PDF签名八、 总结一、 概述印章是我国特有的历史文化产物,古代...
  • java实现数字签名

    2009-08-05 15:11:33
    电子政务是依赖于计算机和网络技术而...由于Java在网络编程中的适用性,以及Java的安全系统结构日益完善和目前Java开发网络安全软件的便利性,因此在电子政务系统中用Java来实现数字签名会具有更好的安全性和现实意义。
  • java swing实现手写板电子签名系统

    千次阅读 2010-07-18 13:28:00
    java swing实现手写板电子签名系统   支持 手写板 ,触摸屏电脑,支持压强 压感效果......................... 部分代码 MyLeftPanel.java   public void paintComponent(Graphics g)  {  super....
  • java通过itext开发PDF数字签名时总是出现"进行BER解码时发生错误",请问各位大神这什么原因造成的。
  • 上一篇忘了说MAC和TAC是什么东西,这里补充下: 其实跟计算机网络安全里面的“数据加密&&数字签名”的模式很相像,一个是内容的加密和验证,也就是信息的私密性,一个是内容完整性的验证,也就是验证发送接收方...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,430
精华内容 4,572
关键字:

java开发电子签名

java 订阅