OCA reporting engine fork for dev and update.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
13 KiB

  1. import java.io.BufferedReader;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.io.InputStreamReader;
  8. import java.net.URL;
  9. import java.net.URLDecoder;
  10. import java.security.CodeSource;
  11. import java.security.KeyStore;
  12. import java.security.KeyStoreException;
  13. import java.security.NoSuchAlgorithmException;
  14. import java.security.PrivateKey;
  15. import java.security.Provider;
  16. import java.security.ProviderException;
  17. import java.security.Security;
  18. import java.security.UnrecoverableKeyException;
  19. import java.security.cert.Certificate;
  20. import java.security.cert.CertificateException;
  21. import java.util.NoSuchElementException;
  22. import java.util.ResourceBundle;
  23. import sun.security.pkcs11.SunPKCS11;
  24. import com.lowagie.text.pdf.PdfReader;
  25. import com.lowagie.text.pdf.PdfSignatureAppearance;
  26. import com.lowagie.text.pdf.PdfStamper;
  27. /*
  28. import com.itextpdf.text.pdf.PdfReader;
  29. import com.itextpdf.text.pdf.PdfSignatureAppearance;
  30. import com.itextpdf.text.pdf.PdfStamper;
  31. */
  32. /**
  33. *
  34. * @author Jan Peter Stotz
  35. *
  36. */
  37. public class JPdfSign {
  38. private static PrivateKey privateKey;
  39. private static Certificate[] certificateChain;
  40. private static ResourceBundle bundle = ResourceBundle.getBundle("strings");
  41. private static String PRODUCTNAME = bundle.getString("productname");
  42. private static String VERSION = bundle.getString("version");
  43. private static String JAR_FILENAME = bundle.getString("jar-filename");
  44. public static void main(String[] args) {
  45. // for (int i = 0; i < args.length; i++) {
  46. // System.out.println("arg[" + i + "] :" + args[i]);
  47. // }
  48. if (args.length < 2)
  49. showUsage();
  50. try {
  51. String pkcs12FileName = args[0].trim();
  52. String pdfInputFileName = args[1];
  53. String pdfOutputFileName = args[2];
  54. boolean usePKCS12 = !(pkcs12FileName.equals("-PKCS11"));
  55. String passwdfile = "";
  56. if (args.length == 4) {
  57. passwdfile = args[3];
  58. }
  59. // System.out.println("");
  60. // System.out.println("pdfInputFileName : " + pdfInputFileName);
  61. // System.out.println("pdfOutputFileName: " + pdfOutputFileName);
  62. if (usePKCS12)
  63. readPrivateKeyFromPKCS12(pkcs12FileName, passwdfile);
  64. else
  65. readPrivateKeyFromPKCS11();
  66. PdfReader reader = null;
  67. try {
  68. reader = new PdfReader(pdfInputFileName);
  69. } catch (IOException e) {
  70. System.err
  71. .println("An unknown error accoured while opening the input PDF file: \""
  72. + pdfInputFileName + "\"");
  73. e.printStackTrace();
  74. System.exit(-1);
  75. }
  76. FileOutputStream fout = null;
  77. try {
  78. fout = new FileOutputStream(pdfOutputFileName);
  79. } catch (FileNotFoundException e) {
  80. System.err
  81. .println("An unknown error accoured while opening the output PDF file: \""
  82. + pdfOutputFileName + "\"");
  83. e.printStackTrace();
  84. System.exit(-1);
  85. }
  86. PdfStamper stp = null;
  87. try {
  88. stp = PdfStamper.createSignature(reader, fout, '\0', null, true);
  89. PdfSignatureAppearance sap = stp.getSignatureAppearance();
  90. sap.setCrypto(privateKey, certificateChain, null, PdfSignatureAppearance.WINCER_SIGNED);
  91. // sap.setCrypto(privateKey, certificateChain, null, null);
  92. // sap.setReason("I'm the author");
  93. // sap.setLocation("Lisbon");
  94. // sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1,
  95. // null);
  96. sap.setCertified(true);
  97. stp.close();
  98. } catch (Exception e) {
  99. System.err
  100. .println("An unknown error accoured while signing the PDF file:");
  101. e.printStackTrace();
  102. System.exit(-1);
  103. }
  104. } catch (KeyStoreException kse) {
  105. System.err
  106. .println("An unknown error accoured while initializing the KeyStore instance:");
  107. kse.printStackTrace();
  108. System.exit(-1);
  109. }
  110. }
  111. private static void readPrivateKeyFromPKCS11() throws KeyStoreException {
  112. // Initialize PKCS#11 provider from config file
  113. String configFileName = getConfigFilePath("pkcs11.cfg");
  114. Provider p = null;
  115. try {
  116. p = new SunPKCS11(configFileName);
  117. Security.addProvider(p);
  118. } catch (ProviderException e) {
  119. System.err
  120. .println("Unable to load PKCS#11 provider with config file: "
  121. + configFileName);
  122. e.printStackTrace();
  123. System.exit(-1);
  124. }
  125. String pkcs11PIN = "000000";
  126. System.out.print("Please enter the smartcard pin: ");
  127. try {
  128. BufferedReader in = new BufferedReader(new InputStreamReader(
  129. System.in));
  130. pkcs11PIN = in.readLine();
  131. // System.out.println(pkcs11PIN);
  132. // System.out.println(pkcs11PIN.length());
  133. } catch (Exception e) {
  134. System.err
  135. .println("An unknown error accoured while reading the PIN:");
  136. e.printStackTrace();
  137. System.exit(-1);
  138. }
  139. KeyStore ks = null;
  140. try {
  141. ks = KeyStore.getInstance("pkcs11", p);
  142. ks.load(null, pkcs11PIN.toCharArray());
  143. } catch (NoSuchAlgorithmException e) {
  144. System.err
  145. .println("An unknown error accoured while reading the PKCS#11 smartcard:");
  146. e.printStackTrace();
  147. System.exit(-1);
  148. } catch (CertificateException e) {
  149. System.err
  150. .println("An unknown error accoured while reading the PKCS#11 smartcard:");
  151. e.printStackTrace();
  152. System.exit(-1);
  153. } catch (IOException e) {
  154. System.err
  155. .println("An unknown error accoured while reading the PKCS#11 smartcard:");
  156. e.printStackTrace();
  157. System.exit(-1);
  158. }
  159. String alias = "";
  160. try {
  161. alias = (String) ks.aliases().nextElement();
  162. privateKey = (PrivateKey) ks.getKey(alias, pkcs11PIN.toCharArray());
  163. } catch (NoSuchElementException e) {
  164. System.err
  165. .println("An unknown error accoured while retrieving the private key:");
  166. System.err
  167. .println("The selected PKCS#12 file does not contain any private keys.");
  168. e.printStackTrace();
  169. System.exit(-1);
  170. } catch (NoSuchAlgorithmException e) {
  171. System.err
  172. .println("An unknown error accoured while retrieving the private key:");
  173. e.printStackTrace();
  174. System.exit(-1);
  175. } catch (UnrecoverableKeyException e) {
  176. System.err
  177. .println("An unknown error accoured while retrieving the private key:");
  178. e.printStackTrace();
  179. System.exit(-1);
  180. }
  181. certificateChain = ks.getCertificateChain(alias);
  182. }
  183. protected static void readPrivateKeyFromPKCS12(String pkcs12FileName, String pwdFile)
  184. throws KeyStoreException {
  185. String pkcs12Password = "";
  186. KeyStore ks = null;
  187. if (!pwdFile.equals("")) {
  188. try {
  189. FileInputStream pwdfis = new FileInputStream(pwdFile);
  190. byte[] pwd = new byte[1024];
  191. try {
  192. do {
  193. int r = pwdfis.read(pwd);
  194. if (r < 0) {
  195. break;
  196. }
  197. pkcs12Password += new String(pwd);
  198. pkcs12Password = pkcs12Password.trim();
  199. } while (pwdfis.available() > 0);
  200. pwdfis.close();
  201. } catch (IOException ex) {
  202. System.err
  203. .println("Can't read password file: " + pwdFile);
  204. }
  205. } catch (FileNotFoundException fnfex) {
  206. System.err
  207. .println("Password file not found: " + pwdFile);
  208. }
  209. } else {
  210. System.out.print("Please enter the password for \"" + pkcs12FileName
  211. + "\": ");
  212. try {
  213. BufferedReader in = new BufferedReader(new InputStreamReader(
  214. System.in));
  215. pkcs12Password = in.readLine();
  216. } catch (Exception e) {
  217. System.err
  218. .println("An unknown error accoured while reading the password:");
  219. e.printStackTrace();
  220. System.exit(-1);
  221. }
  222. }
  223. try {
  224. ks = KeyStore.getInstance("pkcs12");
  225. ks.load(new FileInputStream(pkcs12FileName), pkcs12Password
  226. .toCharArray());
  227. } catch (NoSuchAlgorithmException e) {
  228. System.err
  229. .println("An unknown error accoured while reading the PKCS#12 file:");
  230. e.printStackTrace();
  231. System.exit(-1);
  232. } catch (CertificateException e) {
  233. System.err
  234. .println("An unknown error accoured while reading the PKCS#12 file:");
  235. e.printStackTrace();
  236. System.exit(-1);
  237. } catch (FileNotFoundException e) {
  238. System.err.println("Unable to open the PKCS#12 keystore file \""
  239. + pkcs12FileName + "\":");
  240. System.err
  241. .println("The file does not exists or missing read permission.");
  242. System.exit(-1);
  243. } catch (IOException e) {
  244. System.err
  245. .println("An unknown error accoured while reading the PKCS#12 file:");
  246. e.printStackTrace();
  247. System.exit(-1);
  248. }
  249. String alias = "";
  250. try {
  251. alias = (String) ks.aliases().nextElement();
  252. privateKey = (PrivateKey) ks.getKey(alias, pkcs12Password
  253. .toCharArray());
  254. } catch (NoSuchElementException e) {
  255. System.err
  256. .println("An unknown error accoured while retrieving the private key:");
  257. System.err
  258. .println("The selected PKCS#12 file does not contain any private keys.");
  259. e.printStackTrace();
  260. System.exit(-1);
  261. } catch (NoSuchAlgorithmException e) {
  262. System.err
  263. .println("An unknown error accoured while retrieving the private key:");
  264. e.printStackTrace();
  265. System.exit(-1);
  266. } catch (UnrecoverableKeyException e) {
  267. System.err
  268. .println("An unknown error accoured while retrieving the private key:");
  269. e.printStackTrace();
  270. System.exit(-1);
  271. }
  272. certificateChain = ks.getCertificateChain(alias);
  273. }
  274. protected static String getConfigFilePath(String configFilename) {
  275. CodeSource source = JPdfSign.class.getProtectionDomain()
  276. .getCodeSource();
  277. URL url = source.getLocation();
  278. String jarPath = URLDecoder.decode(url.getFile());
  279. File f = new File(jarPath);
  280. try {
  281. jarPath = f.getCanonicalPath();
  282. } catch (IOException e) {
  283. }
  284. if (!f.isDirectory()) {
  285. f = new File(jarPath);
  286. jarPath = f.getParent();
  287. }
  288. System.out.println(jarPath);
  289. if (jarPath.length() > 0) {
  290. return jarPath + File.separator + configFilename;
  291. } else
  292. return configFilename;
  293. }
  294. public static void showUsage() {
  295. System.out.println("jPdfSign v" + VERSION
  296. + " by Jan Peter Stotz - jpstotz@gmx.de\n");
  297. System.out.println(PRODUCTNAME + " usage:");
  298. System.out
  299. .println("\nFor using a PKCS#12 (.p12) file as signature certificate and private key source:");
  300. System.out.print("\tjava -jar " + JAR_FILENAME);
  301. System.out
  302. .println(" pkcs12FileName pdfInputFileName pdfOutputFileName");
  303. System.out
  304. .println("\nFor using a PKCS#11 smartcard as signature certificate and private key source:");
  305. System.out.print("\tjava -jar" + JAR_FILENAME);
  306. System.out.println(" -PKCS11 pdfInputFileName pdfOutputFileName");
  307. System.exit(0);
  308. }
  309. }