Class GenericCertificate
- java.lang.Object
-
- org.zkoss.chart.lic.xml.GenericCertificate
-
- All Implemented Interfaces:
Serializable
public final class GenericCertificate extends Object implements Serializable
This 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 bothSignedObject
andCertificate
.More specifically, a
GenericCertificate
contains 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
PersistenceDelegate
instances 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
sign
and theverify
methods.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
Signature
engine 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
ObjectOutputStream
orXMLEncoder
. 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 int
DEFAULT_BUFSIZE
10KB - the default buffer size for buffered I/O.static String
XML_CHARSET
"UTF-8"
- the character encoding used byXMLEncoder
andXMLDecoder
.
-
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 void
addPropertyChangeListener(PropertyChangeListener l)
Adds a PropertyChangeListener to the listener list.void
addVetoableChangeListener(VetoableChangeListener l)
Adds a VetoableChangeListener to the listener list.protected void
firePropertyChange(PropertyChangeEvent evt)
protected void
fireVetoableChange(PropertyChangeEvent evt)
Object
getContent()
Returns a clone of the certificate's content as it was signed or verified before.String
getEncoded()
Getter for the propertyencoded
.String
getSignature()
Getter for the propertysignature
.String
getSignatureAlgorithm()
Getter for the propertysignatureAlgorithm
.String
getSignatureEncoding()
Getter for the propertysignatureEncoding
.boolean
isLocked()
Returns the "locked" property of this generic certificate.void
removePropertyChangeListener(PropertyChangeListener l)
Removes a PropertyChangeListener from the listener list.void
removeVetoableChangeListener(VetoableChangeListener l)
Removes a VetoableChangeListener from the listener list.void
setEncoded(String encoded)
Setter for the bound propertyencoded
.void
setSignature(String signature)
Setter for the bound propertysignature
.void
setSignatureAlgorithm(String signatureAlgorithm)
Setter for the bound propertysignatureAlgorithm
.void
setSignatureEncoding(String signatureEncoding)
Deprecated.Currently ignored byverify(java.security.PublicKey, java.security.Signature)
.void
sign(Object content, PrivateKey signingKey, Signature signingEngine)
Encodes and signs the givencontent
in this certificate and locks it.void
verify(PublicKey verificationKey, Signature verificationEngine)
Verifies the digital signature of the encoded content in this certificate and locks it.
-
-
-
Field Detail
-
XML_CHARSET
public static final String XML_CHARSET
"UTF-8"
- the character encoding used byXMLEncoder
andXMLDecoder
.- 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(Object content, PrivateKey signingKey, Signature signingEngine) throws NullPointerException, GenericCertificateIsLockedException, PropertyVetoException, PersistenceServiceException, InvalidKeyException
Encodes and signs the givencontent
in this certificate and locks it.Please note the following:
- This method will throw a
PropertyVetoException
if 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
GenericCertificate
if 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:
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
.PropertyVetoException
- If locking the certifificate (and thus signing the object) is vetoed by any listener.PersistenceServiceException
- If the object cannot be serialised.InvalidKeyException
- If the verification key is invalid.
- This method will throw a
-
verify
public final void verify(PublicKey verificationKey, Signature verificationEngine) throws NullPointerException, GenericCertificateIsLockedException, PropertyVetoException, InvalidKeyException, SignatureException, GenericCertificateIntegrityException
Verifies the digital signature of the encoded content in this certificate and locks it.Please note the following:
- This method will throw a
PropertyVetoException
if 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
GenericCertificate
if 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:
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
.PropertyVetoException
- If locking the certifificate (and thus verifying the object) is vetoed by any listener.InvalidKeyException
- If the verification key is invalid.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 Object getContent() throws GenericCertificateNotLockedException, PersistenceServiceException
Returns 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 returnnull
if 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 String getEncoded()
Getter for the propertyencoded
. The default isnull
.- Returns:
- Value of property encoded.
-
setEncoded
public void setEncoded(String encoded) throws GenericCertificateIsLockedException
Setter 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 String getSignature()
Getter for the propertysignature
. The default isnull
.- Returns:
- Value of property signature.
-
setSignature
public void setSignature(String signature) throws GenericCertificateIsLockedException
Setter 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 String getSignatureAlgorithm()
Getter for the propertysignatureAlgorithm
. The default isnull
.- Returns:
- The signature algorithm.
-
setSignatureAlgorithm
public void setSignatureAlgorithm(String signatureAlgorithm) throws GenericCertificateIsLockedException
Setter 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 String getSignatureEncoding()
Getter for the propertysignatureEncoding
. The default isnull
.- Returns:
- The character encoding of the signature string.
-
setSignatureEncoding
public void setSignatureEncoding(String signatureEncoding) throws GenericCertificateIsLockedException
Deprecated.Currently ignored byverify(java.security.PublicKey, java.security.Signature)
. Only provided to causeXMLEncoder
to 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(VetoableChangeListener l)
Adds a VetoableChangeListener to the listener list.- Parameters:
l
- The listener to add.
-
removeVetoableChangeListener
public final void removeVetoableChangeListener(VetoableChangeListener l)
Removes a VetoableChangeListener from the listener list.- Parameters:
l
- The listener to remove.
-
fireVetoableChange
protected final void fireVetoableChange(PropertyChangeEvent evt) throws PropertyVetoException
- Throws:
PropertyVetoException
-
addPropertyChangeListener
public final void addPropertyChangeListener(PropertyChangeListener l)
Adds a PropertyChangeListener to the listener list.- Parameters:
l
- The listener to add.
-
removePropertyChangeListener
public final void removePropertyChangeListener(PropertyChangeListener l)
Removes a PropertyChangeListener from the listener list.- Parameters:
l
- The listener to remove.
-
firePropertyChange
protected final void firePropertyChange(PropertyChangeEvent evt)
-
-