IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> itextpdf 提取数字签名签章图片 -> 正文阅读

[游戏开发]itextpdf 提取数字签名签章图片

itextpdf 提取数字签名签章图片

因业务需求,需要对签名的pdf进行签名验证,政府的电子验证的功能是除了提取pdf表单内容外,还可以提取签章的图片,研究了好久,特此记录一下。

/**
 * 获取pdf签名图片信息
 * @param path          pdf文件
 * @param fileBasePath  图片保存基础路径
 * @return              提取结果
 */
public static PdfSignInfo getImageFromPdf(String path, String fileBasePath) {
    PdfSignInfo pdfSignInfo = new PdfSignInfo();
    try {
        FileInputStream fis = new FileInputStream(path);
        PdfReader reader = new PdfReader(fis);

        String fileName = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
        if (!fileBasePath.endsWith("/")) {
            fileBasePath = fileBasePath + "/";
        }
        fileBasePath = fileBasePath + fileName + "/";
        File file = new File(fileBasePath);
        file.mkdirs();

        pdfSignInfo.setName(path.substring(path.lastIndexOf("/") + 1));

        Field rsaDataField = PdfPKCS7.class.getDeclaredField("RSAdata");
        rsaDataField.setAccessible(true);

        int numberOfPages = reader.getNumberOfPages();
        // pdf 页码数量
        log.debug("page size: {}", numberOfPages);

        int xrefSize = reader.getXrefSize();

        ExtImageRenderListener listener = new ExtImageRenderListener();
        listener.setBasePath(fileBasePath);

        // 获取acro字段
        AcroFields fields = reader.getAcroFields();
        Rectangle pageSize = reader.getPageSize(numberOfPages - 1);
        // pdf 作用域尺寸(全屏)
        log.info("pdf rectangle: {},{},{},{}", pageSize.getLeft(), pageSize.getBottom(), pageSize.getRight(), pageSize.getTop());

        // 获取签名名称
        ArrayList<String> signatureNames = fields.getSignatureNames();
        for (String name : signatureNames) {
            // 指定提供者 获取签名的pkcs7数据
            PdfPKCS7 pkcs7 = fields.verifySignature(name);
            X509Certificate certificate = pkcs7.getSigningCertificate();

            PdfSignInfo.SignatureDetail info = new PdfSignInfo.SignatureDetail();

            String[] appearanceStates = fields.getAppearanceStates(name);
            // 表单域的位置
            List<AcroFields.FieldPosition> fieldPositions = fields.getFieldPositions(name);
            for (AcroFields.FieldPosition fieldPosition : fieldPositions) {
                Rectangle position = fieldPosition.position;
                log.info("field {} position: {}, {}, {}, {}, {}", name, fieldPosition.page,
                        position.getLeft(), position.getBottom(), position.getRight(), position.getTop());
                info.page = fieldPosition.page;
                info.llx = position.getLeft();
                info.lly = position.getBottom();
                info.urx = position.getRight();
                info.ury = position.getTop();
            }

            AcroFields.Item fieldItem = fields.getFieldItem(name);
            int size = fieldItem.size();
            for (int i = 0; i < size; i++) {
                PdfDictionary value = fieldItem.getValue(i);
                Set<PdfName> keys = value.getKeys();
                for (PdfName key : keys) {
                    String keyName = PdfName.decodeName(new String(key.getBytes()));
                    if ("Rect".equalsIgnoreCase(keyName)) {
                        log.debug("签名域的坐标为:{}", value.get(key));
                    }
                }
                PdfObject pdfObject = value.get(PdfName.AP);
                if (pdfObject != null) {
                    PdfDictionary dictionary = (PdfDictionary) pdfObject;
                    PdfIndirectReference ref = (PdfIndirectReference) dictionary.get(PdfName.N);
                    int number = ref.getNumber();
                    log.debug("fieldName: {}, idx: {}", name, number);

                    // 根据ap 获取签章图片
                    PdfObject pdfObjectRelease = reader.getPdfObject(number);
                    if (pdfObjectRelease instanceof PdfStream) {
                        PdfStream s = (PdfStream) pdfObjectRelease;
                        PdfDictionary resources = s.getAsDict(PdfName.RESOURCES);
                        listener.setI(number);
                        try {
                            PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener);
                            processor.processContent(ContentByteUtils.getContentBytesFromContentObject(s), resources);
                            info.filePath = fileBasePath + number + ".png";
                        } catch (Exception ignore) {}
                    }
                }

            }

            // 签名信息
            info.name = name;
            info.time = pkcs7.getSignDate().getTime();
            info.notBefore = certificate.getNotBefore();
            info.notAfter = certificate.getNotAfter();
            info.dnName = certificate.getSubjectDN().getName();
            info.serialNumber = certificate.getSerialNumber();
            info.pubKey = Base64Encoder.encode(certificate.getPublicKey().getEncoded());
            info.pubKeyFormat = certificate.getPublicKey().getFormat();
            info.sigAlgName = certificate.getSigAlgName();
            info.userDnName = certificate.getIssuerDN().getName();
            info.reason = pkcs7.getReason();
            info.location = pkcs7.getLocation();

            info.res = pkcs7.verify();

            pdfSignInfo.getSignatureDetails().add(info);
        }
        log.info(JSON.toJSONString(pdfSignInfo));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return pdfSignInfo;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PdfSignInfo {

    private String name;

    private List<SignatureDetail> signatureDetails = new ArrayList<>();

    public static class SignatureDetail {
        public String name;
        // 签名日期时间
        public Date time;
        // 有效期开始时间
        public Date notBefore;
        // 有效期
        public Date notAfter;
        // 证书名称
        public String dnName;
        // 序列号
        public BigInteger serialNumber;
        // 证书格式 // 证书颁发者
        public String pubKey, pubKeyFormat, sigAlgName, userDnName;
        public boolean res;
        public String imageContent, imagePath;

        public String reason, location;

        public int page;
        public float llx, lly, urx, ury;

        public String filePath;
    }

}
@Slf4j
@Data
public class ExtImageRenderListener implements RenderListener {
    private int i;
    private String basePath;
    @Override
    public void beginTextBlock() {

    }

    public void setBasePath(String basePath) {
        if (basePath.endsWith("/")) {
            this.basePath = basePath;
        } else {
            this.basePath = basePath + "/";
        }
    }

    @Override
    public void renderText(TextRenderInfo renderInfo) {

    }

    @Override
    public void endTextBlock() {

    }

    PdfDictionary resources;

    List<List<Integer>> numbers = new ArrayList<>();

    @SneakyThrows
    @Override
    public void renderImage(ImageRenderInfo renderInfo) {
        PdfImageObject image = renderInfo.getImage();
        if (image == null) {
            log.debug("Image {} could not be read", renderInfo.getRef().getNumber());
            return;
        }

        BufferedImage bufferedImage = image.getBufferedImage();
        if (bufferedImage != null) {
            log.debug("bufferedImage: {}", bufferedImage.getHeight());
            writeImage(bufferedImage);
        }

//        PRStream maskStream = (PRStream) image.getDictionary().getAsStream(PdfName.SMASK);
//        if (maskStream != null) {
//            PdfImageObject pdfImageObject = new PdfImageObject(maskStream);
//            log.debug("mask image: {}", pdfImageObject.getFileType());
//            BufferedImage mask = pdfImageObject.getBufferedImage();
//            writeImage(mask);
//        }
    }

    private void writeImage(BufferedImage bufferedImage) {
        try {
            File file = new File(basePath + i + ".png");
            if (file.exists()) {
                return;
            }
            log.debug("generated image: {}", file.getPath());
            ImageIO.write(bufferedImage, "png", file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-28 12:10:15  更:2022-04-28 12:10:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 14:59:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码