目录
1.SM2签章
国密签章是有签章结构的,遵循一定的标准,可以从签章结构中解析出印章,然后再从印章中保存图片
代码如下:
public void getSealFromPDFStamp() throws Exception {
String pdfStampPath = "F:/Netseal_Work/签章项目和主线总结/离职证明/适配子公司UKEY/上海信旋/安印工具签章.pdf";
byte[] pdfData = FileUtil.getFile(pdfStampPath);
PdfReader reader = null;
try {
reader = new PdfReader(pdfData);
AcroFields af = reader.getAcroFields();
ArrayList<String> names = af.getSignatureNames();
// 获取每一个签名域的 Contents
for (String name : names) {
PdfDictionary dictionary = af.getSignatureDictionary(name);
byte[] bytes = dictionary.getAsString(PdfName.CONTENTS).getBytes();
String hexContents = HexUtil.byte2Hex(bytes);
while (hexContents.endsWith("00"))
hexContents = hexContents.substring(0, hexContents.length() - 2);
StampData sd = new StampData(bytes);
byte[] stampData = sd.getEseal().getEncoded();
FileUtil.storeFile("E:/1.asn1",stampData);
}
} catch (Exception e) {
throw e;
} finally {
try {
if (reader != null)
reader.close();
} catch (Exception e) {
}
}
}
解析保存下来的文件用asn1工具打开
将图片数据保存成文件,就可以把印章图片提取出来了
2.RSA签章
RSA签章没有签章结构,笼统意义来说就是加盖图片进行签名,所以不能再用上面的方式进行提取印章图片,使用PDF源码进行提取
public PdfImageObject extractImage(String signatureName) throws Exception {
MyImageRenderListener listener = new MyImageRenderListener();
PdfDictionary sigFieldDic = reader.getAcroFields().getFieldItem(signatureName).getMerged(0);
PdfDictionary appearancesDic = sigFieldDic.getAsDict(PdfName.AP);
PdfStream normalAppearance = appearancesDic.getAsStream(PdfName.N);
PdfDictionary resourcesDic = normalAppearance.getAsDict(PdfName.RESOURCES);
PdfContentStreamProcessor processor = new PdfContentStreamProcessor(listener);
processor.processContent(ContentByteUtils.getContentBytesFromContentObject(normalAppearance), resourcesDic);
return listener.image;
}
public static void main(String[] args) throws Exception {
byte[] pdfData = FileUtil.getFile("F:/Netseal_Work/签章项目和主线总结/离职证明/适配子公司UKEY/上海信旋/安印工具签章.pdf");
PdfReader reader = new PdfReader(pdfData);
AcroFields acroFields = reader.getAcroFields();
List<String> names = acroFields.getSignatureNames();
ExtractPhoto ep = new ExtractPhoto(reader);
for (String name : names) {
PdfImageObject image = ep.extractImage(name);
FileUtil.storeFile("f:/temp/pdf/" + name + ".png", image.getImageAsBytes());
}
reader.close();
}
}
注意:解析出来的图片带背景,一般都是白色背景,然后再进行一次去背景的操作
public static byte[] cleanBGColor(byte[] bs) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(bs);
BufferedImage bi = ImageIO.read(bais);
BufferedImage tmp = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
for (int i = 0, width = bi.getWidth(); i < width; i++) {
for (int j = 0, height = bi.getHeight(); j < height; j++) {
int rgb = bi.getRGB(i, j);
// if (((rgb & 0xff000000) >> 24 & 0xff) > 0x80)
// tmp.setRGB(i, j, rgb);
// else
// tmp.setRGB(i, j, Color.WHITE.getRGB());
byte[] d = HexUtil.int2Byte(rgb);
int a = d[0] & 0xff;
int r = d[1] & 0xff;
int g = d[2] & 0xff;
int b = d[3] & 0xff;
if (r == 255 && g == 255 && b == 255) {
d[0] = 0;
rgb = HexUtil.byte2Int(d);
}
tmp.setRGB(i, j, rgb);
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(tmp, "png", baos);
return baos.toByteArray();
}
以上步骤就可以获取RSA签章文件的印章图片了