Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / gnu / java / security / provider / RSA.java
blobc3cfbbf79f1a546d41fdb48b4b96d8aa0a9e7f85
1 /* RSA.java -- RSA PKCS#1 signatures.
2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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.
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.
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.
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.
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. */
39 package gnu.java.security.provider;
41 import gnu.java.security.OID;
42 import gnu.java.security.der.DER;
43 import gnu.java.security.der.DERReader;
44 import gnu.java.security.der.DERValue;
45 import gnu.java.security.der.DERWriter;
47 import java.io.ByteArrayOutputStream;
48 import java.io.IOException;
49 import java.math.BigInteger;
50 import java.security.InvalidKeyException;
51 import java.security.MessageDigest;
52 import java.security.PrivateKey;
53 import java.security.PublicKey;
54 import java.security.SecureRandom;
55 import java.security.SignatureException;
56 import java.security.SignatureSpi;
57 import java.security.interfaces.RSAPrivateKey;
58 import java.security.interfaces.RSAPublicKey;
59 import java.util.ArrayList;
61 public abstract class RSA extends SignatureSpi implements Cloneable
64 // Constants and fields.
65 // -------------------------------------------------------------------------
67 /**
68 * digestAlgorithm OBJECT IDENTIFIER ::=
69 * { iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) }
71 protected static final OID DIGEST_ALGORITHM = new OID("1.2.840.113549.2");
73 protected final OID digestAlgorithm;
74 protected final MessageDigest md;
75 protected RSAPrivateKey signerKey;
76 protected RSAPublicKey verifierKey;
78 // Constructor.
79 // -------------------------------------------------------------------------
81 protected RSA(MessageDigest md, OID digestAlgorithm)
83 super();
84 this.md = md;
85 this.digestAlgorithm = digestAlgorithm;
88 // Instance methods.
89 // -------------------------------------------------------------------------
91 public Object clone() throws CloneNotSupportedException
93 return super.clone();
96 protected Object engineGetParameter(String param)
98 throw new UnsupportedOperationException("deprecated");
101 protected void engineSetParameter(String param, Object value)
103 throw new UnsupportedOperationException("deprecated");
106 protected void engineInitSign(PrivateKey privateKey)
107 throws InvalidKeyException
109 if (!(privateKey instanceof RSAPrivateKey))
110 throw new InvalidKeyException();
111 verifierKey = null;
112 signerKey = (RSAPrivateKey) privateKey;
115 protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
116 throws InvalidKeyException
118 // This class does not need random bytes.
119 engineInitSign(privateKey);
122 protected void engineInitVerify(PublicKey publicKey)
123 throws InvalidKeyException
125 if (!(publicKey instanceof RSAPublicKey))
126 throw new InvalidKeyException();
127 signerKey = null;
128 verifierKey = (RSAPublicKey) publicKey;
131 protected void engineUpdate(byte b) throws SignatureException
133 if (signerKey == null && verifierKey == null)
134 throw new SignatureException("not initialized");
135 md.update(b);
138 protected void engineUpdate(byte[] buf, int off, int len)
139 throws SignatureException
141 if (signerKey == null && verifierKey == null)
142 throw new SignatureException("not initialized");
143 md.update(buf, off, len);
146 protected byte[] engineSign() throws SignatureException
148 if (signerKey == null)
149 throw new SignatureException("not initialized for signing");
151 // The signature will be the RSA encrypted BER representation of
152 // the following:
154 // DigestInfo ::= SEQUENCE {
155 // digestAlgorithm DigestAlgorithmIdentifier,
156 // digest Digest }
158 // DigestAlgorithmIdentifier ::= AlgorithmIdentifier
160 // Digest ::= OCTET STRING
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();
171 DERWriter.write(out, new DERValue(DER.SEQUENCE, digestInfo));
173 catch (IOException ioe)
175 throw new SignatureException(ioe.toString());
177 byte[] buf = out.toByteArray();
178 md.reset();
180 // k = octect length of the modulus.
181 int k = signerKey.getModulus().bitLength();
182 k = (k >>> 3) + ((k & 7) == 0 ? 0 : 1);
183 if (buf.length < k - 3)
185 throw new SignatureException("RSA modulus too small");
187 byte[] d = new byte[k];
189 // Padding type 1:
190 // 00 | 01 | FF | ... | FF | 00 | D
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);
196 BigInteger eb = new BigInteger(d);
198 byte[] ed = eb.modPow(signerKey.getPrivateExponent(),
199 signerKey.getModulus()).toByteArray();
201 // Ensure output is k octets long.
202 if (ed.length < k)
204 byte[] b = new byte[k];
205 System.arraycopy(eb, 0, b, k - ed.length, ed.length);
206 ed = b;
208 else if (ed.length > k)
210 if (ed.length != k + 1)
212 throw new SignatureException("modPow result is larger than the modulus");
214 // Maybe an extra 00 octect.
215 byte[] b = new byte[k];
216 System.arraycopy(ed, 1, b, 0, k);
217 ed = b;
220 return ed;
223 protected int engineSign(byte[] out, int off, int len)
224 throws SignatureException
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;
235 protected boolean engineVerify(byte[] sig) throws SignatureException
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();
250 int i = 0;
251 if (eb[0] == 0x00)
253 for (i = 1; i < eb.length && eb[i] == 0x00; i++);
254 if (i == 1)
255 throw new SignatureException("wrong RSA padding");
256 i--;
258 else if (eb[0] == 0x01)
260 for (i = 1; i < eb.length && eb[i] != 0x00; i++)
261 if (eb[i] != (byte) 0xFF)
262 throw new IllegalArgumentException("wrong RSA padding");
264 else
265 throw new SignatureException("wrong RSA padding type");
267 byte[] d = new byte[eb.length-i-1];
268 System.arraycopy(eb, i+1, d, 0, eb.length-i-1);
270 DERReader der = new DERReader(d);
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 // We should never see parameters here, since they are never used.
287 if (val.getTag() != DER.NULL)
288 throw new SignatureException("cannot handle digest parameters");
289 if (sequenceIsBer)
290 der.skip(1); // end-of-sequence byte.
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());
296 catch (IOException ioe)
298 throw new SignatureException(ioe.toString());
302 protected boolean engineVerify(byte[] sig, int off, int len)
303 throws SignatureException
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);