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.AccessibleJFrame
java.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, rootPaneCheckingEnabled
CROSSHAIR_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_CURSOR
BOTTOM_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
PCSCHelper class 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, update
addNotify, getCursorType, getExtendedState, getFrames, getIconImage, getMaximizedBounds, getMenuBar, getState, getTitle, isResizable, isUndecorated, remove, removeNotify, setBackground, setCursor, setExtendedState, setMaximizedBounds, setMenuBar, setOpacity, setResizable, setShape, setState, setTitle, setUndecorated
addPropertyChangeListener, 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, toFront
add, 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, validateTree
action, 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, transferFocusUpCycle
private 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.HeadlessException
public 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.InvalidKeyException
java.security.SignatureException
java.security.NoSuchProviderException
java.security.NoSuchAlgorithmException
java.io.IOException
org.bouncycastle.cms.CMSException
java.security.cert.CertificateException
private 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.CertificateException
private 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.CertStoreException
java.security.InvalidAlgorithmParameterException
java.security.cert.CertificateExpiredException
java.security.cert.CertificateNotYetValidException
java.security.NoSuchAlgorithmException
java.security.NoSuchProviderException
org.bouncycastle.cms.CMSException
public void actionPerformed(java.awt.event.ActionEvent e)
actionPerformed
in interface java.awt.event.ActionListener
ActionListener.actionPerformed(java.awt.event.ActionEvent)
private boolean isTextFile(java.io.File f) throws java.io.IOException
f
- java.io.IOException
private void prepareDigestFromTextArea() throws java.security.NoSuchAlgorithmException, java.io.UnsupportedEncodingException
java.security.NoSuchAlgorithmException
java.io.UnsupportedEncodingException
public 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.CertificateException
private 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
PCSCHelper
class is used
to detect reader and token presence, trying also to provide a candidate
PKCS#11 cryptoki for it.java.io.IOException
public 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.IOException
public void changedUpdate(javax.swing.event.DocumentEvent e)
changedUpdate
in interface javax.swing.event.DocumentListener
public void insertUpdate(javax.swing.event.DocumentEvent e)
insertUpdate
in interface javax.swing.event.DocumentListener
public void removeUpdate(javax.swing.event.DocumentEvent e)
removeUpdate
in interface javax.swing.event.DocumentListener