0001: /*
0002: * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
0003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004: *
0005: * This code is free software; you can redistribute it and/or modify it
0006: * under the terms of the GNU General Public License version 2 only, as
0007: * published by the Free Software Foundation. Sun designates this
0008: * particular file as subject to the "Classpath" exception as provided
0009: * by Sun in the LICENSE file that accompanied this code.
0010: *
0011: * This code is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * version 2 for more details (a copy is included in the LICENSE file that
0015: * accompanied this code).
0016: *
0017: * You should have received a copy of the GNU General Public License version
0018: * 2 along with this work; if not, write to the Free Software Foundation,
0019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020: *
0021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022: * CA 95054 USA or visit www.sun.com if you need additional information or
0023: * have any questions.
0024: */
0025:
0026: package java.security;
0027:
0028: import java.security.spec.AlgorithmParameterSpec;
0029: import java.util.*;
0030: import java.util.concurrent.ConcurrentHashMap;
0031: import java.io.*;
0032: import java.security.cert.Certificate;
0033: import java.security.cert.X509Certificate;
0034:
0035: import java.nio.ByteBuffer;
0036:
0037: import java.security.Provider.Service;
0038:
0039: import javax.crypto.Cipher;
0040: import javax.crypto.CipherSpi;
0041: import javax.crypto.IllegalBlockSizeException;
0042: import javax.crypto.BadPaddingException;
0043: import javax.crypto.NoSuchPaddingException;
0044:
0045: import sun.security.util.Debug;
0046: import sun.security.jca.*;
0047: import sun.security.jca.GetInstance.Instance;
0048:
0049: /**
0050: * This Signature class is used to provide applications the functionality
0051: * of a digital signature algorithm. Digital signatures are used for
0052: * authentication and integrity assurance of digital data.
0053: *
0054: * <p> The signature algorithm can be, among others, the NIST standard
0055: * DSA, using DSA and SHA-1. The DSA algorithm using the
0056: * SHA-1 message digest algorithm can be specified as <tt>SHA1withDSA</tt>.
0057: * In the case of RSA, there are multiple choices for the message digest
0058: * algorithm, so the signing algorithm could be specified as, for example,
0059: * <tt>MD2withRSA</tt>, <tt>MD5withRSA</tt>, or <tt>SHA1withRSA</tt>.
0060: * The algorithm name must be specified, as there is no default.
0061: *
0062: * <p> A Signature object can be used to generate and verify digital
0063: * signatures.
0064: *
0065: * <p> There are three phases to the use of a Signature object for
0066: * either signing data or verifying a signature:<ol>
0067: *
0068: * <li>Initialization, with either
0069: *
0070: * <ul>
0071: *
0072: * <li>a public key, which initializes the signature for
0073: * verification (see {@link #initVerify(PublicKey) initVerify}), or
0074: *
0075: * <li>a private key (and optionally a Secure Random Number Generator),
0076: * which initializes the signature for signing
0077: * (see {@link #initSign(PrivateKey)}
0078: * and {@link #initSign(PrivateKey, SecureRandom)}).
0079: *
0080: * </ul><p>
0081: *
0082: * <li>Updating<p>
0083: *
0084: * <p>Depending on the type of initialization, this will update the
0085: * bytes to be signed or verified. See the
0086: * {@link #update(byte) update} methods.<p>
0087: *
0088: * <li>Signing or Verifying a signature on all updated bytes. See the
0089: * {@link #sign() sign} methods and the {@link #verify(byte[]) verify}
0090: * method.
0091: *
0092: * </ol>
0093: *
0094: * <p>Note that this class is abstract and extends from
0095: * <code>SignatureSpi</code> for historical reasons.
0096: * Application developers should only take notice of the methods defined in
0097: * this <code>Signature</code> class; all the methods in
0098: * the superclass are intended for cryptographic service providers who wish to
0099: * supply their own implementations of digital signature algorithms.
0100: *
0101: * @author Benjamin Renaud
0102: *
0103: * @version 1.110, 05/05/07
0104: */
0105:
0106: public abstract class Signature extends SignatureSpi {
0107:
0108: private static final Debug debug = Debug.getInstance("jca",
0109: "Signature");
0110:
0111: /*
0112: * The algorithm for this signature object.
0113: * This value is used to map an OID to the particular algorithm.
0114: * The mapping is done in AlgorithmObject.algOID(String algorithm)
0115: */
0116: private String algorithm;
0117:
0118: // The provider
0119: Provider provider;
0120:
0121: /**
0122: * Possible {@link #state} value, signifying that
0123: * this signature object has not yet been initialized.
0124: */
0125: protected final static int UNINITIALIZED = 0;
0126:
0127: /**
0128: * Possible {@link #state} value, signifying that
0129: * this signature object has been initialized for signing.
0130: */
0131: protected final static int SIGN = 2;
0132:
0133: /**
0134: * Possible {@link #state} value, signifying that
0135: * this signature object has been initialized for verification.
0136: */
0137: protected final static int VERIFY = 3;
0138:
0139: /**
0140: * Current state of this signature object.
0141: */
0142: protected int state = UNINITIALIZED;
0143:
0144: /**
0145: * Creates a Signature object for the specified algorithm.
0146: *
0147: * @param algorithm the standard string name of the algorithm.
0148: * See Appendix A in the <a href=
0149: * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0150: * Java Cryptography Architecture API Specification & Reference </a>
0151: * for information about standard algorithm names.
0152: */
0153: protected Signature(String algorithm) {
0154: this .algorithm = algorithm;
0155: }
0156:
0157: // name of the special signature alg
0158: private final static String RSA_SIGNATURE = "NONEwithRSA";
0159:
0160: // name of the equivalent cipher alg
0161: private final static String RSA_CIPHER = "RSA/ECB/PKCS1Padding";
0162:
0163: // all the services we need to lookup for compatibility with Cipher
0164: private final static List<ServiceId> rsaIds = Arrays
0165: .asList(new ServiceId[] {
0166: new ServiceId("Signature", "NONEwithRSA"),
0167: new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"),
0168: new ServiceId("Cipher", "RSA/ECB"),
0169: new ServiceId("Cipher", "RSA//PKCS1Padding"),
0170: new ServiceId("Cipher", "RSA"), });
0171:
0172: /**
0173: * Returns a Signature object that implements the specified signature
0174: * algorithm.
0175: *
0176: * <p> This method traverses the list of registered security Providers,
0177: * starting with the most preferred Provider.
0178: * A new Signature object encapsulating the
0179: * SignatureSpi implementation from the first
0180: * Provider that supports the specified algorithm is returned.
0181: *
0182: * <p> Note that the list of registered providers may be retrieved via
0183: * the {@link Security#getProviders() Security.getProviders()} method.
0184: *
0185: * @param algorithm the standard name of the algorithm requested.
0186: * See Appendix A in the <a href=
0187: * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0188: * Java Cryptography Architecture API Specification & Reference </a>
0189: * for information about standard algorithm names.
0190: *
0191: * @return the new Signature object.
0192: *
0193: * @exception NoSuchAlgorithmException if no Provider supports a
0194: * Signature implementation for the
0195: * specified algorithm.
0196: *
0197: * @see Provider
0198: */
0199: public static Signature getInstance(String algorithm)
0200: throws NoSuchAlgorithmException {
0201: List<Service> list;
0202: if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
0203: list = GetInstance.getServices(rsaIds);
0204: } else {
0205: list = GetInstance.getServices("Signature", algorithm);
0206: }
0207: Iterator<Service> t = list.iterator();
0208: if (t.hasNext() == false) {
0209: throw new NoSuchAlgorithmException(algorithm
0210: + " Signature not available");
0211: }
0212: // try services until we find an Spi or a working Signature subclass
0213: NoSuchAlgorithmException failure;
0214: do {
0215: Service s = t.next();
0216: if (isSpi(s)) {
0217: return new Delegate(s, t, algorithm);
0218: } else {
0219: // must be a subclass of Signature, disable dynamic selection
0220: try {
0221: Instance instance = GetInstance.getInstance(s,
0222: SignatureSpi.class);
0223: return getInstance(instance, algorithm);
0224: } catch (NoSuchAlgorithmException e) {
0225: failure = e;
0226: }
0227: }
0228: } while (t.hasNext());
0229: throw failure;
0230: }
0231:
0232: private static Signature getInstance(Instance instance,
0233: String algorithm) {
0234: Signature sig;
0235: if (instance.impl instanceof Signature) {
0236: sig = (Signature) instance.impl;
0237: } else {
0238: SignatureSpi spi = (SignatureSpi) instance.impl;
0239: sig = new Delegate(spi, algorithm);
0240: }
0241: sig.provider = instance.provider;
0242: return sig;
0243: }
0244:
0245: private final static Map<String, Boolean> signatureInfo;
0246:
0247: static {
0248: signatureInfo = new ConcurrentHashMap<String, Boolean>();
0249: Boolean TRUE = Boolean.TRUE;
0250: // pre-initialize with values for our SignatureSpi implementations
0251: signatureInfo.put("sun.security.provider.DSA$RawDSA", TRUE);
0252: signatureInfo
0253: .put("sun.security.provider.DSA$SHA1withDSA", TRUE);
0254: signatureInfo.put("sun.security.rsa.RSASignature$MD2withRSA",
0255: TRUE);
0256: signatureInfo.put("sun.security.rsa.RSASignature$MD5withRSA",
0257: TRUE);
0258: signatureInfo.put("sun.security.rsa.RSASignature$SHA1withRSA",
0259: TRUE);
0260: signatureInfo.put(
0261: "sun.security.rsa.RSASignature$SHA256withRSA", TRUE);
0262: signatureInfo.put(
0263: "sun.security.rsa.RSASignature$SHA384withRSA", TRUE);
0264: signatureInfo.put(
0265: "sun.security.rsa.RSASignature$SHA512withRSA", TRUE);
0266: signatureInfo.put("com.sun.net.ssl.internal.ssl.RSASignature",
0267: TRUE);
0268: signatureInfo.put("sun.security.pkcs11.P11Signature", TRUE);
0269: }
0270:
0271: private static boolean isSpi(Service s) {
0272: if (s.getType().equals("Cipher")) {
0273: // must be a CipherSpi, which we can wrap with the CipherAdapter
0274: return true;
0275: }
0276: String className = s.getClassName();
0277: Boolean result = signatureInfo.get(className);
0278: if (result == null) {
0279: try {
0280: Object instance = s.newInstance(null);
0281: // Signature extends SignatureSpi
0282: // so it is a "real" Spi if it is an
0283: // instance of SignatureSpi but not Signature
0284: boolean r = (instance instanceof SignatureSpi)
0285: && (instance instanceof Signature == false);
0286: if ((debug != null) && (r == false)) {
0287: debug.println("Not a SignatureSpi " + className);
0288: debug
0289: .println("Delayed provider selection may not be "
0290: + "available for algorithm "
0291: + s.getAlgorithm());
0292: }
0293: result = Boolean.valueOf(r);
0294: signatureInfo.put(className, result);
0295: } catch (Exception e) {
0296: // something is wrong, assume not an SPI
0297: return false;
0298: }
0299: }
0300: return result.booleanValue();
0301: }
0302:
0303: /**
0304: * Returns a Signature object that implements the specified signature
0305: * algorithm.
0306: *
0307: * <p> A new Signature object encapsulating the
0308: * SignatureSpi implementation from the specified provider
0309: * is returned. The specified provider must be registered
0310: * in the security provider list.
0311: *
0312: * <p> Note that the list of registered providers may be retrieved via
0313: * the {@link Security#getProviders() Security.getProviders()} method.
0314: *
0315: * @param algorithm the name of the algorithm requested.
0316: * See Appendix A in the <a href=
0317: * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0318: * Java Cryptography Architecture API Specification & Reference </a>
0319: * for information about standard algorithm names.
0320: *
0321: * @param provider the name of the provider.
0322: *
0323: * @return the new Signature object.
0324: *
0325: * @exception NoSuchAlgorithmException if a SignatureSpi
0326: * implementation for the specified algorithm is not
0327: * available from the specified provider.
0328: *
0329: * @exception NoSuchProviderException if the specified provider is not
0330: * registered in the security provider list.
0331: *
0332: * @exception IllegalArgumentException if the provider name is null
0333: * or empty.
0334: *
0335: * @see Provider
0336: */
0337: public static Signature getInstance(String algorithm,
0338: String provider) throws NoSuchAlgorithmException,
0339: NoSuchProviderException {
0340: if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
0341: // exception compatibility with existing code
0342: if ((provider == null) || (provider.length() == 0)) {
0343: throw new IllegalArgumentException("missing provider");
0344: }
0345: Provider p = Security.getProvider(provider);
0346: if (p == null) {
0347: throw new NoSuchProviderException("no such provider: "
0348: + provider);
0349: }
0350: return getInstanceRSA(p);
0351: }
0352: Instance instance = GetInstance.getInstance("Signature",
0353: SignatureSpi.class, algorithm, provider);
0354: return getInstance(instance, algorithm);
0355: }
0356:
0357: /**
0358: * Returns a Signature object that implements the specified
0359: * signature algorithm.
0360: *
0361: * <p> A new Signature object encapsulating the
0362: * SignatureSpi implementation from the specified Provider
0363: * object is returned. Note that the specified Provider object
0364: * does not have to be registered in the provider list.
0365: *
0366: * @param algorithm the name of the algorithm requested.
0367: * See Appendix A in the <a href=
0368: * "../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
0369: * Java Cryptography Architecture API Specification & Reference </a>
0370: * for information about standard algorithm names.
0371: *
0372: * @param provider the provider.
0373: *
0374: * @return the new Signature object.
0375: *
0376: * @exception NoSuchAlgorithmException if a SignatureSpi
0377: * implementation for the specified algorithm is not available
0378: * from the specified Provider object.
0379: *
0380: * @exception IllegalArgumentException if the provider is null.
0381: *
0382: * @see Provider
0383: *
0384: * @since 1.4
0385: */
0386: public static Signature getInstance(String algorithm,
0387: Provider provider) throws NoSuchAlgorithmException {
0388: if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
0389: // exception compatibility with existing code
0390: if (provider == null) {
0391: throw new IllegalArgumentException("missing provider");
0392: }
0393: return getInstanceRSA(provider);
0394: }
0395: Instance instance = GetInstance.getInstance("Signature",
0396: SignatureSpi.class, algorithm, provider);
0397: return getInstance(instance, algorithm);
0398: }
0399:
0400: // return an implementation for NONEwithRSA, which is a special case
0401: // because of the Cipher.RSA/ECB/PKCS1Padding compatibility wrapper
0402: private static Signature getInstanceRSA(Provider p)
0403: throws NoSuchAlgorithmException {
0404: // try Signature first
0405: Service s = p.getService("Signature", RSA_SIGNATURE);
0406: if (s != null) {
0407: Instance instance = GetInstance.getInstance(s,
0408: SignatureSpi.class);
0409: return getInstance(instance, RSA_SIGNATURE);
0410: }
0411: // check Cipher
0412: try {
0413: Cipher c = Cipher.getInstance(RSA_CIPHER, p);
0414: return new Delegate(new CipherAdapter(c), RSA_SIGNATURE);
0415: } catch (GeneralSecurityException e) {
0416: // throw Signature style exception message to avoid confusion,
0417: // but append Cipher exception as cause
0418: throw new NoSuchAlgorithmException("no such algorithm: "
0419: + RSA_SIGNATURE + " for provider " + p.getName(), e);
0420: }
0421: }
0422:
0423: /**
0424: * Returns the provider of this signature object.
0425: *
0426: * @return the provider of this signature object
0427: */
0428: public final Provider getProvider() {
0429: chooseFirstProvider();
0430: return this .provider;
0431: }
0432:
0433: void chooseFirstProvider() {
0434: // empty, overridden in Delegate
0435: }
0436:
0437: /**
0438: * Initializes this object for verification. If this method is called
0439: * again with a different argument, it negates the effect
0440: * of this call.
0441: *
0442: * @param publicKey the public key of the identity whose signature is
0443: * going to be verified.
0444: *
0445: * @exception InvalidKeyException if the key is invalid.
0446: */
0447: public final void initVerify(PublicKey publicKey)
0448: throws InvalidKeyException {
0449: engineInitVerify(publicKey);
0450: state = VERIFY;
0451: }
0452:
0453: /**
0454: * Initializes this object for verification, using the public key from
0455: * the given certificate.
0456: * <p>If the certificate is of type X.509 and has a <i>key usage</i>
0457: * extension field marked as critical, and the value of the <i>key usage</i>
0458: * extension field implies that the public key in
0459: * the certificate and its corresponding private key are not
0460: * supposed to be used for digital signatures, an
0461: * <code>InvalidKeyException</code> is thrown.
0462: *
0463: * @param certificate the certificate of the identity whose signature is
0464: * going to be verified.
0465: *
0466: * @exception InvalidKeyException if the public key in the certificate
0467: * is not encoded properly or does not include required parameter
0468: * information or cannot be used for digital signature purposes.
0469: * @since 1.3
0470: */
0471: public final void initVerify(Certificate certificate)
0472: throws InvalidKeyException {
0473: // If the certificate is of type X509Certificate,
0474: // we should check whether it has a Key Usage
0475: // extension marked as critical.
0476: if (certificate instanceof java.security.cert.X509Certificate) {
0477: // Check whether the cert has a key usage extension
0478: // marked as a critical extension.
0479: // The OID for KeyUsage extension is 2.5.29.15.
0480: X509Certificate cert = (X509Certificate) certificate;
0481: Set<String> critSet = cert.getCriticalExtensionOIDs();
0482:
0483: if (critSet != null && !critSet.isEmpty()
0484: && critSet.contains("2.5.29.15")) {
0485: boolean[] keyUsageInfo = cert.getKeyUsage();
0486: // keyUsageInfo[0] is for digitalSignature.
0487: if ((keyUsageInfo != null)
0488: && (keyUsageInfo[0] == false))
0489: throw new InvalidKeyException("Wrong key usage");
0490: }
0491: }
0492:
0493: PublicKey publicKey = certificate.getPublicKey();
0494: engineInitVerify(publicKey);
0495: state = VERIFY;
0496: }
0497:
0498: /**
0499: * Initialize this object for signing. If this method is called
0500: * again with a different argument, it negates the effect
0501: * of this call.
0502: *
0503: * @param privateKey the private key of the identity whose signature
0504: * is going to be generated.
0505: *
0506: * @exception InvalidKeyException if the key is invalid.
0507: */
0508: public final void initSign(PrivateKey privateKey)
0509: throws InvalidKeyException {
0510: engineInitSign(privateKey);
0511: state = SIGN;
0512: }
0513:
0514: /**
0515: * Initialize this object for signing. If this method is called
0516: * again with a different argument, it negates the effect
0517: * of this call.
0518: *
0519: * @param privateKey the private key of the identity whose signature
0520: * is going to be generated.
0521: *
0522: * @param random the source of randomness for this signature.
0523: *
0524: * @exception InvalidKeyException if the key is invalid.
0525: */
0526: public final void initSign(PrivateKey privateKey,
0527: SecureRandom random) throws InvalidKeyException {
0528: engineInitSign(privateKey, random);
0529: state = SIGN;
0530: }
0531:
0532: /**
0533: * Returns the signature bytes of all the data updated.
0534: * The format of the signature depends on the underlying
0535: * signature scheme.
0536: *
0537: * <p>A call to this method resets this signature object to the state
0538: * it was in when previously initialized for signing via a
0539: * call to <code>initSign(PrivateKey)</code>. That is, the object is
0540: * reset and available to generate another signature from the same
0541: * signer, if desired, via new calls to <code>update</code> and
0542: * <code>sign</code>.
0543: *
0544: * @return the signature bytes of the signing operation's result.
0545: *
0546: * @exception SignatureException if this signature object is not
0547: * initialized properly or if this signature algorithm is unable to
0548: * process the input data provided.
0549: */
0550: public final byte[] sign() throws SignatureException {
0551: if (state == SIGN) {
0552: return engineSign();
0553: }
0554: throw new SignatureException("object not initialized for "
0555: + "signing");
0556: }
0557:
0558: /**
0559: * Finishes the signature operation and stores the resulting signature
0560: * bytes in the provided buffer <code>outbuf</code>, starting at
0561: * <code>offset</code>.
0562: * The format of the signature depends on the underlying
0563: * signature scheme.
0564: *
0565: * <p>This signature object is reset to its initial state (the state it
0566: * was in after a call to one of the <code>initSign</code> methods) and
0567: * can be reused to generate further signatures with the same private key.
0568: *
0569: * @param outbuf buffer for the signature result.
0570: *
0571: * @param offset offset into <code>outbuf</code> where the signature is
0572: * stored.
0573: *
0574: * @param len number of bytes within <code>outbuf</code> allotted for the
0575: * signature.
0576: *
0577: * @return the number of bytes placed into <code>outbuf</code>.
0578: *
0579: * @exception SignatureException if this signature object is not
0580: * initialized properly, if this signature algorithm is unable to
0581: * process the input data provided, or if <code>len</code> is less
0582: * than the actual signature length.
0583: *
0584: * @since 1.2
0585: */
0586: public final int sign(byte[] outbuf, int offset, int len)
0587: throws SignatureException {
0588: if (outbuf == null) {
0589: throw new IllegalArgumentException("No output buffer given");
0590: }
0591: if (outbuf.length - offset < len) {
0592: throw new IllegalArgumentException(
0593: "Output buffer too small for specified offset and length");
0594: }
0595: if (state != SIGN) {
0596: throw new SignatureException("object not initialized for "
0597: + "signing");
0598: }
0599: return engineSign(outbuf, offset, len);
0600: }
0601:
0602: /**
0603: * Verifies the passed-in signature.
0604: *
0605: * <p>A call to this method resets this signature object to the state
0606: * it was in when previously initialized for verification via a
0607: * call to <code>initVerify(PublicKey)</code>. That is, the object is
0608: * reset and available to verify another signature from the identity
0609: * whose public key was specified in the call to <code>initVerify</code>.
0610: *
0611: * @param signature the signature bytes to be verified.
0612: *
0613: * @return true if the signature was verified, false if not.
0614: *
0615: * @exception SignatureException if this signature object is not
0616: * initialized properly, the passed-in signature is improperly
0617: * encoded or of the wrong type, if this signature algorithm is unable to
0618: * process the input data provided, etc.
0619: */
0620: public final boolean verify(byte[] signature)
0621: throws SignatureException {
0622: if (state == VERIFY) {
0623: return engineVerify(signature);
0624: }
0625: throw new SignatureException("object not initialized for "
0626: + "verification");
0627: }
0628:
0629: /**
0630: * Verifies the passed-in signature in the specified array
0631: * of bytes, starting at the specified offset.
0632: *
0633: * <p>A call to this method resets this signature object to the state
0634: * it was in when previously initialized for verification via a
0635: * call to <code>initVerify(PublicKey)</code>. That is, the object is
0636: * reset and available to verify another signature from the identity
0637: * whose public key was specified in the call to <code>initVerify</code>.
0638: *
0639: *
0640: * @param signature the signature bytes to be verified.
0641: * @param offset the offset to start from in the array of bytes.
0642: * @param length the number of bytes to use, starting at offset.
0643: *
0644: * @return true if the signature was verified, false if not.
0645: *
0646: * @exception SignatureException if this signature object is not
0647: * initialized properly, the passed-in signature is improperly
0648: * encoded or of the wrong type, if this signature algorithm is unable to
0649: * process the input data provided, etc.
0650: * @exception IllegalArgumentException if the <code>signature</code>
0651: * byte array is null, or the <code>offset</code> or <code>length</code>
0652: * is less than 0, or the sum of the <code>offset</code> and
0653: * <code>length</code> is greater than the length of the
0654: * <code>signature</code> byte array.
0655: * @since 1.4
0656: */
0657: public final boolean verify(byte[] signature, int offset, int length)
0658: throws SignatureException {
0659: if (state == VERIFY) {
0660: if ((signature == null) || (offset < 0) || (length < 0)
0661: || (offset + length > signature.length)) {
0662: throw new IllegalArgumentException("Bad arguments");
0663: }
0664:
0665: return engineVerify(signature, offset, length);
0666: }
0667: throw new SignatureException("object not initialized for "
0668: + "verification");
0669: }
0670:
0671: /**
0672: * Updates the data to be signed or verified by a byte.
0673: *
0674: * @param b the byte to use for the update.
0675: *
0676: * @exception SignatureException if this signature object is not
0677: * initialized properly.
0678: */
0679: public final void update(byte b) throws SignatureException {
0680: if (state == VERIFY || state == SIGN) {
0681: engineUpdate(b);
0682: } else {
0683: throw new SignatureException("object not initialized for "
0684: + "signature or verification");
0685: }
0686: }
0687:
0688: /**
0689: * Updates the data to be signed or verified, using the specified
0690: * array of bytes.
0691: *
0692: * @param data the byte array to use for the update.
0693: *
0694: * @exception SignatureException if this signature object is not
0695: * initialized properly.
0696: */
0697: public final void update(byte[] data) throws SignatureException {
0698: update(data, 0, data.length);
0699: }
0700:
0701: /**
0702: * Updates the data to be signed or verified, using the specified
0703: * array of bytes, starting at the specified offset.
0704: *
0705: * @param data the array of bytes.
0706: * @param off the offset to start from in the array of bytes.
0707: * @param len the number of bytes to use, starting at offset.
0708: *
0709: * @exception SignatureException if this signature object is not
0710: * initialized properly.
0711: */
0712: public final void update(byte[] data, int off, int len)
0713: throws SignatureException {
0714: if (state == SIGN || state == VERIFY) {
0715: engineUpdate(data, off, len);
0716: } else {
0717: throw new SignatureException("object not initialized for "
0718: + "signature or verification");
0719: }
0720: }
0721:
0722: /**
0723: * Updates the data to be signed or verified using the specified
0724: * ByteBuffer. Processes the <code>data.remaining()</code> bytes
0725: * starting at at <code>data.position()</code>.
0726: * Upon return, the buffer's position will be equal to its limit;
0727: * its limit will not have changed.
0728: *
0729: * @param data the ByteBuffer
0730: *
0731: * @exception SignatureException if this signature object is not
0732: * initialized properly.
0733: * @since 1.5
0734: */
0735: public final void update(ByteBuffer data) throws SignatureException {
0736: if ((state != SIGN) && (state != VERIFY)) {
0737: throw new SignatureException("object not initialized for "
0738: + "signature or verification");
0739: }
0740: if (data == null) {
0741: throw new NullPointerException();
0742: }
0743: engineUpdate(data);
0744: }
0745:
0746: /**
0747: * Returns the name of the algorithm for this signature object.
0748: *
0749: * @return the name of the algorithm for this signature object.
0750: */
0751: public final String getAlgorithm() {
0752: return this .algorithm;
0753: }
0754:
0755: /**
0756: * Returns a string representation of this signature object,
0757: * providing information that includes the state of the object
0758: * and the name of the algorithm used.
0759: *
0760: * @return a string representation of this signature object.
0761: */
0762: public String toString() {
0763: String initState = "";
0764: switch (state) {
0765: case UNINITIALIZED:
0766: initState = "<not initialized>";
0767: break;
0768: case VERIFY:
0769: initState = "<initialized for verifying>";
0770: break;
0771: case SIGN:
0772: initState = "<initialized for signing>";
0773: break;
0774: }
0775: return "Signature object: " + getAlgorithm() + initState;
0776: }
0777:
0778: /**
0779: * Sets the specified algorithm parameter to the specified value.
0780: * This method supplies a general-purpose mechanism through
0781: * which it is possible to set the various parameters of this object.
0782: * A parameter may be any settable parameter for the algorithm, such as
0783: * a parameter size, or a source of random bits for signature generation
0784: * (if appropriate), or an indication of whether or not to perform
0785: * a specific but optional computation. A uniform algorithm-specific
0786: * naming scheme for each parameter is desirable but left unspecified
0787: * at this time.
0788: *
0789: * @param param the string identifier of the parameter.
0790: * @param value the parameter value.
0791: *
0792: * @exception InvalidParameterException if <code>param</code> is an
0793: * invalid parameter for this signature algorithm engine,
0794: * the parameter is already set
0795: * and cannot be set again, a security exception occurs, and so on.
0796: *
0797: * @see #getParameter
0798: *
0799: * @deprecated Use
0800: * {@link #setParameter(java.security.spec.AlgorithmParameterSpec)
0801: * setParameter}.
0802: */
0803: @Deprecated
0804: public final void setParameter(String param, Object value)
0805: throws InvalidParameterException {
0806: engineSetParameter(param, value);
0807: }
0808:
0809: /**
0810: * Initializes this signature engine with the specified parameter set.
0811: *
0812: * @param params the parameters
0813: *
0814: * @exception InvalidAlgorithmParameterException if the given parameters
0815: * are inappropriate for this signature engine
0816: *
0817: * @see #getParameters
0818: */
0819: public final void setParameter(AlgorithmParameterSpec params)
0820: throws InvalidAlgorithmParameterException {
0821: engineSetParameter(params);
0822: }
0823:
0824: /**
0825: * Returns the parameters used with this signature object.
0826: *
0827: * <p>The returned parameters may be the same that were used to initialize
0828: * this signature, or may contain a combination of default and randomly
0829: * generated parameter values used by the underlying signature
0830: * implementation if this signature requires algorithm parameters but
0831: * was not initialized with any.
0832: *
0833: * @return the parameters used with this signature, or null if this
0834: * signature does not use any parameters.
0835: *
0836: * @see #setParameter(AlgorithmParameterSpec)
0837: * @since 1.4
0838: */
0839: public final AlgorithmParameters getParameters() {
0840: return engineGetParameters();
0841: }
0842:
0843: /**
0844: * Gets the value of the specified algorithm parameter. This method
0845: * supplies a general-purpose mechanism through which it is possible to
0846: * get the various parameters of this object. A parameter may be any
0847: * settable parameter for the algorithm, such as a parameter size, or
0848: * a source of random bits for signature generation (if appropriate),
0849: * or an indication of whether or not to perform a specific but optional
0850: * computation. A uniform algorithm-specific naming scheme for each
0851: * parameter is desirable but left unspecified at this time.
0852: *
0853: * @param param the string name of the parameter.
0854: *
0855: * @return the object that represents the parameter value, or null if
0856: * there is none.
0857: *
0858: * @exception InvalidParameterException if <code>param</code> is an invalid
0859: * parameter for this engine, or another exception occurs while
0860: * trying to get this parameter.
0861: *
0862: * @see #setParameter(String, Object)
0863: *
0864: * @deprecated
0865: */
0866: @Deprecated
0867: public final Object getParameter(String param)
0868: throws InvalidParameterException {
0869: return engineGetParameter(param);
0870: }
0871:
0872: /**
0873: * Returns a clone if the implementation is cloneable.
0874: *
0875: * @return a clone if the implementation is cloneable.
0876: *
0877: * @exception CloneNotSupportedException if this is called
0878: * on an implementation that does not support <code>Cloneable</code>.
0879: */
0880: public Object clone() throws CloneNotSupportedException {
0881: if (this instanceof Cloneable) {
0882: return super .clone();
0883: } else {
0884: throw new CloneNotSupportedException();
0885: }
0886: }
0887:
0888: /*
0889: * The following class allows providers to extend from SignatureSpi
0890: * rather than from Signature. It represents a Signature with an
0891: * encapsulated, provider-supplied SPI object (of type SignatureSpi).
0892: * If the provider implementation is an instance of SignatureSpi, the
0893: * getInstance() methods above return an instance of this class, with
0894: * the SPI object encapsulated.
0895: *
0896: * Note: All SPI methods from the original Signature class have been
0897: * moved up the hierarchy into a new class (SignatureSpi), which has
0898: * been interposed in the hierarchy between the API (Signature)
0899: * and its original parent (Object).
0900: */
0901:
0902: private static class Delegate extends Signature {
0903:
0904: // The provider implementation (delegate)
0905: // filled in once the provider is selected
0906: private SignatureSpi sigSpi;
0907:
0908: // lock for mutex during provider selection
0909: private final Object lock;
0910:
0911: // next service to try in provider selection
0912: // null once provider is selected
0913: private Service firstService;
0914:
0915: // remaining services to try in provider selection
0916: // null once provider is selected
0917: private Iterator<Service> serviceIterator;
0918:
0919: // constructor
0920: Delegate(SignatureSpi sigSpi, String algorithm) {
0921: super (algorithm);
0922: this .sigSpi = sigSpi;
0923: this .lock = null; // no lock needed
0924: }
0925:
0926: // used with delayed provider selection
0927: Delegate(Service service, Iterator<Service> iterator,
0928: String algorithm) {
0929: super (algorithm);
0930: this .firstService = service;
0931: this .serviceIterator = iterator;
0932: this .lock = new Object();
0933: }
0934:
0935: /**
0936: * Returns a clone if the delegate is cloneable.
0937: *
0938: * @return a clone if the delegate is cloneable.
0939: *
0940: * @exception CloneNotSupportedException if this is called on a
0941: * delegate that does not support <code>Cloneable</code>.
0942: */
0943: public Object clone() throws CloneNotSupportedException {
0944: chooseFirstProvider();
0945: if (sigSpi instanceof Cloneable) {
0946: SignatureSpi sigSpiClone = (SignatureSpi) sigSpi
0947: .clone();
0948: // Because 'algorithm' and 'provider' are private
0949: // members of our supertype, we must perform a cast to
0950: // access them.
0951: Signature that = new Delegate(sigSpiClone,
0952: ((Signature) this ).algorithm);
0953: that.provider = ((Signature) this ).provider;
0954: return that;
0955: } else {
0956: throw new CloneNotSupportedException();
0957: }
0958: }
0959:
0960: private static SignatureSpi newInstance(Service s)
0961: throws NoSuchAlgorithmException {
0962: if (s.getType().equals("Cipher")) {
0963: // must be NONEwithRSA
0964: try {
0965: Cipher c = Cipher.getInstance(RSA_CIPHER, s
0966: .getProvider());
0967: return new CipherAdapter(c);
0968: } catch (NoSuchPaddingException e) {
0969: throw new NoSuchAlgorithmException(e);
0970: }
0971: } else {
0972: Object o = s.newInstance(null);
0973: if (o instanceof SignatureSpi == false) {
0974: throw new NoSuchAlgorithmException(
0975: "Not a SignatureSpi: "
0976: + o.getClass().getName());
0977: }
0978: return (SignatureSpi) o;
0979: }
0980: }
0981:
0982: // max number of debug warnings to print from chooseFirstProvider()
0983: private static int warnCount = 10;
0984:
0985: /**
0986: * Choose the Spi from the first provider available. Used if
0987: * delayed provider selection is not possible because initSign()/
0988: * initVerify() is not the first method called.
0989: */
0990: void chooseFirstProvider() {
0991: if (sigSpi != null) {
0992: return;
0993: }
0994: synchronized (lock) {
0995: if (sigSpi != null) {
0996: return;
0997: }
0998: if (debug != null) {
0999: int w = --warnCount;
1000: if (w >= 0) {
1001: debug
1002: .println("Signature.init() not first method "
1003: + "called, disabling delayed provider selection");
1004: if (w == 0) {
1005: debug
1006: .println("Further warnings of this type will "
1007: + "be suppressed");
1008: }
1009: new Exception("Call trace").printStackTrace();
1010: }
1011: }
1012: Exception lastException = null;
1013: while ((firstService != null)
1014: || serviceIterator.hasNext()) {
1015: Service s;
1016: if (firstService != null) {
1017: s = firstService;
1018: firstService = null;
1019: } else {
1020: s = serviceIterator.next();
1021: }
1022: if (isSpi(s) == false) {
1023: continue;
1024: }
1025: try {
1026: sigSpi = newInstance(s);
1027: provider = s.getProvider();
1028: // not needed any more
1029: firstService = null;
1030: serviceIterator = null;
1031: return;
1032: } catch (NoSuchAlgorithmException e) {
1033: lastException = e;
1034: }
1035: }
1036: ProviderException e = new ProviderException(
1037: "Could not construct SignatureSpi instance");
1038: if (lastException != null) {
1039: e.initCause(lastException);
1040: }
1041: throw e;
1042: }
1043: }
1044:
1045: private void chooseProvider(int type, Key key,
1046: SecureRandom random) throws InvalidKeyException {
1047: synchronized (lock) {
1048: if (sigSpi != null) {
1049: init(sigSpi, type, key, random);
1050: return;
1051: }
1052: Exception lastException = null;
1053: while ((firstService != null)
1054: || serviceIterator.hasNext()) {
1055: Service s;
1056: if (firstService != null) {
1057: s = firstService;
1058: firstService = null;
1059: } else {
1060: s = serviceIterator.next();
1061: }
1062: // if provider says it does not support this key, ignore it
1063: if (s.supportsParameter(key) == false) {
1064: continue;
1065: }
1066: // if instance is not a SignatureSpi, ignore it
1067: if (isSpi(s) == false) {
1068: continue;
1069: }
1070: try {
1071: SignatureSpi spi = newInstance(s);
1072: init(spi, type, key, random);
1073: provider = s.getProvider();
1074: sigSpi = spi;
1075: firstService = null;
1076: serviceIterator = null;
1077: return;
1078: } catch (Exception e) {
1079: // NoSuchAlgorithmException from newInstance()
1080: // InvalidKeyException from init()
1081: // RuntimeException (ProviderException) from init()
1082: if (lastException == null) {
1083: lastException = e;
1084: }
1085: }
1086: }
1087: // no working provider found, fail
1088: if (lastException instanceof InvalidKeyException) {
1089: throw (InvalidKeyException) lastException;
1090: }
1091: if (lastException instanceof RuntimeException) {
1092: throw (RuntimeException) lastException;
1093: }
1094: String k = (key != null) ? key.getClass().getName()
1095: : "(null)";
1096: throw new InvalidKeyException(
1097: "No installed provider supports this key: " + k,
1098: lastException);
1099: }
1100: }
1101:
1102: private final static int I_PUB = 1;
1103: private final static int I_PRIV = 2;
1104: private final static int I_PRIV_SR = 3;
1105:
1106: private void init(SignatureSpi spi, int type, Key key,
1107: SecureRandom random) throws InvalidKeyException {
1108: switch (type) {
1109: case I_PUB:
1110: spi.engineInitVerify((PublicKey) key);
1111: break;
1112: case I_PRIV:
1113: spi.engineInitSign((PrivateKey) key);
1114: break;
1115: case I_PRIV_SR:
1116: spi.engineInitSign((PrivateKey) key, random);
1117: break;
1118: default:
1119: throw new AssertionError("Internal error: " + type);
1120: }
1121: }
1122:
1123: protected void engineInitVerify(PublicKey publicKey)
1124: throws InvalidKeyException {
1125: if (sigSpi != null) {
1126: sigSpi.engineInitVerify(publicKey);
1127: } else {
1128: chooseProvider(I_PUB, publicKey, null);
1129: }
1130: }
1131:
1132: protected void engineInitSign(PrivateKey privateKey)
1133: throws InvalidKeyException {
1134: if (sigSpi != null) {
1135: sigSpi.engineInitSign(privateKey);
1136: } else {
1137: chooseProvider(I_PRIV, privateKey, null);
1138: }
1139: }
1140:
1141: protected void engineInitSign(PrivateKey privateKey,
1142: SecureRandom sr) throws InvalidKeyException {
1143: if (sigSpi != null) {
1144: sigSpi.engineInitSign(privateKey, sr);
1145: } else {
1146: chooseProvider(I_PRIV_SR, privateKey, sr);
1147: }
1148: }
1149:
1150: protected void engineUpdate(byte b) throws SignatureException {
1151: chooseFirstProvider();
1152: sigSpi.engineUpdate(b);
1153: }
1154:
1155: protected void engineUpdate(byte[] b, int off, int len)
1156: throws SignatureException {
1157: chooseFirstProvider();
1158: sigSpi.engineUpdate(b, off, len);
1159: }
1160:
1161: protected void engineUpdate(ByteBuffer data) {
1162: chooseFirstProvider();
1163: sigSpi.engineUpdate(data);
1164: }
1165:
1166: protected byte[] engineSign() throws SignatureException {
1167: chooseFirstProvider();
1168: return sigSpi.engineSign();
1169: }
1170:
1171: protected int engineSign(byte[] outbuf, int offset, int len)
1172: throws SignatureException {
1173: chooseFirstProvider();
1174: return sigSpi.engineSign(outbuf, offset, len);
1175: }
1176:
1177: protected boolean engineVerify(byte[] sigBytes)
1178: throws SignatureException {
1179: chooseFirstProvider();
1180: return sigSpi.engineVerify(sigBytes);
1181: }
1182:
1183: protected boolean engineVerify(byte[] sigBytes, int offset,
1184: int length) throws SignatureException {
1185: chooseFirstProvider();
1186: return sigSpi.engineVerify(sigBytes, offset, length);
1187: }
1188:
1189: protected void engineSetParameter(String param, Object value)
1190: throws InvalidParameterException {
1191: chooseFirstProvider();
1192: sigSpi.engineSetParameter(param, value);
1193: }
1194:
1195: protected void engineSetParameter(AlgorithmParameterSpec params)
1196: throws InvalidAlgorithmParameterException {
1197: chooseFirstProvider();
1198: sigSpi.engineSetParameter(params);
1199: }
1200:
1201: protected Object engineGetParameter(String param)
1202: throws InvalidParameterException {
1203: chooseFirstProvider();
1204: return sigSpi.engineGetParameter(param);
1205: }
1206:
1207: protected AlgorithmParameters engineGetParameters() {
1208: chooseFirstProvider();
1209: return sigSpi.engineGetParameters();
1210: }
1211: }
1212:
1213: // adapter for RSA/ECB/PKCS1Padding ciphers
1214: private static class CipherAdapter extends SignatureSpi {
1215:
1216: private final Cipher cipher;
1217:
1218: private ByteArrayOutputStream data;
1219:
1220: CipherAdapter(Cipher cipher) {
1221: this .cipher = cipher;
1222: }
1223:
1224: protected void engineInitVerify(PublicKey publicKey)
1225: throws InvalidKeyException {
1226: cipher.init(Cipher.DECRYPT_MODE, publicKey);
1227: if (data == null) {
1228: data = new ByteArrayOutputStream(128);
1229: } else {
1230: data.reset();
1231: }
1232: }
1233:
1234: protected void engineInitSign(PrivateKey privateKey)
1235: throws InvalidKeyException {
1236: cipher.init(Cipher.ENCRYPT_MODE, privateKey);
1237: data = null;
1238: }
1239:
1240: protected void engineInitSign(PrivateKey privateKey,
1241: SecureRandom random) throws InvalidKeyException {
1242: cipher.init(Cipher.ENCRYPT_MODE, privateKey, random);
1243: data = null;
1244: }
1245:
1246: protected void engineUpdate(byte b) throws SignatureException {
1247: engineUpdate(new byte[] { b }, 0, 1);
1248: }
1249:
1250: protected void engineUpdate(byte[] b, int off, int len)
1251: throws SignatureException {
1252: if (data != null) {
1253: data.write(b, off, len);
1254: return;
1255: }
1256: byte[] out = cipher.update(b, off, len);
1257: if ((out != null) && (out.length != 0)) {
1258: throw new SignatureException(
1259: "Cipher unexpectedly returned data");
1260: }
1261: }
1262:
1263: protected byte[] engineSign() throws SignatureException {
1264: try {
1265: return cipher.doFinal();
1266: } catch (IllegalBlockSizeException e) {
1267: throw new SignatureException("doFinal() failed", e);
1268: } catch (BadPaddingException e) {
1269: throw new SignatureException("doFinal() failed", e);
1270: }
1271: }
1272:
1273: protected boolean engineVerify(byte[] sigBytes)
1274: throws SignatureException {
1275: try {
1276: byte[] out = cipher.doFinal(sigBytes);
1277: byte[] dataBytes = data.toByteArray();
1278: data.reset();
1279: return Arrays.equals(out, dataBytes);
1280: } catch (BadPaddingException e) {
1281: // e.g. wrong public key used
1282: // return false rather than throwing exception
1283: return false;
1284: } catch (IllegalBlockSizeException e) {
1285: throw new SignatureException("doFinal() failed", e);
1286: }
1287: }
1288:
1289: protected void engineSetParameter(String param, Object value)
1290: throws InvalidParameterException {
1291: throw new InvalidParameterException(
1292: "Parameters not supported");
1293: }
1294:
1295: protected Object engineGetParameter(String param)
1296: throws InvalidParameterException {
1297: throw new InvalidParameterException(
1298: "Parameters not supported");
1299: }
1300:
1301: }
1302:
1303: }
|