Signature.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /* Signature.java --- Signature Class
  2. Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package java.security;
  32. import gnu.java.lang.CPStringBuilder;
  33. import gnu.java.security.Engine;
  34. import java.lang.reflect.InvocationTargetException;
  35. import java.nio.ByteBuffer;
  36. import java.security.cert.Certificate;
  37. import java.security.cert.X509Certificate;
  38. import java.security.spec.AlgorithmParameterSpec;
  39. /**
  40. * <code>Signature</code> is used to provide an interface to digital signature
  41. * algorithms. Digital signatures provide authentication and data integrity of
  42. * digital data.
  43. *
  44. * <p>The GNU provider provides the NIST standard DSA which uses DSA and SHA-1.
  45. * It can be specified by SHA/DSA, SHA-1/DSA or its OID. If the RSA signature
  46. * algorithm is provided then it could be MD2/RSA. MD5/RSA, or SHA-1/RSA. The
  47. * algorithm must be specified because there is no default.</p>
  48. *
  49. * <p>Signature provides implementation-independent algorithms which are
  50. * requested by the user through the <code>getInstance()<?code> methods. It can
  51. * be requested by specifying just the algorithm name or by specifying both the
  52. * algorithm name and provider name.</p>
  53. *
  54. * <p>The three phases of using <code>Signature</code> are:</p>
  55. *
  56. * <ol>
  57. * <li>Initializing:
  58. * <ul>
  59. * <li>It must be initialized with a private key for signing.</li>
  60. * <li>It must be initialized with a public key for verifying.</li>
  61. * </li>
  62. *
  63. * <li>Updating:
  64. * <p>Update the bytes for signing or verifying with calls to update.</p>
  65. * </li>
  66. *
  67. * <li>Signing or Verify the signature on the currently stored bytes by
  68. * calling sign or verify.</li>
  69. * </ol>
  70. *
  71. * @author Mark Benvenuto (ivymccough@worldnet.att.net)
  72. */
  73. public abstract class Signature extends SignatureSpi
  74. {
  75. /** Service name for signatures. */
  76. private static final String SIGNATURE = "Signature";
  77. /**
  78. * Possible state value which signifies that this instance has not yet been
  79. * initialized.
  80. */
  81. protected static final int UNINITIALIZED = 0;
  82. /**
  83. * Possible state value which signifies that this instance has been
  84. * initialized for signing purposes.
  85. */
  86. protected static final int SIGN = 2;
  87. /**
  88. * Possible state value which signifies that this instance has been
  89. * initialized for verification purposes.
  90. */
  91. protected static final int VERIFY = 3;
  92. /** Current sate of this instance. */
  93. protected int state = UNINITIALIZED;
  94. private String algorithm;
  95. Provider provider;
  96. // Constructor.
  97. // ------------------------------------------------------------------------
  98. /**
  99. * Constructs a new <code>Signature</code> instance for a designated digital
  100. * signature algorithm.
  101. *
  102. * @param algorithm
  103. * the algorithm to use.
  104. */
  105. protected Signature(String algorithm)
  106. {
  107. this.algorithm = algorithm;
  108. state = UNINITIALIZED;
  109. }
  110. /**
  111. * Returns an instance of <code>Signature</code> representing the specified
  112. * signature.
  113. *
  114. * @param algorithm the algorithm to use.
  115. * @return a new instance repesenting the desired algorithm.
  116. * @throws NoSuchAlgorithmException if the algorithm is not implemented by any
  117. * provider.
  118. * @throws IllegalArgumentException if <code>algorithm</code> is
  119. * <code>null</code> or is an empty string.
  120. */
  121. public static Signature getInstance(String algorithm)
  122. throws NoSuchAlgorithmException
  123. {
  124. Provider[] p = Security.getProviders();
  125. NoSuchAlgorithmException lastException = null;
  126. for (int i = 0; i < p.length; i++)
  127. try
  128. {
  129. return getInstance(algorithm, p[i]);
  130. }
  131. catch (NoSuchAlgorithmException x)
  132. {
  133. lastException = x;
  134. }
  135. if (lastException != null)
  136. throw lastException;
  137. throw new NoSuchAlgorithmException(algorithm);
  138. }
  139. /**
  140. * Returns an instance of <code>Signature</code> representing the specified
  141. * signature from the named provider.
  142. *
  143. * @param algorithm the algorithm to use.
  144. * @param provider the name of the provider to use.
  145. * @return a new instance repesenting the desired algorithm.
  146. * @throws NoSuchProviderException if the named provider was not found.
  147. * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
  148. * named provider.
  149. * @throws IllegalArgumentException if either <code>algorithm</code> or
  150. * <code>provider</code> is <code>null</code> or empty.
  151. */
  152. public static Signature getInstance(String algorithm, String provider)
  153. throws NoSuchAlgorithmException, NoSuchProviderException
  154. {
  155. if (provider == null)
  156. throw new IllegalArgumentException("provider MUST NOT be null");
  157. provider = provider.trim();
  158. if (provider.length() == 0)
  159. throw new IllegalArgumentException("provider MUST NOT be empty");
  160. Provider p = Security.getProvider(provider);
  161. if (p == null)
  162. throw new NoSuchProviderException(provider);
  163. return getInstance(algorithm, p);
  164. }
  165. /**
  166. * Returns an instance of <code>Signature</code> representing the specified
  167. * signature from the specified {@link Provider}.
  168. *
  169. * @param algorithm the algorithm to use.
  170. * @param provider the {@link Provider} to use.
  171. * @return a new instance repesenting the desired algorithm.
  172. * @throws NoSuchAlgorithmException if the algorithm is not implemented by the
  173. * {@link Provider}.
  174. * @throws IllegalArgumentException if either <code>algorithm</code> or
  175. * <code>provider</code> is <code>null</code>, or if
  176. * <code>algorithm</code> is an empty string.
  177. */
  178. public static Signature getInstance(String algorithm, Provider provider)
  179. throws NoSuchAlgorithmException
  180. {
  181. CPStringBuilder sb = new CPStringBuilder("Signature algorithm [")
  182. .append(algorithm).append("] from provider[")
  183. .append(provider).append("] ");
  184. Object o;
  185. try
  186. {
  187. o = Engine.getInstance(SIGNATURE, algorithm, provider);
  188. }
  189. catch (InvocationTargetException x)
  190. {
  191. Throwable cause = x.getCause();
  192. if (cause instanceof NoSuchAlgorithmException)
  193. throw (NoSuchAlgorithmException) cause;
  194. if (cause == null)
  195. cause = x;
  196. sb.append("could not be created");
  197. NoSuchAlgorithmException y = new NoSuchAlgorithmException(sb.toString());
  198. y.initCause(cause);
  199. throw y;
  200. }
  201. Signature result;
  202. if (o instanceof SignatureSpi)
  203. result = new DummySignature((SignatureSpi) o, algorithm);
  204. else if (o instanceof Signature)
  205. {
  206. result = (Signature) o;
  207. result.algorithm = algorithm;
  208. }
  209. else
  210. {
  211. sb.append("is of an unexpected Type: ").append(o.getClass().getName());
  212. throw new NoSuchAlgorithmException(sb.toString());
  213. }
  214. result.provider = provider;
  215. return result;
  216. }
  217. /**
  218. * Returns the {@link Provider} of this instance.
  219. *
  220. * @return the {@link Provider} of this instance.
  221. */
  222. public final Provider getProvider()
  223. {
  224. return provider;
  225. }
  226. /**
  227. * Initializes this instance with the public key for verification purposes.
  228. *
  229. * @param publicKey
  230. * the public key to verify with.
  231. * @throws InvalidKeyException
  232. * if the key is invalid.
  233. */
  234. public final void initVerify(PublicKey publicKey) throws InvalidKeyException
  235. {
  236. state = VERIFY;
  237. engineInitVerify(publicKey);
  238. }
  239. /**
  240. * Verify a signature with a designated {@link Certificate}. This is a FIPS
  241. * 140-1 compatible method since it verifies a signature with a certificate.
  242. *
  243. * <p>If the {@link Certificate} is an X.509 one, has a <i>KeyUsage</i>
  244. * parameter and that parameter indicates this key is not to be used for
  245. * signing then an exception is thrown.</p>
  246. *
  247. * @param certificate
  248. * a {@link Certificate} containing a public key to verify with.
  249. * @throws InvalidKeyException if the key is invalid.
  250. */
  251. public final void initVerify(Certificate certificate)
  252. throws InvalidKeyException
  253. {
  254. state = VERIFY;
  255. if (certificate.getType().equals("X509"))
  256. {
  257. X509Certificate cert = (X509Certificate) certificate;
  258. boolean[]array = cert.getKeyUsage();
  259. if (array != null && array[0] == false)
  260. throw new InvalidKeyException(
  261. "KeyUsage of this Certificate indicates it cannot be used for digital signing");
  262. }
  263. this.initVerify(certificate.getPublicKey());
  264. }
  265. /**
  266. * Initializes this class with the private key for signing purposes.
  267. *
  268. * @param privateKey
  269. * the private key to sign with.
  270. * @throws InvalidKeyException
  271. * if the key is invalid.
  272. */
  273. public final void initSign(PrivateKey privateKey) throws InvalidKeyException
  274. {
  275. state = SIGN;
  276. engineInitSign(privateKey);
  277. }
  278. /**
  279. * Initializes this class with the private key and source of randomness for
  280. * signing purposes.
  281. *
  282. * @param privateKey
  283. * the private key to sign with.
  284. * @param random
  285. * the {@link SecureRandom} to use.
  286. * @throws InvalidKeyException
  287. * if the key is invalid.
  288. */
  289. public final void initSign(PrivateKey privateKey, SecureRandom random)
  290. throws InvalidKeyException
  291. {
  292. state = SIGN;
  293. engineInitSign(privateKey, random);
  294. }
  295. /**
  296. * Returns the signature bytes of all the data fed to this instance. The
  297. * format of the output depends on the underlying signature algorithm.
  298. *
  299. * @return the signature bytes.
  300. * @throws SignatureException
  301. * if the engine is not properly initialized.
  302. */
  303. public final byte[] sign() throws SignatureException
  304. {
  305. if (state == SIGN)
  306. return engineSign();
  307. else
  308. throw new SignatureException();
  309. }
  310. /**
  311. * Generates signature bytes of all the data fed to this instance and stores
  312. * it in the designated array. The format of the result depends on the
  313. * underlying signature algorithm.
  314. *
  315. * <p>After calling this method, the instance is reset to its initial state
  316. * and can then be used to generate additional signatures.</p>
  317. *
  318. * <p><b>IMPLEMENTATION NOTE:</b> Neither this method nor the GNU provider
  319. * will return partial digests. If <code>len</code> is less than the
  320. * signature length, this method will throw a {@link SignatureException}. If
  321. * it is greater than or equal then it is ignored.</p>
  322. *
  323. * @param outbuf
  324. * array of bytes of where to store the resulting signature bytes.
  325. * @param offset
  326. * the offset to start at in the array.
  327. * @param len
  328. * the number of the bytes to use in the array.
  329. * @return the real number of bytes used.
  330. * @throws SignatureException
  331. * if the engine is not properly initialized.
  332. * @since 1.2
  333. */
  334. public final int sign(byte[] outbuf, int offset, int len)
  335. throws SignatureException
  336. {
  337. if (state == SIGN)
  338. return engineSign(outbuf, offset, len);
  339. else
  340. throw new SignatureException();
  341. }
  342. /**
  343. * Verifies a designated signature.
  344. *
  345. * @param signature
  346. * the signature bytes to verify.
  347. * @return <code>true</code> if verified, <code>false</code> otherwise.
  348. * @throws SignatureException
  349. * if the engine is not properly initialized or the signature does
  350. * not check.
  351. */
  352. public final boolean verify(byte[]signature) throws SignatureException
  353. {
  354. if (state == VERIFY)
  355. return engineVerify(signature);
  356. else
  357. throw new SignatureException();
  358. }
  359. /**
  360. * Verifies a designated signature.
  361. *
  362. * @param signature
  363. * the signature bytes to verify.
  364. * @param offset
  365. * the offset to start at in the array.
  366. * @param length
  367. * the number of the bytes to use from the array.
  368. * @return <code>true</code> if verified, <code>false</code> otherwise.
  369. * @throws IllegalArgumentException
  370. * if the <code>signature</code> byte array is <code>null</code>,
  371. * or the <code>offset</code> or <code>length</code> is less
  372. * than <code>0</code>, or the sum of the <code>offset</code>
  373. * and <code>length</code> is greater than the length of the
  374. * <code>signature</code> byte array.
  375. * @throws SignatureException
  376. * if the engine is not properly initialized or the signature does
  377. * not check.
  378. */
  379. public final boolean verify(byte[] signature, int offset, int length)
  380. throws SignatureException
  381. {
  382. if (state != VERIFY)
  383. throw new SignatureException("illegal state");
  384. if (signature == null)
  385. throw new IllegalArgumentException("signature is null");
  386. if (offset < 0)
  387. throw new IllegalArgumentException("offset is less than 0");
  388. if (length < 0)
  389. throw new IllegalArgumentException("length is less than 0");
  390. if (offset + length < signature.length)
  391. throw new IllegalArgumentException("range is out of bounds");
  392. return engineVerify(signature, offset, length);
  393. }
  394. /**
  395. * Updates the data to be signed or verified with the specified byte.
  396. *
  397. * @param b
  398. * the byte to update with.
  399. * @throws SignatureException
  400. * if the engine is not properly initialized.
  401. */
  402. public final void update(byte b) throws SignatureException
  403. {
  404. if (state != UNINITIALIZED)
  405. engineUpdate(b);
  406. else
  407. throw new SignatureException();
  408. }
  409. /**
  410. * Updates the data to be signed or verified with the specified bytes.
  411. *
  412. * @param data
  413. * the array of bytes to use.
  414. * @throws SignatureException
  415. * if the engine is not properly initialized.
  416. */
  417. public final void update(byte[]data) throws SignatureException
  418. {
  419. if (state != UNINITIALIZED)
  420. engineUpdate(data, 0, data.length);
  421. else
  422. throw new SignatureException();
  423. }
  424. /**
  425. * Updates the data to be signed or verified with the specified bytes.
  426. *
  427. * @param data
  428. * an array of bytes to use.
  429. * @param off
  430. * the offset to start at in the array.
  431. * @param len
  432. * the number of bytes to use from the array.
  433. * @throws SignatureException
  434. * if the engine is not properly initialized.
  435. */
  436. public final void update(byte[]data, int off, int len)
  437. throws SignatureException
  438. {
  439. if (state != UNINITIALIZED)
  440. engineUpdate(data, off, len);
  441. else
  442. throw new SignatureException();
  443. }
  444. /**
  445. * Update this signature with the {@link java.nio.Buffer#remaining()}
  446. * bytes of the input buffer.
  447. *
  448. * @param input The input buffer.
  449. * @throws SignatureException If this instance was not properly
  450. * initialized.
  451. */
  452. public final void update(ByteBuffer input) throws SignatureException
  453. {
  454. if (state != UNINITIALIZED)
  455. engineUpdate(input);
  456. else
  457. throw new SignatureException("not initialized");
  458. }
  459. /**
  460. * Returns the name of the algorithm currently used. The names of algorithms
  461. * are usually SHA/DSA or SHA/RSA.
  462. *
  463. * @return name of algorithm.
  464. */
  465. public final String getAlgorithm()
  466. {
  467. return algorithm;
  468. }
  469. /**
  470. * Returns a rstring representation of this instance.
  471. *
  472. * @return a rstring representation of this instance.
  473. */
  474. public String toString()
  475. {
  476. return (algorithm + " Signature");
  477. }
  478. /**
  479. * Sets the specified algorithm parameter to the specified value.
  480. *
  481. * @param param
  482. * the parameter name.
  483. * @param value
  484. * the parameter value.
  485. * @throws InvalidParameterException
  486. * if the parameter is invalid, the parameter is already set and
  487. * can not be changed, a security exception occured, etc.
  488. * @deprecated use the other setParameter
  489. */
  490. public final void setParameter(String param, Object value)
  491. throws InvalidParameterException
  492. {
  493. engineSetParameter(param, value);
  494. }
  495. /**
  496. * Sets the signature engine with the specified {@link AlgorithmParameterSpec}.
  497. *
  498. * <p>By default, and unless overriden by the concrete SPI, this method always
  499. * throws an {@link UnsupportedOperationException}.</p>
  500. *
  501. * @param params
  502. * the parameters to use for intializing this instance.
  503. * @throws InvalidParameterException
  504. * if the parameter is invalid, the parameter is already set and
  505. * cannot be changed, a security exception occured, etc.
  506. */
  507. public final void setParameter(AlgorithmParameterSpec params)
  508. throws InvalidAlgorithmParameterException
  509. {
  510. engineSetParameter(params);
  511. }
  512. /**
  513. * Return the parameters of the algorithm used in this instance as an
  514. * {@link AlgorithmParameters}.
  515. *
  516. * @return the parameters used with this instance, or <code>null</code> if
  517. * this instance does not use any parameters.
  518. */
  519. public final AlgorithmParameters getParameters()
  520. {
  521. return engineGetParameters();
  522. }
  523. /**
  524. * Returns the value for the specified algorithm parameter.
  525. *
  526. * @param param
  527. * the parameter name.
  528. * @return the parameter value.
  529. * @throws InvalidParameterException
  530. * if the parameter is invalid.
  531. * @deprecated use the other getParameter
  532. */
  533. public final Object getParameter(String param)
  534. throws InvalidParameterException
  535. {
  536. return engineGetParameter(param);
  537. }
  538. /**
  539. * Returns a clone of this instance.
  540. *
  541. * @return a clone of this instace.
  542. * @throws CloneNotSupportedException
  543. * if the implementation does not support cloning.
  544. */
  545. public Object clone() throws CloneNotSupportedException
  546. {
  547. return super.clone();
  548. }
  549. }