Home | History | Annotate | Download | only in security
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.security;
     19 
     20 import java.io.ByteArrayInputStream;
     21 import java.io.ByteArrayOutputStream;
     22 import java.io.IOException;
     23 import java.io.ObjectInputStream;
     24 import java.io.ObjectOutputStream;
     25 import java.io.Serializable;
     26 
     27 /**
     28  * A {@code SignedObject} instance acts as a container for another object. The
     29  * {@code SignedObject} contains the target in serialized form along with a
     30  * digital signature of the serialized data.
     31  */
     32 public final class SignedObject implements Serializable {
     33 
     34     private static final long serialVersionUID = 720502720485447167L;
     35 
     36     private byte[] content;
     37 
     38     private byte[] signature;
     39 
     40     private String thealgorithm;
     41 
     42     private void readObject(ObjectInputStream s) throws IOException,
     43             ClassNotFoundException {
     44 
     45         s.defaultReadObject();
     46         byte[] tmp = new byte[content.length];
     47         System.arraycopy(content, 0, tmp, 0, content.length);
     48         content = tmp;
     49         tmp = new byte[signature.length];
     50         System.arraycopy(signature, 0, tmp, 0, signature.length);
     51         signature = tmp;
     52     }
     53 
     54     /**
     55      * Constructs a new instance of {@code SignedObject} with the target object,
     56      * the private key and the engine to compute the signature. The given
     57      * {@code object} is signed with the specified key and engine.
     58      *
     59      * @param object
     60      *            the object to bes signed.
     61      * @param signingKey
     62      *            the private key, used to sign the {@code object}.
     63      * @param signingEngine
     64      *            the engine that performs the signature generation.
     65      * @throws IOException
     66      *             if a serialization error occurs.
     67      * @throws InvalidKeyException
     68      *             if the private key is not valid.
     69      * @throws SignatureException
     70      *             if signature generation failed.
     71      */
     72     public SignedObject(Serializable object, PrivateKey signingKey,
     73             Signature signingEngine) throws IOException, InvalidKeyException,
     74             SignatureException {
     75 
     76         ByteArrayOutputStream baos = new ByteArrayOutputStream();
     77         ObjectOutputStream oos = new ObjectOutputStream(baos);
     78         try {
     79             // Serialize
     80             oos.writeObject(object);
     81             oos.flush();
     82         } finally {
     83             oos.close();
     84         }
     85         content = baos.toByteArray();
     86         signingEngine.initSign(signingKey);
     87         thealgorithm = signingEngine.getAlgorithm();
     88         signingEngine.update(content);
     89         signature = signingEngine.sign();
     90     }
     91 
     92     /**
     93      * Returns the encapsulated object. Each time this method is invoked, the
     94      * encapsulated object is deserialized before it is returned.
     95      *
     96      * @return the encapsulated object.
     97      * @throws IOException
     98      *             if deserialization failed.
     99      * @throws ClassNotFoundException
    100      *             if the class of the encapsulated object can not be found.
    101      */
    102     public Object getObject() throws IOException, ClassNotFoundException {
    103         // deserialize our object
    104         ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
    105                 content));
    106         try {
    107             return ois.readObject();
    108         } finally {
    109             ois.close();
    110         }
    111     }
    112 
    113     /**
    114      * Returns the signature data of the encapsulated serialized object.
    115      *
    116      * @return the signature data of the encapsulated serialized object.
    117      */
    118     public byte[] getSignature() {
    119         byte[] sig = new byte[signature.length];
    120         System.arraycopy(signature, 0, sig, 0, signature.length);
    121         return sig;
    122     }
    123 
    124     /**
    125      * Returns the name of the algorithm of this {@code SignedObject}.
    126      *
    127      * @return the name of the algorithm of this {@code SignedObject}.
    128      */
    129     public String getAlgorithm() {
    130         return thealgorithm;
    131     }
    132 
    133     /**
    134      * Indicates whether the contained signature for the encapsulated object is
    135      * valid.
    136      *
    137      * @param verificationKey
    138      *            the public key to verify the signature.
    139      * @param verificationEngine
    140      *            the signature engine.
    141      * @return {@code true} if the contained signature for the encapsulated
    142      *         object is valid, {@code false} otherwise.
    143      * @throws InvalidKeyException
    144      *             if the public key is invalid.
    145      * @throws SignatureException
    146      *             if signature verification failed.
    147      */
    148     public boolean verify(PublicKey verificationKey,
    149             Signature verificationEngine) throws InvalidKeyException,
    150             SignatureException {
    151 
    152         verificationEngine.initVerify(verificationKey);
    153         verificationEngine.update(content);
    154         return verificationEngine.verify(signature);
    155     }
    156 
    157 }
    158