1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46:
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60:
61: public abstract class RSA extends SignatureSpi implements Cloneable
62: {
63:
64:
65:
66:
67:
71: protected static final OID DIGEST_ALGORITHM = new OID("1.2.840.113549.2");
72:
73: protected final OID digestAlgorithm;
74: protected final MessageDigest md;
75: protected RSAPrivateKey signerKey;
76: protected RSAPublicKey verifierKey;
77:
78:
79:
80:
81: protected RSA(MessageDigest md, OID digestAlgorithm)
82: {
83: super();
84: this.md = md;
85: this.digestAlgorithm = digestAlgorithm;
86: }
87:
88:
89:
90:
91: public Object clone() throws CloneNotSupportedException
92: {
93: return super.clone();
94: }
95:
96: protected Object engineGetParameter(String param)
97: {
98: throw new UnsupportedOperationException("deprecated");
99: }
100:
101: protected void engineSetParameter(String param, Object value)
102: {
103: throw new UnsupportedOperationException("deprecated");
104: }
105:
106: protected void engineInitSign(PrivateKey privateKey)
107: throws InvalidKeyException
108: {
109: if (!(privateKey instanceof RSAPrivateKey))
110: throw new InvalidKeyException();
111: verifierKey = null;
112: signerKey = (RSAPrivateKey) privateKey;
113: }
114:
115: protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
116: throws InvalidKeyException
117: {
118:
119: engineInitSign(privateKey);
120: }
121:
122: protected void engineInitVerify(PublicKey publicKey)
123: throws InvalidKeyException
124: {
125: if (!(publicKey instanceof RSAPublicKey))
126: throw new InvalidKeyException();
127: signerKey = null;
128: verifierKey = (RSAPublicKey) publicKey;
129: }
130:
131: protected void engineUpdate(byte b) throws SignatureException
132: {
133: if (signerKey == null && verifierKey == null)
134: throw new SignatureException("not initialized");
135: md.update(b);
136: }
137:
138: protected void engineUpdate(byte[] buf, int off, int len)
139: throws SignatureException
140: {
141: if (signerKey == null && verifierKey == null)
142: throw new SignatureException("not initialized");
143: md.update(buf, off, len);
144: }
145:
146: protected byte[] engineSign() throws SignatureException
147: {
148: if (signerKey == null)
149: throw new SignatureException("not initialized for signing");
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162: ArrayList digestAlg = new ArrayList(2);
163: digestAlg.add(new DERValue(DER.OBJECT_IDENTIFIER, digestAlgorithm));
164: digestAlg.add(new DERValue(DER.NULL, null));
165: ArrayList digestInfo = new ArrayList(2);
166: digestInfo.add(new DERValue(DER.SEQUENCE, digestAlg));
167: digestInfo.add(new DERValue(DER.OCTET_STRING, md.digest()));
168: ByteArrayOutputStream out = new ByteArrayOutputStream();
169: try
170: {
171: DERWriter.write(out, new DERValue(DER.SEQUENCE, digestInfo));
172: }
173: catch (IOException ioe)
174: {
175: throw new SignatureException(ioe.toString());
176: }
177: byte[] buf = out.toByteArray();
178: md.reset();
179:
180:
181: int k = signerKey.getModulus().bitLength();
182: k = (k >>> 3) + ((k & 7) == 0 ? 0 : 1);
183: if (buf.length < k - 3)
184: {
185: throw new SignatureException("RSA modulus too small");
186: }
187: byte[] d = new byte[k];
188:
189:
190:
191: d[1] = 0x01;
192: for (int i = 2; i < k - buf.length - 1; i++)
193: d[i] = (byte) 0xFF;
194: System.arraycopy(buf, 0, d, k - buf.length, buf.length);
195:
196: BigInteger eb = new BigInteger(d);
197:
198: byte[] ed = eb.modPow(signerKey.getPrivateExponent(),
199: signerKey.getModulus()).toByteArray();
200:
201:
202: if (ed.length < k)
203: {
204: byte[] b = new byte[k];
205: System.arraycopy(eb, 0, b, k - ed.length, ed.length);
206: ed = b;
207: }
208: else if (ed.length > k)
209: {
210: if (ed.length != k + 1)
211: {
212: throw new SignatureException("modPow result is larger than the modulus");
213: }
214:
215: byte[] b = new byte[k];
216: System.arraycopy(ed, 1, b, 0, k);
217: ed = b;
218: }
219:
220: return ed;
221: }
222:
223: protected int engineSign(byte[] out, int off, int len)
224: throws SignatureException
225: {
226: if (out == null || off < 0 || len < 0 || off+len > out.length)
227: throw new SignatureException("illegal output argument");
228: byte[] result = engineSign();
229: if (result.length > len)
230: throw new SignatureException("not enough space for signature");
231: System.arraycopy(result, 0, out, off, result.length);
232: return result.length;
233: }
234:
235: protected boolean engineVerify(byte[] sig) throws SignatureException
236: {
237: if (verifierKey == null)
238: throw new SignatureException("not initialized for verifying");
239: if (sig == null)
240: throw new SignatureException("no signature specified");
241: int k = verifierKey.getModulus().bitLength();
242: k = (k >>> 3) + ((k & 7) == 0 ? 0 : 1);
243: if (sig.length != k)
244: throw new SignatureException("signature is the wrong size (expecting "
245: + k + " bytes, got " + sig.length + ")");
246: BigInteger ed = new BigInteger(1, sig);
247: byte[] eb = ed.modPow(verifierKey.getPublicExponent(),
248: verifierKey.getModulus()).toByteArray();
249:
250: int i = 0;
251: if (eb[0] == 0x00)
252: {
253: for (i = 1; i < eb.length && eb[i] == 0x00; i++);
254: if (i == 1)
255: throw new SignatureException("wrong RSA padding");
256: i--;
257: }
258: else if (eb[0] == 0x01)
259: {
260: for (i = 1; i < eb.length && eb[i] != 0x00; i++)
261: if (eb[i] != (byte) 0xFF)
262: throw new IllegalArgumentException("wrong RSA padding");
263: }
264: else
265: throw new SignatureException("wrong RSA padding type");
266:
267: byte[] d = new byte[eb.length-i-1];
268: System.arraycopy(eb, i+1, d, 0, eb.length-i-1);
269:
270: DERReader der = new DERReader(d);
271: try
272: {
273: DERValue val = der.read();
274: if (val.getTag() != DER.SEQUENCE)
275: throw new SignatureException("failed to parse DigestInfo");
276: val = der.read();
277: if (val.getTag() != DER.SEQUENCE)
278: throw new SignatureException("failed to parse DigestAlgorithmIdentifier");
279: boolean sequenceIsBer = val.getLength() == 0;
280: val = der.read();
281: if (val.getTag() != DER.OBJECT_IDENTIFIER)
282: throw new SignatureException("failed to parse object identifier");
283: if (!val.getValue().equals(digestAlgorithm))
284: throw new SignatureException("digest algorithms do not match");
285: val = der.read();
286:
287: if (val.getTag() != DER.NULL)
288: throw new SignatureException("cannot handle digest parameters");
289: if (sequenceIsBer)
290: der.skip(1);
291: val = der.read();
292: if (val.getTag() != DER.OCTET_STRING)
293: throw new SignatureException("failed to parse Digest");
294: return MessageDigest.isEqual(md.digest(), (byte[]) val.getValue());
295: }
296: catch (IOException ioe)
297: {
298: throw new SignatureException(ioe.toString());
299: }
300: }
301:
302: protected boolean engineVerify(byte[] sig, int off, int len)
303: throws SignatureException
304: {
305: if (sig == null || off < 0 || len < 0 || off+len > sig.length)
306: throw new SignatureException("illegal parameter");
307: byte[] buf = new byte[len];
308: System.arraycopy(sig, off, buf, 0, len);
309: return engineVerify(buf);
310: }
311: }