Class GenericCertificate
- java.lang.Object
-
- org.zkoss.zkex.xml.GenericCertificate
-
- All Implemented Interfaces:
java.io.Serializable
public final class GenericCertificate extends java.lang.Object implements java.io.SerializableThis non-visual JavaBean implements authenticated runtime objects whose integrity cannot be compromised without being detected. The idea and the design of this class is inspired by bothSignedObjectandCertificate.More specifically, a
GenericCertificatecontains an XML string encoded representation of an arbitrary object in the "encoded" property and a Base64 immutable string representation of the object's corresponding digital signature in the "signature" property. The selection of this representation form and the design of this class as a plain JavaBean allows its instances to be serialized using either this package'sPersistenceService, JDK'sXMLEncoder, or the vanillaObjectOutputStream.For an object to be successfully digitally signed, it must support serialisation via JDK's XMLEncoder, for which this package provides the class PersistenceService. This easy-to-use class allows you to provide custom
PersistenceDelegateinstances for the serialisation of any classes which do not implement the JavaBean design pattern and are not supported by XMLEncoder as a default.Whenever an instance of this GenericCertificate class is created, you can arbitrarily set and get its "encoded" and "signature" properties, allowing you to provide even custom deserialisation methods other than this class already provides via the aforementioned classes. However, once this instance is used to either sign or verify another object it gets locked, allowing subsequent read access to its properties only.
The underlying signing algorithm is designated by the Signature object passed to the
signand theverifymethods.A typical usage for signing is the following:
<pre> GenericCertificate cert = new GenericCertificate(); Signature signingEngine = Signature.getInstance(algorithm, provider); try { cert.sign(myObject, signingKey, signingEngine); } catch (PropertyVetoException signingVetoed) { // ... } catch (PersistenceServiceException serialisationFailed) { // ... } catch (InvalidKeyException invalidKey) { // ... } catch (SignatureException signingEngineBroken) { // ... } </pre>A typical usage for verification is the following (having received GenericCertificatecert):<pre> Signature verificationEngine = Signature.getInstance(algorithm, provider); try { cert.verify(publicKey, verificationEngine)); } catch (PropertyVetoException verificationVetoed) { // ... } catch (InvalidKeyException invalidKey) { // ... } catch (SignatureException verificationEngineBroken) { // ... } catch (GenericCertificateException integrityCompromised) { // ... } Object myObject = cert.getContent(); </pre>Several points are worth noting:-
There is no need to initialize the signing or verification engine,
as it will be re-initialized inside the
sign(java.lang.Object, java.security.PrivateKey, java.security.Signature)andverify(java.security.PublicKey, java.security.Signature)methods. Secondly, for verification to succeed, the specified public key must be the public key corresponding to the private key used to sign the GenericCertificate. -
In contrast to SignedObject, this class adds more security
as it is impossible to retrieve the signed object without verifying
the signature before. A SignedObject however could
be deserialised from a compromised file and the application developer
may erraticaly forget to call the
SignedObject.verify(java.security.PublicKey, java.security.Signature)method before retrieving the signed object by callingSignedObject.getObject(). -
More importantly, for flexibility reasons, the
sign() and verify() methods allow for
customized signature engines, which can implement signature
algorithms that are not installed formally as part of a crypto
provider. However, it is crucial that the programmer writing the
verifier code be aware what
Signatureengine is being used, as its own implementation of theSignature.verify(byte[])method is invoked to verify a signature. In other words, a malicious Signature engine may choose to always return true on verification in an attempt to bypass a security check. - The signature algorithm can be, among others, the NIST standard DSA, using DSA and SHA-1. The algorithm is specified using the same convention as that for signatures. The DSA algorithm using the SHA-1 message digest algorithm can be specified, for example, as "SHA/DSA" or "SHA-1/DSA" (they are equivalent). In the case of RSA, there are multiple choices for the message digest algorithm, so the signing algorithm could be specified as, for example, "MD2/RSA", "MD5/RSA" or "SHA-1/RSA". The algorithm name must be specified, as there is no default.
- The name of the Cryptography Package Provider is designated by the Signature parameter to the sign() and verify() methods. If the provider is not specified, the default provider is used. Each installation can be configured to use a particular provider as default.
- The property change listeners are not persistet when
using
ObjectOutputStreamorXMLEncoder. Object.equals(Object)andObject.hashCode()are not overridden by this class because different JVMs will produce different literal encodings of the same object and we cannot rely on a properequals(...)implementation in the class of a signed object.
- It can be used internally to any Java runtime as an unforgeable authorization token -- one that can be passed around without the fear that the token can be maliciously modified without being detected.
- It can be used to sign and serialize data/object for storage outside the Java runtime (e.g., storing critical access control data on disk).
- Nested GenericCertificates can be used to construct a logical sequence of signatures, resembling a chain of authorization and delegation.
This class is thread-safe.
- Author:
- Christian Schlichtherle
- See Also:
Signature,SignedObject,Certificate, Serialized Form
-
-
Field Summary
Fields Modifier and Type Field Description static intDEFAULT_BUFSIZE10KB - the default buffer size for buffered I/O.static java.lang.StringXML_CHARSET"UTF-8"- the character encoding used byXMLEncoderandXMLDecoder.
-
Constructor Summary
Constructors Constructor Description GenericCertificate()Creates a new generic certificate.GenericCertificate(GenericCertificate cert)Copy constructor for the given generic certificate.
-
Method Summary
All Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description voidaddPropertyChangeListener(java.beans.PropertyChangeListener l)Adds a PropertyChangeListener to the listener list.voidaddVetoableChangeListener(java.beans.VetoableChangeListener l)Adds a VetoableChangeListener to the listener list.protected voidfirePropertyChange(java.beans.PropertyChangeEvent evt)protected voidfireVetoableChange(java.beans.PropertyChangeEvent evt)java.lang.ObjectgetContent()Returns a clone of the certificate's content as it was signed or verified before.java.lang.StringgetEncoded()Getter for the propertyencoded.java.lang.StringgetSignature()Getter for the propertysignature.java.lang.StringgetSignatureAlgorithm()Getter for the propertysignatureAlgorithm.java.lang.StringgetSignatureEncoding()Getter for the propertysignatureEncoding.booleanisLocked()Returns the "locked" property of this generic certificate.voidremovePropertyChangeListener(java.beans.PropertyChangeListener l)Removes a PropertyChangeListener from the listener list.voidremoveVetoableChangeListener(java.beans.VetoableChangeListener l)Removes a VetoableChangeListener from the listener list.voidsetEncoded(java.lang.String encoded)Setter for the bound propertyencoded.voidsetSignature(java.lang.String signature)Setter for the bound propertysignature.voidsetSignatureAlgorithm(java.lang.String signatureAlgorithm)Setter for the bound propertysignatureAlgorithm.voidsetSignatureEncoding(java.lang.String signatureEncoding)Deprecated.Currently ignored byverify(java.security.PublicKey, java.security.Signature).voidsign(java.lang.Object content, java.security.PrivateKey signingKey, java.security.Signature signingEngine)Encodes and signs the givencontentin this certificate and locks it.voidverify(java.security.PublicKey verificationKey, java.security.Signature verificationEngine)Verifies the digital signature of the encoded content in this certificate and locks it.
-
-
-
Field Detail
-
XML_CHARSET
public static final java.lang.String XML_CHARSET
"UTF-8"- the character encoding used byXMLEncoderandXMLDecoder.- See Also:
- Constant Field Values
-
DEFAULT_BUFSIZE
public static final int DEFAULT_BUFSIZE
10KB - the default buffer size for buffered I/O.- See Also:
- Constant Field Values
-
-
Constructor Detail
-
GenericCertificate
public GenericCertificate()
Creates a new generic certificate.
-
GenericCertificate
public GenericCertificate(GenericCertificate cert)
Copy constructor for the given generic certificate. Note that the new certificate is unlocked and does not have any event listeners.
-
-
Method Detail
-
sign
public final void sign(java.lang.Object content, java.security.PrivateKey signingKey, java.security.Signature signingEngine) throws java.lang.NullPointerException, GenericCertificateIsLockedException, java.beans.PropertyVetoException, PersistenceServiceException, java.security.InvalidKeyExceptionEncodes and signs the givencontentin this certificate and locks it.Please note the following:
- This method will throw a
PropertyVetoExceptionif this certificate is already locked, i.e. if it has been signed or verified before. - Because this method locks this certificate, a subsequent call to
sign(Object, PrivateKey, Signature)orverify(PublicKey, Signature)is redundant and will throw aPropertyVetoException. UseisLocked()to detect whether a generic certificate has been successfuly signed or verified before or callgetContent()and expect an Exception to be thrown if it hasn't. - There is no way to unlock this certificate.
Call the copy constructor of
GenericCertificateif you need an unlocked copy of the certificate.
- Parameters:
content- The object to sign. This must either be a JavaBean or an instance of any other class which is supported by{@link PersistenceService}- maybenull.signingKey- The private key for signing - may not benull.signingEngine- The signature signing engine - may not benull.- Throws:
java.lang.NullPointerException- If the preconditions for the parameters do not hold.GenericCertificateIsLockedException- If this certificate is already locked by signing or verifying it before. Note that this is actually a subclass ofPropertyVetoException.java.beans.PropertyVetoException- If locking the certifificate (and thus signing the object) is vetoed by any listener.PersistenceServiceException- If the object cannot be serialised.java.security.InvalidKeyException- If the verification key is invalid.
- This method will throw a
-
verify
public final void verify(java.security.PublicKey verificationKey, java.security.Signature verificationEngine) throws java.lang.NullPointerException, GenericCertificateIsLockedException, java.beans.PropertyVetoException, java.security.InvalidKeyException, java.security.SignatureException, GenericCertificateIntegrityExceptionVerifies the digital signature of the encoded content in this certificate and locks it.Please note the following:
- This method will throw a
PropertyVetoExceptionif this certificate is already locked, i.e. if it has been signed or verified before. - Because this method locks this certificate, a subsequent call to
sign(Object, PrivateKey, Signature)orverify(PublicKey, Signature)is redundant and will throw aPropertyVetoException. UseisLocked()to detect whether a generic certificate has been successfuly signed or verified before or callgetContent()and expect an Exception to be thrown if it hasn't. - There is no way to unlock this certificate.
Call the copy constructor of
GenericCertificateif you need an unlocked copy of the certificate.
- Parameters:
verificationKey- The public key for verification - may not benull.verificationEngine- The signature verification engine - may not benull.- Throws:
java.lang.NullPointerException- If the preconditions for the parameters do not hold.GenericCertificateIsLockedException- If this certificate is already locked by signing or verifying it before. Note that this is actually a subclass ofPropertyVetoException.java.beans.PropertyVetoException- If locking the certifificate (and thus verifying the object) is vetoed by any listener.java.security.InvalidKeyException- If the verification key is invalid.java.security.SignatureException- If signature verification failed.GenericCertificateIntegrityException- If the integrity of this certificate has been compromised.
- This method will throw a
-
isLocked
public final boolean isLocked()
Returns the "locked" property of this generic certificate. Iftrue, an object was successfully signed or verified before and a clone can be safely retrieved usinggetContent().
-
getContent
public java.lang.Object getContent() throws GenericCertificateNotLockedException, PersistenceServiceExceptionReturns a clone of the certificate's content as it was signed or verified before. You should save the returned object for later use as each call to this method is pretty expensive in terms of runtime and memory. This method may returnnullif this has been signed before.- Throws:
GenericCertificateNotLockedException- If no content has been signed or verified before. Note that this is ultimately aRuntimeException.PersistenceServiceException- If the signed object cannot get reinstantiated from its XML representation for some reason. This may happen for example if the signed object was created by a more recent version of its class which contains additional properties which are not supported by earlier versions.
-
getEncoded
public final java.lang.String getEncoded()
Getter for the propertyencoded. The default isnull.- Returns:
- Value of property encoded.
-
setEncoded
public void setEncoded(java.lang.String encoded) throws GenericCertificateIsLockedExceptionSetter for the bound propertyencoded.- Parameters:
encoded- The new encoded representation of the signed object - may benull.- Throws:
GenericCertificateIsLockedException- If this certificate is already locked by signing or verifying it before. Note that this is actually a subclass ofPropertyVetoException.
-
getSignature
public final java.lang.String getSignature()
Getter for the propertysignature. The default isnull.- Returns:
- Value of property signature.
-
setSignature
public void setSignature(java.lang.String signature) throws GenericCertificateIsLockedExceptionSetter for the bound propertysignature.- Parameters:
signature- The signature encoded as a string - may benull.- Throws:
GenericCertificateIsLockedException- If this certificate is already locked by signing or verifying it before. Note that this is actually a subclass ofPropertyVetoException.
-
getSignatureAlgorithm
public final java.lang.String getSignatureAlgorithm()
Getter for the propertysignatureAlgorithm. The default isnull.- Returns:
- The signature algorithm.
-
setSignatureAlgorithm
public void setSignatureAlgorithm(java.lang.String signatureAlgorithm) throws GenericCertificateIsLockedExceptionSetter for the bound propertysignatureAlgorithm.- Parameters:
signatureAlgorithm- The string identifying the signature algorithm - may benull.- Throws:
GenericCertificateIsLockedException- If this certificate is already locked by signing or verifying it before. Note that this is actually a subclass ofPropertyVetoException.
-
getSignatureEncoding
public final java.lang.String getSignatureEncoding()
Getter for the propertysignatureEncoding. The default isnull.- Returns:
- The character encoding of the signature string.
-
setSignatureEncoding
public void setSignatureEncoding(java.lang.String signatureEncoding) throws GenericCertificateIsLockedExceptionDeprecated.Currently ignored byverify(java.security.PublicKey, java.security.Signature). Only provided to causeXMLEncoderto encode this property for upwards compatibility.Setter for the bound propertysignatureEncoding.- Parameters:
signatureEncoding- The string identifying the signature encoding - may benull.- Throws:
GenericCertificateIsLockedException- If this certificate is already locked by signing or verifying it before. Note that this is actually a subclass ofPropertyVetoException.
-
addVetoableChangeListener
public final void addVetoableChangeListener(java.beans.VetoableChangeListener l)
Adds a VetoableChangeListener to the listener list.- Parameters:
l- The listener to add.
-
removeVetoableChangeListener
public final void removeVetoableChangeListener(java.beans.VetoableChangeListener l)
Removes a VetoableChangeListener from the listener list.- Parameters:
l- The listener to remove.
-
fireVetoableChange
protected final void fireVetoableChange(java.beans.PropertyChangeEvent evt) throws java.beans.PropertyVetoException- Throws:
java.beans.PropertyVetoException
-
addPropertyChangeListener
public final void addPropertyChangeListener(java.beans.PropertyChangeListener l)
Adds a PropertyChangeListener to the listener list.- Parameters:
l- The listener to add.
-
removePropertyChangeListener
public final void removePropertyChangeListener(java.beans.PropertyChangeListener l)
Removes a PropertyChangeListener from the listener list.- Parameters:
l- The listener to remove.
-
firePropertyChange
protected final void firePropertyChange(java.beans.PropertyChangeEvent evt)
-
-