GNU Classpath (0.20) | |
Frames | No Frames |
1: /* SignedObject.java --- Signed Object Class 2: Copyright (C) 1999, 2003, Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package java.security; 39: 40: import java.io.ByteArrayInputStream; 41: import java.io.ByteArrayOutputStream; 42: import java.io.IOException; 43: import java.io.ObjectInput; 44: import java.io.ObjectInputStream; 45: import java.io.ObjectOutputStream; 46: import java.io.Serializable; 47: 48: /** 49: * <p><code>SignedObject</code> is a class for the purpose of creating authentic 50: * runtime objects whose integrity cannot be compromised without being detected. 51: * </p> 52: * 53: * <p>More specifically, a <code>SignedObject</code> contains another 54: * {@link Serializable} object, the (to-be-)signed object and its signature.</p> 55: * 56: * <p>The signed object is a <i>"deep copy"</i> (in serialized form) of an 57: * original object. Once the copy is made, further manipulation of the original 58: * object has no side effect on the copy.</p> 59: * 60: * <p>The underlying signing algorithm is designated by the {@link Signature} 61: * object passed to the constructor and the <code>verify()</code> method. A 62: * typical usage for signing is the following:</p> 63: * 64: * <pre> 65: * Signature signingEngine = Signature.getInstance(algorithm, provider); 66: * SignedObject so = new SignedObject(myobject, signingKey, signingEngine); 67: * </pre> 68: * 69: * <p>A typical usage for verification is the following (having received 70: * <code>SignedObject</code> so):</p> 71: * 72: * <pre> 73: * Signature verificationEngine = Signature.getInstance(algorithm, provider); 74: * if (so.verify(publickey, verificationEngine)) 75: * try 76: * { 77: * Object myobj = so.getObject(); 78: * } 79: * catch (ClassNotFoundException ignored) {}; 80: * </pre> 81: * 82: * <p>Several points are worth noting. First, there is no need to initialize the 83: * signing or verification engine, as it will be re-initialized inside the 84: * constructor and the <code>verify()</code> method. Secondly, for verification 85: * to succeed, the specified public key must be the public key corresponding to 86: * the private key used to generate the <code>SignedObject</code>.</p> 87: * 88: * <p>More importantly, for flexibility reasons, the <code>constructor</code> 89: * and <code>verify()</code> method allow for customized signature engines, 90: * which can implement signature algorithms that are not installed formally as 91: * part of a crypto provider. However, it is crucial that the programmer writing 92: * the verifier code be aware what {@link Signature} engine is being used, as 93: * its own implementation of the <code>verify()</code> method is invoked to 94: * verify a signature. In other words, a malicious {@link Signature} may choose 95: * to always return <code>true</code> on verification in an attempt to bypass a 96: * security check.</p> 97: * 98: * <p>The signature algorithm can be, among others, the NIST standard <i>DSS</i>, 99: * using <i>DSA</i> and <i>SHA-1</i>. The algorithm is specified using the same 100: * convention as that for signatures. The <i>DSA</i> algorithm using the 101: * <i>SHA-1</i> message digest algorithm can be specified, for example, as 102: * <code>"SHA/DSA"</code> or <code>"SHA-1/DSA"</code> (they are equivalent). In 103: * the case of <i>RSA</i>, there are multiple choices for the message digest 104: * algorithm, so the signing algorithm could be specified as, for example, 105: * <code>"MD2/RSA"</code>, <code>"MD5/RSA"</code> or <code>"SHA-1/RSA"</code>. 106: * The algorithm name must be specified, as there is no default.</p> 107: * 108: * <p>The name of the Cryptography Package Provider is designated also by the 109: * {@link Signature} parameter to the <code>constructor</code> and the <code> 110: * verify()</code> method. If the provider is not specified, the default 111: * provider is used. Each installation can be configured to use a particular 112: * provider as default.</p> 113: * 114: * <p>Potential applications of <code>SignedObject</code> include:</p> 115: * 116: * <ul> 117: * <li>It can be used internally to any Java runtime as an unforgeable 118: * authorization token -- one that can be passed around without the fear that 119: * the token can be maliciously modified without being detected.</li> 120: * <li>It can be used to sign and serialize data/object for storage outside the 121: * Java runtime (e.g., storing critical access control data on disk).</li> 122: * <li>Nested <i>SignedObjects</i> can be used to construct a logical sequence 123: * of signatures, resembling a chain of authorization and delegation.</li> 124: * </ul> 125: * 126: * @author Mark Benvenuto (ivymccough@worldnet.att.net) 127: * @since 1.2 128: * @see Signature 129: */ 130: public final class SignedObject implements Serializable 131: { 132: private static final long serialVersionUID = 720502720485447167L; 133: 134: /** @serial */ 135: private byte[] content; 136: /** @serial */ 137: private byte[] signature; 138: /** @serial */ 139: private String thealgorithm; 140: 141: /** 142: * Constructs a <code>SignedObject</code> from any {@link Serializable} 143: * object. The given object is signed with the given signing key, using the 144: * designated signature engine. 145: * 146: * @param object the object to be signed. 147: * @param signingKey the private key for signing. 148: * @param signingEngine the signature signing engine. 149: * @throws IOException if an error occurs during serialization. 150: * @throws InvalidKeyException if the key is invalid. 151: * @throws SignatureException if signing fails. 152: */ 153: public SignedObject(Serializable object, PrivateKey signingKey, 154: Signature signingEngine) 155: throws IOException, InvalidKeyException, SignatureException 156: { 157: thealgorithm = signingEngine.getAlgorithm(); 158: 159: ByteArrayOutputStream ostream = new ByteArrayOutputStream(); 160: ObjectOutputStream p = new ObjectOutputStream(ostream); 161: p.writeObject(object); 162: p.flush(); 163: p.close(); 164: 165: content = ostream.toByteArray(); 166: 167: signingEngine.initSign(signingKey); 168: signingEngine.update(content); 169: signature = signingEngine.sign(); 170: } 171: 172: /** 173: * Retrieves the encapsulated object. The encapsulated object is de-serialized 174: * before it is returned. 175: * 176: * @return the encapsulated object. 177: * @throws IOException if an error occurs during de-serialization. 178: * @throws ClassNotFoundException if an error occurs during de-serialization. 179: */ 180: public Object getObject() throws IOException, ClassNotFoundException 181: { 182: ByteArrayInputStream bais = new ByteArrayInputStream(content); 183: ObjectInput oi = new ObjectInputStream(bais); 184: Object obj = oi.readObject(); 185: oi.close(); 186: bais.close(); 187: 188: return obj; 189: } 190: 191: /** 192: * Retrieves the signature on the signed object, in the form of a byte array. 193: * 194: * @return a copy of the signature. 195: */ 196: public byte[] getSignature() 197: { 198: return (byte[]) signature.clone(); 199: 200: } 201: 202: /** 203: * Retrieves the name of the signature algorithm. 204: * 205: * @return the signature algorithm name. 206: */ 207: public String getAlgorithm() 208: { 209: return thealgorithm; 210: } 211: 212: /** 213: * Verifies that the signature in this <code>SignedObject</code> is the valid 214: * signature for the object stored inside, with the given verification key, 215: * using the designated verification engine. 216: * 217: * @param verificationKey the public key for verification. 218: * @param verificationEngine the signature verification engine. 219: * @return <code>true</code> if the signature is valid, <code>false</code> 220: * otherwise. 221: * @throws SignatureException if signature verification failed. 222: * @throws InvalidKeyException if the verification key is invalid. 223: */ 224: public boolean verify(PublicKey verificationKey, Signature verificationEngine) 225: throws InvalidKeyException, SignatureException 226: { 227: verificationEngine.initVerify(verificationKey); 228: verificationEngine.update(content); 229: return verificationEngine.verify(signature); 230: } 231: 232: /** Called to restore the state of the SignedObject from a stream. */ 233: private void readObject(ObjectInputStream s) 234: throws IOException, ClassNotFoundException 235: { 236: s.defaultReadObject(); 237: content = (byte[]) content.clone(); 238: signature = (byte[]) signature.clone(); 239: } 240: }
GNU Classpath (0.20) |