Untitled
unknown
java
3 years ago
19 kB
6
Indexable
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDictionary;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfName;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.*;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.bouncycastle.cert.ocsp.OCSPException;
import org.bouncycastle.cert.ocsp.OCSPResp;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.tsp.*;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import javax.net.ssl.*;
import java.io.*;
import java.math.BigInteger;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
public class ApiConnect {
public static final String baseURL = "https://emea.api.dss.globalsign.com:8443/v2";
private static final String fieldName = "sig1";
private static String RESOURCE_FOLDER = "src/main/resources/";
private static final String SRC = RESOURCE_FOLDER + "hello_world.pdf";
private static final String DEST = RESOURCE_FOLDER + "signed_dss_production.pdf";
private static final String LTV = RESOURCE_FOLDER + "LTV_dss_production.pdf";
public static JSONObject login(String aURL, Object aKey, Object aSecret)
throws IOException, ParseException {
URL loginURL = new URL(aURL + "/login");
HttpsURLConnection conn = (HttpsURLConnection) loginURL.openConnection();
JSONObject apiLogin = new JSONObject();
apiLogin.put("api_key", aKey);
apiLogin.put("api_secret", aSecret);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setRequestProperty("Content-Length", "" + apiLogin.toString().length());
//Send Request
conn.setDoOutput(true);
DataOutputStream os = new DataOutputStream(conn.getOutputStream());
os.writeBytes(apiLogin.toString());
os.flush();
os.close();
//Get Response
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String aux = "";
StringBuilder builder = new StringBuilder();
while ((aux = br.readLine()) != null) {
builder.append(aux);
}
String output = builder.toString();
JSONParser parser = new JSONParser();
JSONObject accessCode = (JSONObject) parser.parse(output);
br.close();
conn.disconnect();
return accessCode;
}
public static JSONObject identity(String aURL, JSONObject aObj) throws IOException, ParseException {
URL loginURL = new URL(aURL + "/identity");
HttpsURLConnection conn = (HttpsURLConnection) loginURL.openConnection();
//info for certificate with individual identities
/**JSONObject apiID = new JSONObject();
JSONObject subj = new JSONObject();
subj.put("common_name", "ENTER YOUR N@ME");
subj.put("country", "US");
JSONArray adm = new JSONArray();
adm.add("ENTER YOUR DEP@RTMENT");
subj.put("organizational_unit", adm);
apiID.put("subject_dn", subj); **/
//info for organization certificate has been prepopulated so we send an empty request
JSONObject apiID = new JSONObject();
String token = (String) aObj.get("access_token");
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "Bearer " + token);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setRequestProperty("Content-Length", "" + apiID.toString().length());
//Send Request
conn.setDoOutput(true);
DataOutputStream os = new DataOutputStream(conn.getOutputStream());
os.writeBytes(apiID.toString());
os.flush();
os.close();
//Get Response
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String aux = "";
StringBuilder builder = new StringBuilder();
while ((aux = br.readLine()) != null) {
builder.append(aux);
}
String output = builder.toString();
JSONParser parser1 = new JSONParser();
JSONObject identity = (JSONObject) parser1.parse(output);
br.close();
conn.disconnect();
return identity;
}
public static JSONObject certificatePath(String aURL, JSONObject aObj) throws IOException, ParseException {
URL loginURL = new URL(aURL + "/certificate_path");
HttpsURLConnection conn = (HttpsURLConnection) loginURL.openConnection();
String token = (String) aObj.get("access_token");
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Bearer " + token);
//Get Response
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String aux = "";
StringBuilder builder = new StringBuilder();
while ((aux = br.readLine()) != null) {
builder.append(aux);
}
String output = builder.toString();
JSONParser parser = new JSONParser();
JSONObject path = (JSONObject) parser.parse(output);
br.close();
conn.disconnect();
return path;
}
public static JSONObject sign(String aURL, String id, String digest, JSONObject aObj)
throws IOException, ParseException {
URL loginURL = new URL(aURL + "/identity/" + id + "/sign/" + digest);
HttpsURLConnection conn = (HttpsURLConnection) loginURL.openConnection();
String token = (String) aObj.get("access_token");
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Bearer " + token);
//Get Response
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String aux = "";
StringBuilder builder = new StringBuilder();
while ((aux = br.readLine()) != null) {
builder.append(aux);
}
String output = builder.toString();
JSONParser parser = new JSONParser();
JSONObject signature = (JSONObject) parser.parse(output);
br.close();
conn.disconnect();
return signature;
}
public static JSONObject timestamp(String aURL, String digest, JSONObject aObj) throws IOException, ParseException{
URL loginURL = new URL (aURL+ "/timestamp/" + digest);
HttpsURLConnection conn = (HttpsURLConnection) loginURL.openConnection();
String token = (String)aObj.get("access_token");
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Bearer "+ token);
//Get Response
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String aux = "";
StringBuilder builder = new StringBuilder();
while ((aux = br.readLine()) != null){
builder.append(aux);
}
String output = builder.toString();
JSONParser parser = new JSONParser();
JSONObject time = (JSONObject) parser.parse(output);
br.close();
conn.disconnect();
return time;
}
public static Certificate[] createChain(String cert, String ca) throws IOException, CertificateException {
Certificate[] chainy = new Certificate[2];
CertificateFactory fact = CertificateFactory.getInstance("X.509");
X509Certificate cer = null;
InputStream in = new ByteArrayInputStream(cert.getBytes("UTF-8"));
cer = (X509Certificate) fact.generateCertificate(in);
chainy[0] = (Certificate) cer;
X509Certificate caCert = null;
in = new ByteArrayInputStream(ca.getBytes("UTF-8"));
caCert = (X509Certificate) fact.generateCertificate(in);
chainy[1] = (Certificate) caCert;
return chainy;
}
static class DSSTSAClient implements ITSAClient{
public static final int DEFAULTTOKENSIZE = 4096;
public static final String DEFAULTHASHALGORITHM = "SHA-256";
private final JSONObject accessToken;
public DSSTSAClient (JSONObject accessToken){
this.accessToken = accessToken;
}
public MessageDigest getMessageDigest() throws GeneralSecurityException {
return MessageDigest.getInstance(DEFAULTHASHALGORITHM);
}
public byte[] getTimeStampToken(byte[] imprint) throws Exception {
TimeStampRequestGenerator tsqGenerator = new TimeStampRequestGenerator();
tsqGenerator.setCertReq(true);
BigInteger nonce = BigInteger.valueOf(System.currentTimeMillis());
TimeStampRequest request = tsqGenerator.generate(new ASN1ObjectIdentifier(DigestAlgorithms.getAllowedDigest(DEFAULTHASHALGORITHM)), imprint, nonce);
JSONObject time = timestamp(baseURL,Hex.encodeHexString(request.getMessageImprintDigest()),accessToken);
String tst = (String)time.get("token");
byte[] token = Base64.getDecoder().decode(tst);
CMSSignedData cms = new CMSSignedData(token);
TimeStampToken tstToken = new TimeStampToken(cms);
return tstToken.getEncoded();
}
public int getTokenSizeEstimate() {
return DEFAULTTOKENSIZE;
}
}
static void addLTV(String src, String dest, IOcspClient ocsp, ICrlClient crl, LtvVerification.Level timestampLevel, LtvVerification.Level signatureLevel) throws IOException, GeneralSecurityException
{
PdfDocument pdfDoc = new PdfDocument(new PdfReader(new FileInputStream(src)), new PdfWriter(new FileOutputStream(dest)), new StampingProperties().useAppendMode());
LtvVerification v = new LtvVerification(pdfDoc);
SignatureUtil signatureUtil = new SignatureUtil(pdfDoc);
List<String> names = signatureUtil.getSignatureNames();
String sigName = names.get(names.size() - 1);
PdfPKCS7 pkcs7 = signatureUtil.readSignatureData(sigName);
if (pkcs7.isTsp())
{
v.addVerification(sigName, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
timestampLevel, LtvVerification.CertificateInclusion.YES);
}
else
{
for (String name : names)
{
v.addVerification(name, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
signatureLevel, LtvVerification.CertificateInclusion.YES);
}
}
v.merge();
pdfDoc.close();
}
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
GSConfig config = new GSConfig();
InputStream trustStream = new FileInputStream(config.sslCertificatePath());
char[] trustPassword = config.getKeyPassword().toCharArray();
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(trustStream, trustPassword);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(trustStore, trustPassword);
KeyManager[] kms = kmf.getKeyManagers();
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kms, trustAllCerts, null);
SSLContext.setDefault(sslContext);
//get JSON access token
JSONObject access = login(baseURL, config.getApiKey(), config.getApiSecret());
//get JSON with id/certificate/ocsp respone
JSONObject identity = identity(baseURL, access);
String cert = (String) identity.get("signing_cert");
String id = (String) identity.get("id");
String oc1 = (String) identity.get("ocsp_response");
JSONObject path = certificatePath(baseURL, access);
String ca = (String) path.get("path");
//Create Certificate chain
Certificate[] chain = createChain(cert, ca);
String temp = RESOURCE_FOLDER + UUID.randomUUID().toString() + ".pdf";
//create empty signature
PdfReader reader = new PdfReader(SRC);
FileOutputStream os = new FileOutputStream(temp);
PdfSigner stamper = new PdfSigner(reader, os, new StampingProperties());
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setPageRect(new Rectangle(36, 508, 254, 200));
appearance.setPageNumber(1);
appearance.setLayer2FontSize(14f);
stamper.setFieldName(fieldName);
appearance.setReason("Test GS Jose");
appearance.setLocation("GlobalSign Belgium");
IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.Adobe_PPKLite,
PdfName.Adbe_pkcs7_detached);
stamper.signExternalContainer(external, 8192);
//OCSP
byte[] oc2 = Base64.getDecoder().decode(oc1);
OCSPResp ocspResp = new OCSPResp(oc2);
IExternalSignatureContainer gsContainer = new MyExternalSignatureContainer(id, access, chain, ocspResp);
FileOutputStream os1 = new FileOutputStream(DEST);
PdfSigner signer = new PdfSigner(new PdfReader(temp), os1, new StampingProperties());
PdfSigner.signDeferred(signer.getDocument(), fieldName, os1, gsContainer);
addLTV(DEST, LTV, new OcspClientBouncyCastle(null), new CrlClientOnline(), LtvVerification.Level.OCSP_CRL, LtvVerification.Level.OCSP_CRL);
// Files.deleteIfExists(Paths.get(temp)); //by some reason itext does not release lock
// Files.deleteIfExists(Paths.get(DEST));
System.out.println("GS Finished");
}
static class MyExternalSignatureContainer implements IExternalSignatureContainer {
protected final String id;
private final Certificate[] chain;
private final JSONObject access;
private OCSPResp ocspResp;
public MyExternalSignatureContainer(String id, JSONObject access, Certificate[] chain, OCSPResp ocspResp) {
this.id = id;
this.access = access;
this.chain = chain;
this.ocspResp = ocspResp;
}
public void modifySigningDictionary(PdfDictionary arg0) {
}
public byte[] sign(InputStream arg0) {
try {
BasicOCSPResp basicResp = (BasicOCSPResp) ocspResp.getResponseObject();
byte[] oc = basicResp.getEncoded();
Collection<byte[]> ocspCollection = Collections.singletonList(oc);
String hashAlgorithm = "SHA256";
BouncyCastleDigest digest = new BouncyCastleDigest();
PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, digest, false);
byte[] hash = DigestAlgorithms.digest(arg0, digest.getMessageDigest(hashAlgorithm));
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, PdfSigner.CryptoStandard.CADES, ocspCollection,
null);
//create sha256 message digest
sh = MessageDigest.getInstance("SHA-256").digest(sh);
//create hex encoded sha256 message digest
String hexencodedDigest = new BigInteger(1, sh).toString(16);
hexencodedDigest = hexencodedDigest.toUpperCase();
JSONObject signed = ApiConnect.sign(baseURL, id, hexencodedDigest, access);
String sig = (String) signed.get("signature");
//decode hex signature
byte[] dsg = Hex.decodeHex(sig.toCharArray());
//include signature on PDF
sgn.setExternalDigest(dsg, null, "RSA");
//create TimeStamp Client
ITSAClient tsc = new DSSTSAClient(access);
return sgn.getEncodedPKCS7(hash, PdfSigner.CryptoStandard.CADES, tsc, ocspCollection, null);
} catch (DecoderException | IOException | ParseException | GeneralSecurityException | OCSPException de) {
throw new RuntimeException(de);
}
}
}
public static class GSConfig {
public String getApiSecret() {
return "00000000000000000000000000";
}
public String getApiKey() {
return "000000000";
}
public String getKeyPassword() {
return "yourJKSpassword";
}
public String sslCertificatePath() {
return "src/main/resources/yourjks.jks";
}
}
}
Editor is loading...