# HG changeset patch # User nolith # Date 1181347242 -7200 # Branch trunk # Node ID 0d720da477e5011733498441d9b46db6c60893be # Parent 825ce43906de01000c116c9608d47ef37ee92b09 [svn] Initial import. diff -r 825ce43906de01000c116c9608d47ef37ee92b09 -r 0d720da477e5011733498441d9b46db6c60893be src/org/abisso/PortableNotary/Messages.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/abisso/PortableNotary/Messages.java Sat Jun 09 02:00:42 2007 +0200 @@ -0,0 +1,22 @@ +package org.abisso.PortableNotary; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class Messages { + private static final String BUNDLE_NAME = "org.abisso.PortableNotary.messages"; //$NON-NLS-1$ + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + private Messages() { + } + + public static String getString(String key) { + try { + return RESOURCE_BUNDLE.getString(key); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} diff -r 825ce43906de01000c116c9608d47ef37ee92b09 -r 0d720da477e5011733498441d9b46db6c60893be src/org/abisso/PortableNotary/Notary.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/abisso/PortableNotary/Notary.java Sat Jun 09 02:00:42 2007 +0200 @@ -0,0 +1,180 @@ +package org.abisso.PortableNotary; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Enumeration; +import java.util.NoSuchElementException; + +import com.lowagie.text.pdf.AcroFields; +import com.lowagie.text.pdf.PdfPKCS7; +import com.lowagie.text.pdf.PdfReader; + +public class Notary { + + static private String replaceBoolean(String str) { + str = str.replace("true", + Messages.getString("Notary.True") ) + .replace("false", + Messages.getString("Notary.False")); + return str; + } + + static void println(boolean verbose, String str) { + if (verbose) + System.out.println(replaceBoolean(str)); + } + + static void printf(boolean verbose, String str, Object ... args ) { + if (verbose) + System.out.printf(str,args); + } + + static boolean check(String certdb, String signed_doc, char[] password, boolean verbose) { + KeyStore kall; + try { + kall = KeyStore.getInstance(KeyStore.getDefaultType()); + File keystore = new File(certdb); + kall.load(new FileInputStream(keystore), password); + } catch (CertificateException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + return false; + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + PdfReader reader; + try { + reader = new PdfReader(signed_doc); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + AcroFields af = reader.getAcroFields(); + ArrayList names = af.getSignatureNames(); + for (int k = 0; k < names.size(); ++k) { + String name = (String)names.get(k); + println(verbose, Messages.getString("Notary.SignatureName") + name); //$NON-NLS-1$ + println(verbose, + Messages.getString("Notary.SignatuteCoversWholeDocument") + af.signatureCoversWholeDocument(name)); //$NON-NLS-1$ + printf(verbose, + Messages.getString("Notary.DecumentRevisionNOfM"), af.getRevision(name), //$NON-NLS-1$ + af.getTotalRevisions()); + + PdfPKCS7 pk = af.verifySignature(name); + Calendar cal = pk.getSignDate(); + Certificate pkc[] = pk.getCertificates(); + println(true, + Messages.getString("Notary.Subject") + + PdfPKCS7.getSubjectFields(pk.getSigningCertificate())); //$NON-NLS-1$ + try { + println(true, Messages.getString("Notary.DocumentModified") + !pk.verify()); //$NON-NLS-1$ + } catch (SignatureException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + for( int i = 0; i < pkc.length; i++) { + try { + Enumeration aliases = kall.aliases(); + while(true) { + String alias = aliases.nextElement(); + if (kall.getCertificate(alias).getPublicKey().equals( + pkc[i].getPublicKey()) ) + println(true, Messages.getString("Notary.TrustedSignature")); //$NON-NLS-1$ + } + } catch (KeyStoreException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchElementException e) { + break; + } + + + + } + Object fails[] = PdfPKCS7.verifyCertificates(pkc, kall, null, cal); + if (fails == null) { + println(true, Messages.getString("Notary.CertificateVerified")); //$NON-NLS-1$ + return true; + }else { + println(true, Messages.getString("Notary.CertificateFailed") + fails[1]); //$NON-NLS-1$ + return false; + } + } + return false; + } + + static boolean extractRevision(String extraction_path, String signed_doc, boolean verbose){ + PdfReader reader; + try { + reader = new PdfReader(signed_doc); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + AcroFields af = reader.getAcroFields(); + ArrayList names = af.getSignatureNames(); + printf(verbose, "%d revision(s) found.", names.size()); + for (int k = 0; k < names.size(); ++k) { + String name = (String)names.get(k); +// Start revision extraction + FileOutputStream out; + try { + out = new FileOutputStream(extraction_path+ + "revision_" + af.getRevision(name) + ".pdf"); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + byte bb[] = new byte[8192]; + InputStream ip; + try { + ip = af.extractRevision(name); + + int n = 0; + while ((n = ip.read(bb)) > 0) + out.write(bb, 0, n); + out.close(); + ip.close(); + println(verbose, Messages.getString("Notary.RevisionExtracted") + + "revision_" + af.getRevision(name) + ".pdf"); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + // End revision extraction + + } + return true; + } + +} diff -r 825ce43906de01000c116c9608d47ef37ee92b09 -r 0d720da477e5011733498441d9b46db6c60893be src/org/abisso/PortableNotary/PortableNotary.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/abisso/PortableNotary/PortableNotary.java Sat Jun 09 02:00:42 2007 +0200 @@ -0,0 +1,114 @@ +package org.abisso.PortableNotary; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.OptionBuilder; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.PosixParser; + +public class PortableNotary { + + private static final short NO_ERROR = 0; + private static final short LEGACY_JVM = 1; + private static final short WRONG_PARAMS_NUMBER = 2; + private static final short WRONG_PARAMS = 3; + + /** + * @param args + */ + @SuppressWarnings("static-access") //$NON-NLS-1$ + public static void main(String[] args) { + +// create the command line parser + CommandLineParser parser = new PosixParser(); + +// create the Options + Options options = new Options(); + options.addOption( "S", "save-option", false, Messages.getString("PortableNotary.SaveAllOptions") ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + options.addOption( "P", "print-option", false, Messages.getString("PortableNotary.PrintAllOptions") ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + options.addOption( "v", false, "verbose" ); //$NON-NLS-1$ //$NON-NLS-2$ + options.addOption( "p", false, Messages.getString("PortableNotary.AskPassword") ); //$NON-NLS-1$ //$NON-NLS-2$ + options.addOption( "h", "help", false, Messages.getString("PortableNotary.PrintHelp")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + options.addOption( OptionBuilder.withLongOpt( "keystore" ) //$NON-NLS-1$ + .withArgName("PATH") //$NON-NLS-1$ + .withDescription( Messages.getString("PortableNotary.JavaKeystorePath") ) //$NON-NLS-1$ + .hasArg() + .create("k") ); //$NON-NLS-1$ + options.addOption( OptionBuilder.withLongOpt( "password" ) //$NON-NLS-1$ + .withArgName("PASS") //$NON-NLS-1$ + .withDescription( Messages.getString("PortableNotary.JavaKeystorePassword") ) //$NON-NLS-1$ + .hasArg() + .create() ); + + + HelpFormatter usage = new HelpFormatter(); + + Preferences pref = Preferences.getIstance(); + //my_usage(usage,options); + String file_path = ""; //$NON-NLS-1$ + String keystore_path = pref.getKeystore_path(); + char[] password = pref.getKeystore_pass().toCharArray(); + boolean verbose = false; + try { + // parse the command line arguments + CommandLine line = parser.parse( options, args ); + + if (line.hasOption("h")) { //$NON-NLS-1$ + my_usage(usage,options); + System.exit(NO_ERROR); + } + boolean save = line.hasOption("S"); //$NON-NLS-1$ + verbose = line.hasOption("v"); //$NON-NLS-1$ + // validate that keystore has been set + if( line.hasOption( "k" ) ) { //$NON-NLS-1$ + keystore_path = line.getOptionValue( "k" ); //$NON-NLS-1$ + if (save) + pref.setKeystore_path(keystore_path); + } + +// validate that keystore has been set + if( line.hasOption( "password" ) ) { //$NON-NLS-1$ + password= line.getOptionValue( "password" ).toCharArray(); //$NON-NLS-1$ + if (save) + pref.setKeystore_pass(password.toString()); + } + + if (line.hasOption("P") ) { //$NON-NLS-1$ + System.out.println(Messages.getString("PortableNotary.OptionsSaved")); //$NON-NLS-1$ + System.out.println("keystore="+pref.getKeystore_path()); //$NON-NLS-1$ + System.out.println("password="+pref.getKeystore_pass()); //$NON-NLS-1$ + } + + if (line.hasOption("p")) { //$NON-NLS-1$ + try { + password = System.console().readPassword(Messages.getString("PortableNotary.EnterPassword")); //$NON-NLS-1$ + }catch (Exception e) { + e.printStackTrace(System.err); + System.err.println(Messages.getString("PortableNotary.RequireJava6")); //$NON-NLS-1$ + System.exit(LEGACY_JVM); + } + } + if (line.getArgs().length != 1 && !line.hasOption("P")) { //$NON-NLS-1$ + my_usage(usage, options); + System.exit(WRONG_PARAMS_NUMBER); + }else if (line.getArgs().length == 1){ + file_path = line.getArgs()[0]; + Notary.check(keystore_path, file_path, password, verbose); + } + } + catch( ParseException exp ) { + System.out.println( Messages.getString("PortableNotary.UnexpectedException") + exp.getMessage() ); //$NON-NLS-1$ + my_usage(usage,options); + System.exit(WRONG_PARAMS); + } + + + } + + static void my_usage(HelpFormatter usage, Options options) { + usage.printHelp("PortableNotary [opts] filename",options); //$NON-NLS-1$ + } + +} diff -r 825ce43906de01000c116c9608d47ef37ee92b09 -r 0d720da477e5011733498441d9b46db6c60893be src/org/abisso/PortableNotary/Preferences.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/abisso/PortableNotary/Preferences.java Sat Jun 09 02:00:42 2007 +0200 @@ -0,0 +1,60 @@ +package org.abisso.PortableNotary; + + +public class Preferences { + + // public static java.util.Locale Language; + + private String keystore_path = ""; + private String keystore_pass = ""; + private java.util.prefs.Preferences prefs = java.util.prefs.Preferences.userNodeForPackage (PortableNotary.class); + + static Preferences istance = null; + + /** Creates a new instance of Preferences */ + protected Preferences() { + keystore_path = prefs.get("KeystorePath", System.getProperty("user.home") + + System.getProperty("file.separator") + ".keystore"); + keystore_pass = prefs.get("KeystorePass", ""); + } + + public static Preferences getIstance() { + if (istance==null) + istance = new Preferences(); + return istance; + } + + /** + * @return the keystore_pass + */ + public String getKeystore_pass() { + return keystore_pass; + } + + /** + * @param keystore_pass the keystore_pass to set + */ + public void setKeystore_pass(String keystore_pass) { + this.keystore_pass = keystore_pass; + prefs.put("KeystorePass", keystore_pass); + } + + /** + * @return the keystore_path + */ + public String getKeystore_path() { + return keystore_path; + } + + /** + * @param keystore_path the keystore_path to set + */ + public void setKeystore_path(String keystore_path) { + this.keystore_path = keystore_path; + prefs.put("KeystorePath", keystore_path); + } + + + + +} diff -r 825ce43906de01000c116c9608d47ef37ee92b09 -r 0d720da477e5011733498441d9b46db6c60893be src/org/abisso/PortableNotary/messages.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/abisso/PortableNotary/messages.properties Sat Jun 09 02:00:42 2007 +0200 @@ -0,0 +1,21 @@ +Notary.SignatureName=Signature name: +Notary.SignatuteCoversWholeDocument=Signature covers whole document: +Notary.DecumentRevisionNOfM=Document revision %d of %d\n +Notary.Subject=Subject: +Notary.DocumentModified=Document modified: +Notary.TrustedSignature=The signature certificate is trusted +Notary.CertificateVerified=Certificates verified against the KeyStore +Notary.CertificateFailed=Certificate failed: +Notary.True=true +Notary.False=false +Notary.RevisionExtracted=Revision extracted: +PortableNotary.SaveAllOptions=save all options in preferences +PortableNotary.PrintAllOptions=print all options in preferences +PortableNotary.AskPassword=ask for password (only Java 6) +PortableNotary.PrintHelp=print help (this page) +PortableNotary.JavaKeystorePath=java keystore path +PortableNotary.JavaKeystorePassword=java keystore password +PortableNotary.OptionsSaved=listing options saved in preferences +PortableNotary.EnterPassword=Enter password: +PortableNotary.RequireJava6=This option require Java 6 +PortableNotary.UnexpectedException=Unexpected exception: diff -r 825ce43906de01000c116c9608d47ef37ee92b09 -r 0d720da477e5011733498441d9b46db6c60893be src/org/abisso/PortableNotary/messages_it.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/abisso/PortableNotary/messages_it.properties Sat Jun 09 02:00:42 2007 +0200 @@ -0,0 +1,21 @@ +Notary.SignatureName=Nome della firma: +Notary.SignatuteCoversWholeDocument=La firma copre l'intero documento: +Notary.DecumentRevisionNOfM=Revisione %d di %d\n +Notary.Subject=Firma di: +Notary.DocumentModified=Documento modificato: +Notary.TrustedSignature=La firma del certificato è fidata +Notary.CertificateVerified=Verifica della certification autoriry effettuata +Notary.CertificateFailed=Verifica della certification autority fallita: +Notary.True=sì +Notary.False=no +Notary.RevisionExtracted=Estratta revisione: +PortableNotary.SaveAllOptions=salva tutte le opzioni nelle preferenze +PortableNotary.PrintAllOptions=stampa tutte le opzioni nelle preferenze +PortableNotary.AskPassword=chiadi la password (solo Java 6) +PortableNotary.PrintHelp=stampa l'aiuto (questa pagina) +PortableNotary.JavaKeystorePath=percorso del keystore java +PortableNotary.JavaKeystorePassword=password del keystore java +PortableNotary.OptionsSaved=Lista delle opzioni salvate nelle preferenze +PortableNotary.EnterPassword=Inserire la password: +PortableNotary.RequireJava6=Questa opzione richiede Java 6 +PortableNotary.UnexpectedException=Eccezione inaspettata: