001: /*
002: *
003: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025:
026: package com.sun.j2me.crypto;
027:
028: import java.security.SignatureException;
029: import java.security.PrivateKey;
030: import java.security.PublicKey;
031:
032: import java.security.MessageDigest;
033: import java.security.GeneralSecurityException;
034:
035: /**
036: * Implements RSA Signatures.
037: */
038: public class RSASignature {
039:
040: /** Current message digest. */
041: MessageDigest md = null;
042:
043: /** Current cipher. */
044: Cipher c = null;
045:
046: /** Current key. */
047: RSAKey k = null;
048:
049: /** Signature prefix. */
050: byte[] prefix;
051:
052: /**
053: * Constructs an RSA signature object that uses the specified
054: * signature algorithm.
055: *
056: * @param sigPrefix Prefix for the signature
057: * @param messageDigest Message digest for the signature
058: *
059: * @exception NoSuchAlgorithmException if RSA is
060: * not available in the caller's environment.
061: */
062: RSASignature(byte[] sigPrefix, MessageDigest messageDigest)
063: throws NoSuchAlgorithmException {
064: prefix = sigPrefix;
065: md = messageDigest;
066:
067: try {
068: c = Cipher.getNewInstance("RSA");
069: } catch (NoSuchPaddingException e) {
070: // we used the default mode and padding this should not happen
071: throw new NoSuchAlgorithmException();
072: }
073: }
074:
075: /**
076: * Initializes the <CODE>RSASignature</CODE> object with the appropriate
077: * <CODE>Key</CODE> for signature verification.
078: *
079: * @param theKey the key object to use for verification
080: *
081: * @exception InvalidKeyException if the key type is inconsistent
082: * with the mode or signature implementation.
083: */
084: public void initVerify(PublicKey publicKey)
085: throws InvalidKeyException {
086:
087: if (!(publicKey instanceof RSAPublicKey)) {
088: throw new InvalidKeyException();
089: }
090:
091: c.init(Cipher.DECRYPT_MODE, publicKey);
092: k = (RSAKey) publicKey;
093: }
094:
095: /**
096: * Accumulates a signature of the input data. When this method is used,
097: * temporary storage of intermediate results is required. This method
098: * should only be used if all the input data required for the signature
099: * is not available in one byte array. The sign() or verify() method is
100: * recommended whenever possible.
101: *
102: * @param inBuf the input buffer of data to be signed
103: * @param inOff starting offset within the input buffer for data to
104: * be signed
105: * @param inLen the byte length of data to be signed
106: *
107: * @exception SignatureException if this signature object is not
108: * initialized properly.
109: */
110: public void update(byte[] b, int off, int len)
111: throws SignatureException {
112: if (k == null) {
113: throw new SignatureException("Illegal State");
114: }
115:
116: md.update(b, off, len);
117: }
118:
119: /**
120: * Verifies the signature of all/last input data against the passed
121: * in signature. A call to this method also resets this signature
122: * object to the state it was in when previously initialized via a
123: * call to init(). That is, the object is reset and available to
124: * verify another message.
125: *
126: * @param sigBuf the input buffer containing signature data
127: * @param sigOff starting offset within the sigBuf where signature
128: * data begins
129: * @param sigLen byte length of signature data
130: *
131: * @return true if signature verifies, false otherwise
132: *
133: * @exception SignatureException if this signature object is not
134: * initialized properly, or the passed-in signature is improperly
135: * encoded or of the wrong type, etc.
136: */
137: public boolean verify(byte[] sigBuf, int sigOff, int sigLen)
138: throws SignatureException {
139: if (k == null || !(k instanceof RSAPublicKey)) {
140: throw new SignatureException("Illegal State");
141: }
142:
143: byte[] res = null;
144: int val;
145: byte[] digest = new byte[md.getDigestLength()];
146:
147: try {
148: md.digest(digest, 0, digest.length);
149: res = new byte[k.getModulusLen()];
150: val = c.doFinal(sigBuf, sigOff, sigLen, res, 0);
151: } catch (IllegalArgumentException iae) {
152: throw new SignatureException(iae.getMessage());
153: } catch (GeneralSecurityException e) {
154: return false;
155: }
156:
157: int size = prefix.length + md.getDigestLength();
158:
159: if (val != size) {
160: return false;
161: }
162:
163: // Match the prefix corresponding to the signature algorithm
164: for (int i = 0; i < prefix.length; i++) {
165: if (res[i] != prefix[i]) {
166: return false;
167: }
168: }
169:
170: for (int i = prefix.length; i < size; i++) {
171: if (res[i] != digest[i - prefix.length]) {
172: return false;
173: }
174: }
175:
176: return true;
177: }
178: }
|