public class GUITest
extends javax.swing.JFrame
implements java.awt.event.ActionListener, javax.swing.event.DocumentListener
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).
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.
(Good stuff for a next release ...)
javax.swing.JFrame.AccessibleJFramejava.awt.Window.AccessibleAWTWindow, java.awt.Window.Type| Modifier and Type | Field and Description |
|---|---|
private byte[] |
bytesToSign |
private javax.swing.JButton |
c |
private javax.swing.JTextArea |
certArea |
private byte[] |
certificate |
private FindCertTask |
certTask |
private ExternalSignatureCMSSignedDataGenerator |
cmsGenerator |
private java.lang.String |
cryptokiLib |
private javax.swing.JTextArea |
dataArea |
(package private) boolean |
debug |
private java.lang.String |
digestAlg |
private java.lang.String |
encAlg |
private java.lang.String |
encodedDigest |
private byte[] |
encryptedDigest |
private javax.swing.JButton |
f |
private java.io.File |
fileToSign |
private javax.swing.Timer |
findTimer |
private boolean |
forcingCryptoki |
private java.io.PrintStream |
log |
private javax.swing.JTextArea |
logArea |
private boolean |
makeDigestOnToken |
private org.bouncycastle.cms.CMSProcessable |
msg |
static int |
ONE_SECOND |
private javax.swing.JProgressBar |
progressBar |
private static java.lang.String |
PROPERTIES_FILE |
private javax.swing.JPasswordField |
pwd |
private javax.swing.JButton |
s |
private ExternalSignatureSignerInfoGenerator |
signerInfoGenerator |
private java.lang.String |
signerLabel |
private java.util.ArrayList |
signersCertList |
private DigestSignTask |
signTask |
private javax.swing.Timer |
signTimer |
(package private) boolean |
submitAfterSigning |
accessibleContext, EXIT_ON_CLOSE, rootPane, rootPaneCheckingEnabledCROSSHAIR_CURSOR, DEFAULT_CURSOR, E_RESIZE_CURSOR, HAND_CURSOR, ICONIFIED, MAXIMIZED_BOTH, MAXIMIZED_HORIZ, MAXIMIZED_VERT, MOVE_CURSOR, N_RESIZE_CURSOR, NE_RESIZE_CURSOR, NORMAL, NW_RESIZE_CURSOR, S_RESIZE_CURSOR, SE_RESIZE_CURSOR, SW_RESIZE_CURSOR, TEXT_CURSOR, W_RESIZE_CURSOR, WAIT_CURSORBOTTOM_ALIGNMENT, CENTER_ALIGNMENT, LEFT_ALIGNMENT, RIGHT_ALIGNMENT, TOP_ALIGNMENT| Constructor and Description |
|---|
GUITest(java.lang.String title,
java.lang.String aDebug,
java.lang.String aCryptoki)
The class constructor.
|
| Modifier and Type | Method and Description |
|---|---|
void |
actionPerformed(java.awt.event.ActionEvent e)
The "control center" of the class, mandatory to satisfy the
java.awt.event.ActionListener interface contract.
|
private long |
algToMechanism(boolean digestOnToken,
java.lang.String digestAlg,
java.lang.String encryptionAlg) |
private byte[] |
applyPkcs1Padding(int resultLength,
byte[] srcBytes) |
private org.bouncycastle.cms.CMSSignedData |
buildCMSSignedData()
Creates the signed data structure, using signer infos precedently
accumulated.
|
void |
changedUpdate(javax.swing.event.DocumentEvent e) |
private void |
closeSignature()
Terminates the signing procedure creating the signer information data
structure.
|
java.lang.String |
decode(java.lang.String s)
Decodes a base64 String in a normal Unicode string.
|
byte[] |
decodeToBytes(java.lang.String s)
Converts a base64 String in a byte array.
|
private boolean |
detectCardAndCriptoki()
This triggers the PCSC wrapper stuff; a
PCSCHelperclass is used
to detect reader and token presence, trying also to provide a candidate
PKCS#11 cryptoki for it. |
private void |
enableControls(boolean enable)
Enables GUI controls.
|
private byte[] |
encapsulateInDigestInfo(java.lang.String digestAlg,
byte[] digestBytes) |
java.lang.String |
encode(java.lang.String s)
Encodes a String into its base64 encoding version.
|
java.lang.String |
encodeFromBytes(byte[] bytes)
Creates the base64 encoding of a byte array.
|
private void |
findCert() |
(package private) java.lang.String |
formatAsHexString(byte[] bytes)
Converts a byte array in its exadecimal representation.
|
java.lang.String |
getAppletInfo()
Returns information about this applet.
|
byte[] |
getCertificate()
Returns the signer's certificate.
|
private java.lang.String |
getCryptokiLib()
Returns the cryptoki library name.
|
java.lang.String |
getEncodedDigest()
Returns the base64 encoding of the digest.
|
byte[] |
getEncryptedDigest()
Gets the digest encrypted with the private key of the signer.
|
java.io.File |
getFileToSign() |
java.security.cert.X509Certificate |
getJavaCertificate() |
private java.lang.String |
getSignerLabel()
Returns the label identifiyng the signer objects on the token.
|
private void |
initStatus(int min,
int max)
Resets the progress bar status.
|
void |
insertUpdate(javax.swing.event.DocumentEvent e) |
private boolean |
isDebugMode()
Tests if the program is in debug mode
|
boolean |
isForcingCryptoki() |
private boolean |
isTextFile(java.io.File f)
Tests if a file is a text file; this method probably works only in a
unicode system (fixme).
|
private void |
loadProperties() |
static void |
main(java.lang.String[] args) |
private void |
openSignature(java.lang.String digestAlg,
java.lang.String encryptionAlg,
boolean digestOnToken)
Prepares a signing procedure.
|
private void |
prepareDigestFromTextArea()
Takes text from data area and digests it.
|
void |
removeUpdate(javax.swing.event.DocumentEvent e) |
private void |
setCertificate(byte[] newCertificate)
Sets the signer certificate
|
private void |
setCryptokiLib(java.lang.String newCryptokiLib)
Sets the cryptoki library name.
|
void |
setEncodedDigest(java.lang.String data)
Sets the base64 encoded digest.
|
void |
setEncryptedDigest(byte[] newEncryptedDigest)
Sets the private-key encrypted digest
|
void |
setFileToSign(java.io.File fileToSign) |
private void |
setSignerLabel(java.lang.String newSignerLabel)
Sets the label identifiyng the signer objects on the token.
|
private void |
setStatus(int code,
java.lang.String statusString)
Sets the current status of the program (shown in the progress bar and
with alerts in case of error.
|
private void |
sign()
Starts a signing task in a separate thread.
|
addImpl, createRootPane, frameInit, getAccessibleContext, getContentPane, getDefaultCloseOperation, getGlassPane, getGraphics, getJMenuBar, getLayeredPane, getRootPane, getTransferHandler, isDefaultLookAndFeelDecorated, isRootPaneCheckingEnabled, paramString, processWindowEvent, remove, repaint, setContentPane, setDefaultCloseOperation, setDefaultLookAndFeelDecorated, setGlassPane, setIconImage, setJMenuBar, setLayeredPane, setLayout, setRootPane, setRootPaneCheckingEnabled, setTransferHandler, updateaddNotify, getCursorType, getExtendedState, getFrames, getIconImage, getMaximizedBounds, getMenuBar, getState, getTitle, isResizable, isUndecorated, remove, removeNotify, setBackground, setCursor, setExtendedState, setMaximizedBounds, setMenuBar, setOpacity, setResizable, setShape, setState, setTitle, setUndecoratedaddPropertyChangeListener, addPropertyChangeListener, addWindowFocusListener, addWindowListener, addWindowStateListener, applyResourceBundle, applyResourceBundle, createBufferStrategy, createBufferStrategy, dispose, getBackground, getBufferStrategy, getFocusableWindowState, getFocusCycleRootAncestor, getFocusOwner, getFocusTraversalKeys, getIconImages, getInputContext, getListeners, getLocale, getModalExclusionType, getMostRecentFocusOwner, getOpacity, getOwnedWindows, getOwner, getOwnerlessWindows, getShape, getToolkit, getType, getWarningString, getWindowFocusListeners, getWindowListeners, getWindows, getWindowStateListeners, hide, isActive, isAlwaysOnTop, isAlwaysOnTopSupported, isAutoRequestFocus, isFocusableWindow, isFocusCycleRoot, isFocused, isLocationByPlatform, isOpaque, isShowing, isValidateRoot, pack, paint, postEvent, processEvent, processWindowFocusEvent, processWindowStateEvent, removeWindowFocusListener, removeWindowListener, removeWindowStateListener, reshape, setAlwaysOnTop, setAutoRequestFocus, setBounds, setBounds, setCursor, setFocusableWindowState, setFocusCycleRoot, setIconImages, setLocation, setLocation, setLocationByPlatform, setLocationRelativeTo, setMinimumSize, setModalExclusionType, setSize, setSize, setType, setVisible, show, toBack, toFrontadd, add, add, add, add, addContainerListener, applyComponentOrientation, areFocusTraversalKeysSet, countComponents, deliverEvent, doLayout, findComponentAt, findComponentAt, getAlignmentX, getAlignmentY, getComponent, getComponentAt, getComponentAt, getComponentCount, getComponents, getComponentZOrder, getContainerListeners, getFocusTraversalPolicy, getInsets, getLayout, getMaximumSize, getMinimumSize, getMousePosition, getPreferredSize, insets, invalidate, isAncestorOf, isFocusCycleRoot, isFocusTraversalPolicyProvider, isFocusTraversalPolicySet, layout, list, list, locate, minimumSize, paintComponents, preferredSize, print, printComponents, processContainerEvent, remove, removeAll, removeContainerListener, setComponentZOrder, setFocusTraversalKeys, setFocusTraversalPolicy, setFocusTraversalPolicyProvider, setFont, transferFocusDownCycle, validate, validateTreeaction, add, addComponentListener, addFocusListener, addHierarchyBoundsListener, addHierarchyListener, addInputMethodListener, addKeyListener, addMouseListener, addMouseMotionListener, addMouseWheelListener, bounds, checkImage, checkImage, coalesceEvents, contains, contains, createImage, createImage, createVolatileImage, createVolatileImage, disable, disableEvents, dispatchEvent, enable, enable, enableEvents, enableInputMethods, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, getBaseline, getBaselineResizeBehavior, getBounds, getBounds, getColorModel, getComponentListeners, getComponentOrientation, getCursor, getDropTarget, getFocusListeners, getFocusTraversalKeysEnabled, getFont, getFontMetrics, getForeground, getGraphicsConfiguration, getHeight, getHierarchyBoundsListeners, getHierarchyListeners, getIgnoreRepaint, getInputMethodListeners, getInputMethodRequests, getKeyListeners, getLocation, getLocation, getLocationOnScreen, getMouseListeners, getMouseMotionListeners, getMousePosition, getMouseWheelListeners, getName, getParent, getPeer, getPropertyChangeListeners, getPropertyChangeListeners, getSize, getSize, getTreeLock, getWidth, getX, getY, gotFocus, handleEvent, hasFocus, imageUpdate, inside, isBackgroundSet, isCursorSet, isDisplayable, isDoubleBuffered, isEnabled, isFocusable, isFocusOwner, isFocusTraversable, isFontSet, isForegroundSet, isLightweight, isMaximumSizeSet, isMinimumSizeSet, isPreferredSizeSet, isValid, isVisible, keyDown, keyUp, list, list, list, location, lostFocus, mouseDown, mouseDrag, mouseEnter, mouseExit, mouseMove, mouseUp, move, nextFocus, paintAll, prepareImage, prepareImage, printAll, processComponentEvent, processFocusEvent, processHierarchyBoundsEvent, processHierarchyEvent, processInputMethodEvent, processKeyEvent, processMouseEvent, processMouseMotionEvent, processMouseWheelEvent, removeComponentListener, removeFocusListener, removeHierarchyBoundsListener, removeHierarchyListener, removeInputMethodListener, removeKeyListener, removeMouseListener, removeMouseMotionListener, removeMouseWheelListener, removePropertyChangeListener, removePropertyChangeListener, repaint, repaint, repaint, requestFocus, requestFocus, requestFocusInWindow, requestFocusInWindow, resize, resize, revalidate, setComponentOrientation, setDropTarget, setEnabled, setFocusable, setFocusTraversalKeysEnabled, setForeground, setIgnoreRepaint, setLocale, setMaximumSize, setName, setPreferredSize, show, size, toString, transferFocus, transferFocusBackward, transferFocusUpCycleprivate javax.swing.JTextArea logArea
private javax.swing.JTextArea dataArea
private javax.swing.JPasswordField pwd
private javax.swing.JTextArea certArea
private DigestSignTask signTask
private javax.swing.Timer signTimer
private FindCertTask certTask
private javax.swing.Timer findTimer
private javax.swing.JButton f
private javax.swing.JButton c
private javax.swing.JButton s
private javax.swing.JProgressBar progressBar
boolean debug
boolean submitAfterSigning
private byte[] bytesToSign
private java.lang.String encodedDigest
private byte[] encryptedDigest
private java.io.PrintStream log
public static final int ONE_SECOND
private java.lang.String cryptokiLib
private java.lang.String signerLabel
private byte[] certificate
private org.bouncycastle.cms.CMSProcessable msg
private ExternalSignatureCMSSignedDataGenerator cmsGenerator
private ExternalSignatureSignerInfoGenerator signerInfoGenerator
private java.util.ArrayList signersCertList
private java.io.File fileToSign
private boolean forcingCryptoki
private static java.lang.String PROPERTIES_FILE
private boolean makeDigestOnToken
private java.lang.String digestAlg
private java.lang.String encAlg
public GUITest(java.lang.String title,
java.lang.String aDebug,
java.lang.String aCryptoki)
title - , shown on the window title bar.aDebug - if True, causes operation log to be shown in the GUI, in a
dedicated pane.java.awt.HeadlessExceptionpublic boolean isForcingCryptoki()
private void loadProperties()
private void findCert()
public static void main(java.lang.String[] args)
private void openSignature(java.lang.String digestAlg,
java.lang.String encryptionAlg,
boolean digestOnToken)
throws java.security.InvalidKeyException,
java.security.SignatureException,
java.security.NoSuchProviderException,
java.security.NoSuchAlgorithmException,
java.io.IOException,
org.bouncycastle.cms.CMSException,
java.security.cert.CertificateException
digestAlg - encryptionAlg - digestOnToken - java.security.InvalidKeyExceptionjava.security.SignatureExceptionjava.security.NoSuchProviderExceptionjava.security.NoSuchAlgorithmExceptionjava.io.IOExceptionorg.bouncycastle.cms.CMSExceptionjava.security.cert.CertificateExceptionprivate void sign()
digestOnToken - if true, the cryptoki - card takes care of digesting; raw
bytes to sign are passed to cryptoki functions.private void closeSignature()
throws java.security.cert.CertificateException
java.security.cert.CertificateExceptionprivate org.bouncycastle.cms.CMSSignedData buildCMSSignedData()
throws java.security.cert.CertStoreException,
java.security.InvalidAlgorithmParameterException,
java.security.cert.CertificateExpiredException,
java.security.cert.CertificateNotYetValidException,
java.security.NoSuchAlgorithmException,
java.security.NoSuchProviderException,
org.bouncycastle.cms.CMSException
java.security.cert.CertStoreExceptionjava.security.InvalidAlgorithmParameterExceptionjava.security.cert.CertificateExpiredExceptionjava.security.cert.CertificateNotYetValidExceptionjava.security.NoSuchAlgorithmExceptionjava.security.NoSuchProviderExceptionorg.bouncycastle.cms.CMSExceptionpublic void actionPerformed(java.awt.event.ActionEvent e)
actionPerformed in interface java.awt.event.ActionListenerActionListener.actionPerformed(java.awt.event.ActionEvent)private boolean isTextFile(java.io.File f)
throws java.io.IOException
f - java.io.IOExceptionprivate void prepareDigestFromTextArea()
throws java.security.NoSuchAlgorithmException,
java.io.UnsupportedEncodingException
java.security.NoSuchAlgorithmExceptionjava.io.UnsupportedEncodingExceptionpublic java.lang.String decode(java.lang.String s)
s - public byte[] decodeToBytes(java.lang.String s)
s - private void enableControls(boolean enable)
enable - booleanpublic java.lang.String encode(java.lang.String s)
s - public java.lang.String encodeFromBytes(byte[] bytes)
bytes - public java.lang.String getAppletInfo()
public byte[] getCertificate()
public java.security.cert.X509Certificate getJavaCertificate()
throws java.security.cert.CertificateException
java.security.cert.CertificateExceptionprivate java.lang.String getCryptokiLib()
public java.lang.String getEncodedDigest()
public byte[] getEncryptedDigest()
private java.lang.String getSignerLabel()
private void initStatus(int min,
int max)
min - max - private boolean isDebugMode()
private void setCertificate(byte[] newCertificate)
newCertificate - private void setCryptokiLib(java.lang.String newCryptokiLib)
newCryptokiLib - public void setEncodedDigest(java.lang.String data)
data - public void setEncryptedDigest(byte[] newEncryptedDigest)
newEncryptedDigest - private void setSignerLabel(java.lang.String newSignerLabel)
newSignerLabel - private void setStatus(int code,
java.lang.String statusString)
code - statusString - private long algToMechanism(boolean digestOnToken,
java.lang.String digestAlg,
java.lang.String encryptionAlg)
java.lang.String formatAsHexString(byte[] bytes)
bytes - private boolean detectCardAndCriptoki()
throws java.io.IOException
PCSCHelperclass is used
to detect reader and token presence, trying also to provide a candidate
PKCS#11 cryptoki for it.java.io.IOExceptionpublic java.io.File getFileToSign()
public void setFileToSign(java.io.File fileToSign)
private byte[] applyPkcs1Padding(int resultLength,
byte[] srcBytes)
private byte[] encapsulateInDigestInfo(java.lang.String digestAlg,
byte[] digestBytes)
throws java.io.IOException
java.io.IOExceptionpublic void changedUpdate(javax.swing.event.DocumentEvent e)
changedUpdate in interface javax.swing.event.DocumentListenerpublic void insertUpdate(javax.swing.event.DocumentEvent e)
insertUpdate in interface javax.swing.event.DocumentListenerpublic void removeUpdate(javax.swing.event.DocumentEvent e)
removeUpdate in interface javax.swing.event.DocumentListener