자바 를 이용 하여 PDF 파일 에 전자 서명 을 하 는 실전 과정
인장 은 우리 나라 특유 의 역사 문화 산물 로 고대 에는 주로 신분증 과 직권 을 행사 하 는 도구 로 사용 되 었 다.그것 의 기원 은 사회 생활 의 실제 수요 때문이다.일찍이 상주 시대 에 인장 이 이미 생 겼 다.오늘날 의 인장 은 이미 독특 하고 실용성 과 예술성 을 하나 로 융합 시 킨 예술 보물 이 되 었 다.전통 적 인 인장 은 나 쁜 사람,소인 에 게 개인 적 으로 새 겨 지기 쉽다.어떤 개인 공인 이 국가 재산 을 착복 했다 는 보 도 는 드 물 었 다.컴퓨터 기술,암호 화 기술 과 영상 처리 기술 의 발전 에 따라 전자 서명 이 나 타 났 다.전자 서명 은 전자 서명 의 표현 형식 으로 이미지 처리 기술,디지털 암호 화 기술 을 이용 하여 전자 서명 작업 을 종이 파일 날인 작업 과 같은 시각 적 효과 로 전환 시 키 는 동시에 전자 서명 기술 을 이용 하여 전자 정보의 진실성 과 완전 성,서명 인의 부인 할 수 없 는 성 을 보장 한다.
전자 서명 은 디지털 인증서 와 마찬가지 로 인증 의 한 수단 으로 전자 형식 으로 존재 하고 전자 문서 에 의존 하 며 논리 적 으로 관련 되 며 전자 문서 서명 자의 신분 을 식별 하고 문서 의 완전 성 을 확보 하 며 서명 자가 전자 문서 가 진술 한 사실 에 동의 하 는 내용 을 말한다.일반적으로 전자 서명 에 대한 인정 은 기술적 인 측면 에서 볼 수 있다.특정 기술 방안 을 통 해 당사자 의 신분 을 감별 하고 전자 자료 내용 이 변조 되 지 않도록 하 는 안전 보장 조 치 를 말한다.전자 서명 은 항상 안전 이메일 발송,안전 사이트 방문,인터넷 입찰 입찰 입찰,인터넷 계약,안전 인터넷 공문 전송,회사 계약,전자 처방 용지 등 을 보낸다.
전자 서명 은 매우 복잡 한 문제 로 관련 전자 서명 시스템 이 있 을 정도 로 크다.전자 처방전 의 PDF 파일 에 전자 서명 을 적용 하 는 방법 을 공유 합 니 다.
2.기술 선택
현재 주류 처리 PDF 파일 두 jar 패 키 지 는 다음 과 같 습 니 다.
PDFBox,iText 5,iText 7 세 가 지 를 비교 합 니 다.
1.다음 그림 과 같은 사인 사진 생 성
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 {
/**
* @param doctorName
* String
* @param hospitalName
* String
* @param date
* String
*
* @param jpgname
* String jpg
* @return
*/
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");
}
}
4.어떻게 템 플 릿 에 따라 PDF 파일 을 생 성 합 니까?1.PDF 템 플 릿 만 들 기
현재 PDF 템 플 릿 도 구 는 다른 것 이 없어 위대 한 Adobe 회사 가 제공 하 는 Adobe Acrobatpro DC 소프트웨어 로 만 제작 할 수 있다.이 소프트웨어 를 어떻게 사용 하 는 지 는 더 이상 말 하지 않 겠 습 니 다.사용 중 에 어떤 것 이 있 으 면 따로 문의 하 셔 도 됩 니 다.
2.다음 그림 과 같은 PDF 템 플 릿 을 만 듭 니 다.이 템 플 릿 은 PDF 가 있 는 폼 필드 입 니 다.
5.PKCS 12 인증 서 를 어떻게 생 성 합 니까?
1.PKCS 의 간단 한 소개
PKCS:The Public-Key Cryptography Standards(PKCS 로 약칭)는 미국 RSA 데이터 보안 회사 와 합작 파트너 가 제정 한 공개 키 암호 학 기준 으로 인증서 신청,인증서 업데이트,인증서 폐기 표 발표,확장 인증서 내용 과 디지털 서명,디지털 봉투 의 형식 등 일련의 관련 협 의 를 포함한다.
1999 년 말 까지 PKCS 는 다음 과 같은 기준 을 발표 했다.
2.JAVA 를 사용 하여 PKCS 12 인증 서 를 생 성하 고 저장 합 니 다.관련 분석 은 코드 설명 참조.
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;
}
/**
* @param password
*
* @param issuerStr
*
* @param subjectStr
*
* @param certificateCRL
*
* @return
*/
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;
}
/**
* @param issuerStr
* @param subjectStr
* @param keyPair
* @param result
* @param certificateCRL
* @param extensions
* @return
*/
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,[email protected],L= ,ST= ";
String subjectStr = "CN=huangjinjin,OU=gitbook ,O=gitbook ,C=CN,[email protected],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();
}
}
6.어떻게 높 고 뚜렷 한 사인 을 만 듭 니까?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 {
/**
* @param fields
* @param data
* @throws IOException
* @throws DocumentException
*/
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, " ");
}
}
}
/**
* @param templatePdfPath
* pdf
* @param generatePdfPath
* pdf
* @param data
*
*/
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();
/* PDF */
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);
/* , false PDF , true*/
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 );
}
}
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 {
/**
* @param password
*
* @param keyStorePath
*
* @param signPdfSrc
* PDF
* @param signImage
*
* @param x
* x
* @param y
* y
* @return
*/
public static byte[] sign(String password, String keyStorePath, String signPdfSrc, String signImage,
float x, float y) {
File signPdfSrcFile = new File(signPdfSrc);
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(signPdfSrc);
signPDFData = new ByteArrayOutputStream();
// pdf
File temp = new File(signPdfSrcFile.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();
}
}
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 {
/**
* @param password
*
* @param keyStorePath
*
* @param signPdfSrc
* PDF
* @param x
*
* @param y
* @return
*/
public static byte[] sign(String password, String keyStorePath, String signPdfSrc,
float x, float y,
String signText) {
File signPdfSrcFile = new File(signPdfSrc);
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(signPdfSrc);
signPDFData = new ByteArrayOutputStream();
// pdf
File temp = new File(signPdfSrcFile.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, "
2017-12-20");
FileOutputStream f = new FileOutputStream(new File("C:\\Users\\zhilin\\Desktop\\chat\\signed2.pdf"));
f.write(fileData);
f.close();
}
}
아래 두 개의 서명 의 차 이 를 분석 해 보면 왼쪽 의 서명 이 매우 모호 하고 오른쪽 이 매우 뚜렷 하 다 는 것 을 발견 할 수 있다.7.어떻게 여러 번 PDF 서명 을 진행 합 니까?
여러 개의 서명 중점 코드 를 생 성하 여 SignPdf.자바 류 에 레이 블 설명 을 했 습 니 다.여러 번 서명 을 하려 면 이미 서명 한 PDF 파일 에 다시 sign 방법 을 호출 하여 다시 서명 하면 됩 니 다(여섯 번 째 시 에 그림 이 있 으 면 두 개의 서명 이 있 습 니 다.이것 이 바로 여러 번 서명 한 결과 입 니 다).
PdfStamper.createSignature(reader, signPDFData, '\0', temp, true);
8.총화공유 중인 sign.jpg 파일 의 흰색 배경 을 투명 하 게 처리 해 야 정확 한 전자 서명 효 과 를 얻 을 수 있 습 니 다.SignPdf.자바 와 SignHighPdf.자바 를 문자 가 있 는 PDF 에 서명 하여 효 과 를 볼 수 있 습 니 다).
모두 가 본 회사 의 공인 은 모두 원형 이다.이것 도 할 수 있 습 니 다.여러분 은 동 그 란 그림 사인 을 어떻게 만 드 는 지 생각해 보 세 요.그리고 전자 서명 을 합 니 다.여 기 는 주로 코드 실현 을 설명 하 는데 모든 코드 가 매우 많다.모두 돌아 가서 코드 를 잘 연구 해라.진정한 전자 서명 은 CA 인증 회 사 를 통 해 이 루어 져 야 합 니 다.저 는 참고 방안 을 제공 하여 여러분 에 게 공부 하 게 할 뿐 입 니 다.
자 바 를 이용 하여 PDF 파일 에 대한 전자 서명 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 가 PDF 파일 에 대한 전자 서명 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.