📄 guitest.java
字号:
/** * j4sign - an open, multi-platform digital signature solution * Copyright (c) 2004 Roberto Resoli - Servizio Sistema Informativo - Comune di Trento. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * *//* * $Header: /cvsroot/j4sign/j4sign/src/java/core/it/trento/comune/j4sign/examples/GUITest.java,v 1.3 2005/09/09 06:42:10 resoli Exp $ * $Revision: 1.3 $ * $Date: 2005/09/09 06:42:10 $ */package it.trento.comune.j4sign.examples;import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;import it.trento.comune.j4sign.cms.ExternalSignatureCMSSignedDataGenerator;import it.trento.comune.j4sign.cms.ExternalSignatureSignerInfoGenerator;import it.trento.comune.j4sign.pcsc.CardInfo;import it.trento.comune.j4sign.pcsc.PCSCHelper;import java.awt.*;import javax.swing.*;import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;import org.bouncycastle.cms.CMSException;import org.bouncycastle.cms.CMSProcessable;import org.bouncycastle.cms.CMSProcessableByteArray;import org.bouncycastle.cms.CMSSignedData;import org.bouncycastle.cms.CMSSignedDataGenerator;import org.bouncycastle.cms.SignerInformation;import org.bouncycastle.cms.SignerInformationStore;import org.bouncycastle.jce.provider.BouncyCastleProvider;import java.io.*;import java.security.*;import java.security.cert.CertStore;import java.security.cert.CertStoreException;import java.security.cert.CertificateEncodingException;import java.security.cert.CertificateException;import java.security.cert.CertificateExpiredException;import java.security.cert.CertificateNotYetValidException;import java.security.cert.CollectionCertStoreParameters;import java.security.cert.X509Certificate;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import java.util.Map;import java.util.Properties;/** * A graphical user interface program for testing the generation of a CMS signed * message, using a pkcs11 token (usually a SmartCard). This examples shows a * simple method for signing text files; other file types are explicitly * excluded because we want avoid to manage here complex issues related to file * visualization. <br> * The italian law states clearly that the signing procedure has to make aware * the signer of the content being signed. Signing files that contains macros or * other procedures that can dinamically modify the visualization of the content * is also explicitely prohibithed. <br> * As a good rule, we should sign only a content we know and comprehend * completely. <br> * For this reason, we also STRONGLY SUGGEST NOT TO SIGN proprietary file * formats. <br> * Threads and timers are used in this example are used to enhance user * interface, permitting live logging of signing procedure and the use of a * progress bar. * <p> * Multiple signatures are permitted, each with different token types; the * generated CMS message keeps signers informations at the same level (similar * to a paper document with multiple signatures). I call this arrangement * "combined signatures", in contrast with "nested signatures" (like a signed * paper document put in a signed envelope). * <p> * <b>N.B. note that in this example signature verification only ensures signed * data integrity; a complete verification to ensure non-repudiation requires * checking the full certification path including the CA root certificate, and * CRL verification on the CA side. <br> * (Good stuff for a next release ...) </b> * * @author Roberto Resoli */public class GUITest extends JFrame implements java.awt.event.ActionListener { private JTextArea logArea = null; private JTextArea dataArea = null; private JPasswordField pwd = null; private DigestSignTask task = null; private Timer timer = null; private JButton f = null; private JButton c = null; private JButton s = null; private JProgressBar progressBar = null; boolean debug = false; boolean submitAfterSigning = false; private byte[] bytesToSign = null; private String encodedDigest = null; private byte[] encryptedDigest; private java.io.PrintStream log = null; public final static int ONE_SECOND = 1000; private java.lang.String cryptokiLib = null; private java.lang.String signerLabel = null; private byte[] certificate = null; private CMSProcessable msg = null; private ExternalSignatureCMSSignedDataGenerator cmsGenerator = null; private ExternalSignatureSignerInfoGenerator signerInfoGenerator = null; private ArrayList signersCertList = null; private File fileToSign = null; private boolean forcingCryptoki = false; private static String PROPERTIES_FILE = "clitest.properties"; private boolean makeDigestOnToken = true; private String digestAlg = CMSSignedDataGenerator.DIGEST_SHA1; private String encAlg = CMSSignedDataGenerator.ENCRYPTION_RSA; /** * @return Returns the forcingCryptoki. */ public boolean isForcingCryptoki() { return forcingCryptoki; } private void loadProperties() { Properties props = new Properties(); String propertiesFile = PROPERTIES_FILE; System.out.println("Trying to load properties from: '" + propertiesFile + "'"); try { InputStream in = getClass().getResourceAsStream( "/" + propertiesFile); if (in != null) { props.load(in); in.close(); } else System.out.println("'" + propertiesFile + "' not found!"); } catch (IOException e) { System.out.println(e); } if (props.size() > 0) { Iterator i = props.entrySet().iterator(); System.out.println("loaded properties:"); while (i.hasNext()) { Map.Entry me = (Map.Entry) i.next(); System.out.println((me.getKey().toString() + ": " + me .getValue())); } if (props.getProperty("digest.algorithm") != null) this.digestAlg = props.getProperty("digest.algorithm"); if (props.getProperty("digest.ontoken") != null) this.makeDigestOnToken = Boolean.valueOf( props.getProperty("digest.ontoken")).booleanValue(); if (props.getProperty("encryption.algorithm") != null) this.encAlg = props.getProperty("encryption.algorithm"); } } /** * The class constructor. * * @param title , * shown on the window title bar. * @param aDebug * if True, causes operation log to be shown in the GUI, in a * dedicated pane. * @throws java.awt.HeadlessException */ public GUITest(String title, String aDebug, String aCryptoki) throws HeadlessException { super(title); System.out.println("Initializing GUITest ..."); System.out.println("Loading properties ..."); loadProperties(); if (aDebug != null) this.debug = Boolean.valueOf(aDebug).booleanValue(); if (aCryptoki != null) { this.cryptokiLib = aCryptoki; this.forcingCryptoki = true; } System.out.println("\nUsing cryptoki:\t" + getCryptokiLib()); System.out.println("Using signer:\t" + getSignerLabel() + "\n"); getContentPane().setLayout(new BorderLayout()); if (!debug) log = System.out; else { logArea = new JTextArea(); logArea.setFont(new Font("Monospaced", Font.PLAIN, 12)); log = new PrintStream(new JTextAreaOutputStream(logArea), true); dataArea = new JTextArea(); JPanel dataAreaPanel = new JPanel(); dataAreaPanel.setLayout(new BorderLayout()); dataAreaPanel.add(dataArea, BorderLayout.CENTER); dataAreaPanel.add(new JLabel("Put down here the text to sign:"), BorderLayout.NORTH); f = new JButton("Load File"); f.setEnabled(true); c = new JButton("Save Certificate"); c.setEnabled(false); s = new JButton("Save Signed File"); s.setEnabled(false); f.addActionListener(this); c.addActionListener(this); s.addActionListener(this); JScrollPane logScrollPane = new JScrollPane(logArea); JScrollPane dataScrollPane = new JScrollPane(dataAreaPanel); JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, logScrollPane, dataScrollPane); splitPane.setOneTouchExpandable(true); splitPane.setDividerLocation(200); //splitPane.setDividerLocation(0); //Provide minimum sizes for the two components in the split pane /* * Dimension minimumSize = new Dimension(100, 50); * logScrollPane.setMinimumSize(minimumSize); * dataScrollPane.setMinimumSize(minimumSize); */ //Provide a preferred size for the split pane splitPane.setPreferredSize(new Dimension(400, 200)); getContentPane().add(splitPane, BorderLayout.CENTER); } pwd = new JPasswordField(); pwd.setPreferredSize(new Dimension(50, 20)); pwd.addActionListener(this); JPanel southPanel = new JPanel(); southPanel.setLayout(new BoxLayout(southPanel, BoxLayout.Y_AXIS)); JPanel controlsPanel = new JPanel(); JPanel statusPanel = new JPanel(); statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.X_AXIS)); controlsPanel.add(pwd); if (debug) { controlsPanel.add(f); controlsPanel.add(s); controlsPanel.add(c); } progressBar = new JProgressBar(); progressBar.setStringPainted(false); progressBar.setStringPainted(true); setStatus(DigestSignTask.RESET, "Inserire il pin e battere INVIO per firmare."); statusPanel.add(progressBar); southPanel.add(controlsPanel); southPanel.add(statusPanel); getContentPane().add(southPanel, debug ? BorderLayout.SOUTH : BorderLayout.CENTER); //retrive data to sign from html form. //retriveEncodedDigestFromForm(); /* * //Create a new sign task. task = new DigestSignTask(getCryptokiLib(), * getSignerLabel(), log); //Create a timer. timer = new * Timer(ONE_SECOND, new java.awt.event.ActionListener() { public void * actionPerformed(java.awt.event.ActionEvent evt) { * setStatus(task.getCurrent(), task.getMessage()); if (task.done()) { * timer.stop(); progressBar.setValue(progressBar.getMinimum()); if * (task.getCurrent() == DigestSignTask.SIGN_DONE) { * Toolkit.getDefaultToolkit().beep(); * setEncryptedDigest(task.getEncryptedDigest()); * returnEncryptedDigestToForm(); setCertificate(task.getCertificate()); * returnCertificateToForm(); if (getSubmitAfterSigning()) { * submitForm(); } } enableControls(true); } } }); */ //dataArea.setText(decode(getEncodedData())); } public static void main(String[] args) { Security.insertProviderAt(new BouncyCastleProvider(), 3); String cryptoki = (args.length == 1) ? args[0] : null; GUITest frame = new GUITest("j4sign GUI Test", "true", cryptoki); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(600, 400); //frame.pack(); Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); frame.setLocation((d.width - frame.getWidth()) / 2, (d.height - frame .getHeight()) / 2); frame.show(); } /** * Prepares a signing procedure. * * @param digestAlg * @param encryptionAlg * @param digestOnToken * @throws InvalidKeyException * @throws CertificateEncodingException * @throws SignatureException * @throws NoSuchProviderException * @throws NoSuchAlgorithmException * @throws IOException * @throws CMSException */ private void openSignature(String digestAlg, String encryptionAlg, boolean digestOnToken) throws InvalidKeyException, CertificateEncodingException, SignatureException, NoSuchProviderException, NoSuchAlgorithmException, IOException, CMSException { this.msg = new CMSProcessableByteArray(dataArea.getText().getBytes( "UTF8")); this.cmsGenerator = new ExternalSignatureCMSSignedDataGenerator(); this.signersCertList = new ArrayList(); this.signerInfoGenerator = new ExternalSignatureSignerInfoGenerator( digestAlg, encryptionAlg); this.bytesToSign = this.signerInfoGenerator.getBytesToSign( PKCSObjectIdentifiers.data, msg, "BC"); if (!digestOnToken) { log.println("\nCalculating digest ...\n"); MessageDigest md = MessageDigest.getInstance(digestAlg); md.update(bytesToSign); byte[] digest = md.digest(); log.println("digestAlg digest:\n" + formatAsHexString(digest)); log.println("Done."); setEncodedDigest(encodeFromBytes(digest)); } } /** * Terminates the signing procedure creating the signer information data * structure. * * @throws CertificateException */ private void closeSignature() throws CertificateException { if ((getCertificate() != null) && (getEncryptedDigest() != null)) { log.println("======== Encryption completed ========="); log.println("Encrypted Digest bytes:\n" + formatAsHexString(getEncryptedDigest())); log.println("Certificate bytes:\n" + formatAsHexString(getCertificate())); //get Certificate java.security.cert.CertificateFactory cf = java.security.cert.CertificateFactory .getInstance("X.509"); java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream( getCertificate()); java.security.cert.X509Certificate javaCert = (java.security.cert.X509Certificate) cf .generateCertificate(bais); this.signerInfoGenerator.setCertificate(javaCert); this.signerInfoGenerator.setSignedBytes(getEncryptedDigest()); this.cmsGenerator.addSignerInf(this.signerInfoGenerator); this.signersCertList.add(javaCert); s.setEnabled(true); c.setEnabled(true); } } /** * Creates the signed data structure, using signer infos precedently * accumulated. * * @return * @throws CertStoreException * @throws InvalidAlgorithmParameterException * @throws CertificateExpiredException * @throws CertificateNotYetValidException * @throws NoSuchAlgorithmException * @throws NoSuchProviderException * @throws CMSException */ private CMSSignedData buildCMSSignedData() throws CertStoreException, InvalidAlgorithmParameterException, CertificateExpiredException, CertificateNotYetValidException, NoSuchAlgorithmException, NoSuchProviderException, CMSException { CMSSignedData s = null; if (this.signersCertList.size() != 0) { //Per passare i certificati al generatore li si incapsula // in un // CertStore. CertStore store = CertStore.getInstance("Collection", new CollectionCertStoreParameters(this.signersCertList), "BC"); log.println("Adding certificates ... "); this.cmsGenerator.addCertificatesAndCRLs(store); //Finalmente, si pu� creare il l'oggetto CMS. log.println("Generating CMSSignedData "); s = this.cmsGenerator.generate(this.msg, true); //Verifica log.println("\nStarting CMSSignedData verification ... "); //recupero dal CMS la lista dei certificati CertStore certs = s.getCertificatesAndCRLs("Collection", "BC"); //Recupero i firmatari. SignerInformationStore signers = s.getSignerInfos(); Collection c = signers.getSigners(); log.println(c.size() + " signers found."); Iterator it = c.iterator(); //ciclo tra tutti i firmatari int i = 0; while (it.hasNext()) { SignerInformation signer = (SignerInformation) it.next(); Collection certCollection = certs.getCertificates(signer .getSID()); if (certCollection.size() == 1) { //Iterator certIt = certCollection.iterator(); //X509Certificate cert = (X509Certificate) // certIt.next(); X509Certificate cert = (X509Certificate) certCollection .toArray()[0]; log.println(i + ") Verifiying signature from:\n" + cert.getSubjectDN()); /* * log.println("Certificate follows:"); * log.println("===================================="); * log.println(cert); * log.println("===================================="); */ if (signer.verify(cert, "BC")) { log.println("SIGNATURE " + i + " OK!"); } else System.err.println("SIGNATURE " + i + " Failure!"); } else System.out .println("There is not exactly one certificate for this signer!"); i++; } } return s; } /** * The "control center" of the class, mandatory to satisfy the * java.awt.event.ActionListener interface contract. * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(java.awt.event.ActionEvent e) { try { setStatus(DigestSignTask.RESET, ""); //sign action if (e.getSource() == pwd) { initStatus(0, DigestSignTask.SIGN_MAXIMUM); if (detectCardAndCriptoki()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -