home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / security / SignedObject.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  8.4 KB  |  233 lines

  1. /*
  2.  * @(#)SignedObject.java    1.32 98/03/18
  3.  *
  4.  * Copyright 1997 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import java.io.*;
  18.  
  19. /**
  20.  * <p> SignedObject is a class for the purpose of creating authentic
  21.  * runtime objects whose integrity cannot be compromised without being
  22.  * detected.
  23.  *
  24.  * <p> More specifically, a SignedObject contains another Serializable
  25.  * object, the (to-be-)signed object and its signature.
  26.  *
  27.  * <p> The signed object is a "deep copy" (in serialized form) of an
  28.  * original object.  Once the copy is made, further manipulation of
  29.  * the original object has no side effect on the copy.
  30.  *
  31.  * <p> The underlying signing algorithm is designated by the Signature
  32.  * object passed to the constructor and the <code>verify</code> method.
  33.  * A typical usage for signing is the following:
  34.  *
  35.  * <p> <code> <pre>
  36.  * Signature signingEngine = Signature.getInstance(algorithm,
  37.  *                                                 provider);
  38.  * SignedObject so = new SignedObject(myobject, signingKey,
  39.  *                                    signingEngine);
  40.  * </pre> </code>
  41.  *
  42.  * <p> A typical usage for verification is the following (having
  43.  * received SignedObject <code>so</code>):
  44.  *
  45.  * <p> <code> <pre>
  46.  * Signature verificationEngine =
  47.  *     Signature.getInstance(algorithm, provider);
  48.  * if (so.verify(publickey, verificationEngine))
  49.  *     try {
  50.  *         Object myobj = so.getObject();
  51.  *     } catch (java.lang.ClassNotFoundException e) {};
  52.  * </pre> </code>
  53.  *
  54.  * <p> Several points are worth noting.  First, there is no need to
  55.  * initialize the signing or verification engine, as it will be
  56.  * re-initialized inside the constructor and the <code>verify</code>
  57.  * method. Secondly, for verification to succeed, the specified
  58.  * public key must be the public key corresponding to the private key
  59.  * used to generate the SignedObject.
  60.  *
  61.  * <p> More importantly, for flexibility reasons, the
  62.  * constructor and <code>verify</code> method allow for
  63.  * customized signature engines, which can implement signature
  64.  * algorithms that are not installed formally as part of a crypto
  65.  * provider.  However, it is crucial that the programmer writing the
  66.  * verifier code be aware what <code>Signature</code> engine is being
  67.  * used, as its own implementation of the <code>verify</code> method
  68.  * is invoked to verify a signature.  In other words, a malicious
  69.  * <code>Signature</code> may choose to always return true on
  70.  * verification in an attempt to bypass a security check.
  71.  *
  72.  * <p> The signature algorithm can be, among others, the NIST standard
  73.  * DSA, using DSA and SHA-1.  The algorithm is specified using the
  74.  * same convention as that for signatures. The DSA algorithm using the
  75.  * SHA-1 message digest algorithm can be specified, for example, as
  76.  * "SHA/DSA" or "SHA-1/DSA" (they are equivalent).  In the case of
  77.  * RSA, there are multiple choices for the message digest algorithm,
  78.  * so the signing algorithm could be specified as, for example,
  79.  * "MD2/RSA", "MD5/RSA" or "SHA-1/RSA".  The algorithm name must be
  80.  * specified, as there is no default.
  81.  *
  82.  * <p> The name of the Cryptography Package Provider is designated
  83.  * also by the Signature parameter to the constructor and the
  84.  * <code>verify</code> method.  If the provider is not
  85.  * specified, the default provider is used.  Each installation can
  86.  * be configured to use a particular provider as default.
  87.  *
  88.  * <p> Potential applications of SignedObject include: 
  89.  * <ul>
  90.  * <li> It can be used
  91.  * internally to any Java runtime as an unforgeable authorization
  92.  * token -- one that can be passed around without the fear that the
  93.  * token can be maliciously modified without being detected. 
  94.  * <li> It
  95.  * can be used to sign and serialize data/object for storage outside
  96.  * the Java runtime (e.g., storing critical access control data on
  97.  * disk). 
  98.  * <li> Nested SignedObjects can be used to construct a logical
  99.  * sequence of signatures, resembling a chain of authorization and
  100.  * delegation.
  101.  * </ul>
  102.  *
  103.  * @see Signature
  104.  *
  105.  * @version     1.32, 03/18/98
  106.  * @author Li Gong
  107.  */
  108.  
  109. public final class SignedObject implements Serializable {
  110.  
  111.     /*
  112.      * The original content is "deep copied" in its serialized format
  113.      * and stored in a byte array.  The signature field is also in the
  114.      * form of byte array.
  115.      */
  116.  
  117.     private byte[] content;
  118.     private byte[] signature;
  119.     private String thealgorithm;
  120.  
  121.     /**
  122.      * Constructs a SignedObject from any Serializable object.
  123.      * The given object is signed with the given signing key, using the
  124.      * designated signature engine.
  125.      *
  126.      * @param object the object to be signed. 
  127.      * @param signingKey the private key for signing.
  128.      * @param signingEngine the signature signing engine.
  129.      *
  130.      * @exception IOException if an error occurs during serialization
  131.      * @exception InvalidKeyException if the key is invalid.
  132.      * @exception SignatureException if signing fails.
  133.      */
  134.     public SignedObject(Serializable object, PrivateKey signingKey,
  135.             Signature signingEngine)
  136.     throws IOException, InvalidKeyException, SignatureException {
  137.         // creating a stream pipe-line, from a to b
  138.         ByteArrayOutputStream b = new ByteArrayOutputStream();
  139.         ObjectOutput a = new ObjectOutputStream(b);
  140.         
  141.         // write and flush the object content to byte array
  142.         a.writeObject(object);
  143.         a.flush();
  144.         a.close();
  145.         this.content = b.toByteArray();
  146.         b.close();
  147.         
  148.         // now sign the encapsulated object
  149.         this.sign(signingKey, signingEngine);
  150.     }
  151.  
  152.     /**
  153.      * Retrieves the encapsulated object.
  154.      * The encapsulated object is de-serialized before it is returned.
  155.      * 
  156.      * @return the encapsulated object.
  157.      *
  158.      * @exception IOException if an error occurs during de-serialization
  159.      * @exception ClassNotFoundException if an error occurs during 
  160.      * de-serialization
  161.      */
  162.     public Object getObject() 
  163.     throws IOException, ClassNotFoundException
  164.     {
  165.     // creating a stream pipe-line, from b to a
  166.     ByteArrayInputStream b = new ByteArrayInputStream(this.content);
  167.     ObjectInput a = new ObjectInputStream(b);
  168.     Object obj = a.readObject();
  169.     b.close();
  170.     a.close();
  171.     return obj;
  172.     }
  173.  
  174.     /**
  175.      * Retrieves the signature on the signed object, in the form of a
  176.      * byte array.
  177.      * 
  178.      * @return the signature.
  179.      */
  180.     public byte[] getSignature() {
  181.     // return only a clone, for integrity reasons
  182.     byte[] sig = (byte[])this.signature.clone();
  183.     return sig;
  184.     }
  185.  
  186.     /**
  187.      * Retrieves the name of the signature algorithm.
  188.      *
  189.      * @return the signature algorithm name.
  190.      */
  191.     public String getAlgorithm() {
  192.     return this.thealgorithm;
  193.     }
  194.  
  195.     /** 
  196.      * Verifies that the signature in this SignedObject is the valid
  197.      * signature for the object stored inside, with the given
  198.      * verification key, using the designated verification engine.
  199.      * 
  200.      * @param verificationKey the public key for verification.
  201.      * @param verificationEngine the signature verification engine.
  202.      *
  203.      * @exception SignatureException if signature verification failed.
  204.      * @exception InvalidKeyException if the verification key is invalid.
  205.      */
  206.     public boolean verify(PublicKey verificationKey,
  207.               Signature verificationEngine)
  208.      throws InvalidKeyException, SignatureException {
  209.          verificationEngine.initVerify(verificationKey);
  210.          verificationEngine.update(this.content);
  211.          return verificationEngine.verify(this.signature);
  212.     }
  213.  
  214.     /*
  215.      * Signs the encapsulated object with the given signing key, using the
  216.      * designated signature engine.
  217.      * 
  218.      * @param signingKey the private key for signing.
  219.      * @param signingEngine the signature signing engine.
  220.      *
  221.      * @exception InvalidKeyException if the key is invalid.
  222.      * @exception SignatureException if signing fails.
  223.      */
  224.     private void sign(PrivateKey signingKey, Signature signingEngine)
  225.     throws InvalidKeyException, SignatureException {
  226.         // initialize the signing engine
  227.         signingEngine.initSign(signingKey);
  228.         signingEngine.update(this.content);
  229.         this.signature = signingEngine.sign();
  230.         this.thealgorithm = signingEngine.getAlgorithm();
  231.     }
  232. }
  233.