View | Details | Return to bug 26067 | Differences between
and this patch

Collapse All | Expand All

(-)Properties.java (-60 / +51 lines)
Lines 49-60 Link Here
49
import java.util.logging.Logger;
49
import java.util.logging.Logger;
50
50
51
/**
51
/**
52
 * <p>A global object containing build-specific properties that affect the
52
 * A global object containing build-specific properties that affect the
53
 * behaviour of the generated binaries from this library.</p>
53
 * behaviour of the generated binaries from this library.
54
 */
54
 */
55
public final class Properties
55
public final class Properties
56
{
56
{
57
  private static final Logger log = Logger.getLogger(Properties.class.getName());
57
  private static final Logger log = Logger.getLogger(Properties.class.getName());
58
58
  public static final String VERSION = "gnu.crypto.version";
59
  public static final String VERSION = "gnu.crypto.version";
59
60
60
  public static final String PROPERTIES_FILE = "gnu.crypto.properties.file";
61
  public static final String PROPERTIES_FILE = "gnu.crypto.properties.file";
Lines 79-87 Link Here
79
80
80
  private boolean doRSABlinding = true;
81
  private boolean doRSABlinding = true;
81
82
82
  // Constructor(s)
83
  // -------------------------------------------------------------------------
84
85
  /** Trivial constructor to enforce Singleton pattern. */
83
  /** Trivial constructor to enforce Singleton pattern. */
86
  private Properties()
84
  private Properties()
87
  {
85
  {
Lines 89-106 Link Here
89
    init();
87
    init();
90
  }
88
  }
91
89
92
  // Class methods
93
  // -------------------------------------------------------------------------
94
95
  /**
90
  /**
96
   * <p>Returns the string representation of the library global configuration
91
   * Returns the string representation of the library global configuration
97
   * property with the designated <code>key</code>.</p>
92
   * property with the designated <code>key</code>.
98
   *
93
   * 
99
   * @param key the case-insensitive, non-null and non-empty name of a
94
   * @param key the case-insensitive, non-null and non-empty name of a
100
   * configuration property.
95
   *          configuration property.
101
   * @return the string representation of the designated property, or
96
   * @return the string representation of the designated property, or
102
   * <code>null</code> if such property is not yet set, or <code>key</code> is
97
   *         <code>null</code> if such property is not yet set, or
103
   * empty.
98
   *         <code>key</code> is empty.
104
   */
99
   */
105
  public static final synchronized String getProperty(String key)
100
  public static final synchronized String getProperty(String key)
106
  {
101
  {
Lines 116-128 Link Here
116
  }
111
  }
117
112
118
  /**
113
  /**
119
   * <p>Sets the value of a designated library global configuration property,
114
   * Sets the value of a designated library global configuration property, to a
120
   * to a string representation of what should be a legal value.</p>
115
   * string representation of what should be a legal value.
121
   *
116
   * 
122
   * @param key the case-insensitive, non-null and non-empty name of a
117
   * @param key the case-insensitive, non-null and non-empty name of a
123
   * configuration property.
118
   *          configuration property.
124
   * @param value the non-null, non-empty string representation of a legal
119
   * @param value the non-null, non-empty string representation of a legal value
125
   * value of the configuration property named by <code>key</code>.
120
   *          of the configuration property named by <code>key</code>.
126
   */
121
   */
127
  public static final synchronized void setProperty(String key, String value)
122
  public static final synchronized void setProperty(String key, String value)
128
  {
123
  {
Lines 153-165 Link Here
153
  }
148
  }
154
149
155
  /**
150
  /**
156
   * <p>A convenience method that returns, as a boolean, the library global
151
   * A convenience method that returns, as a boolean, the library global
157
   * configuration property indicating if the default Pseudo Random Number
152
   * configuration property indicating if the default Pseudo Random Number
158
   * Generator produces, or not, the same bit stream when instantiated.</p>
153
   * Generator produces, or not, the same bit stream when instantiated.
159
   *
154
   * 
160
   * @return <code>true</code> if the default PRNG produces the same bit stream
155
   * @return <code>true</code> if the default PRNG produces the same bit
161
   * with every VM instance. Returns <code>false</code> if the default PRNG is
156
   *         stream with every VM instance. Returns <code>false</code> if the
162
   * seeded with the time of day of its first invocation.
157
   *         default PRNG is seeded with the time of day of its first
158
   *         invocation.
163
   */
159
   */
164
  public static final synchronized boolean isReproducible()
160
  public static final synchronized boolean isReproducible()
165
  {
161
  {
Lines 170-184 Link Here
170
  }
166
  }
171
167
172
  /**
168
  /**
173
   * <p>A convenience method that returns, as a boolean, the library global
169
   * A convenience method that returns, as a boolean, the library global
174
   * configuration property indicating if the implementations of symmetric
170
   * configuration property indicating if the implementations of symmetric key
175
   * key block ciphers check, or not, for possible/potential weak and semi-weak
171
   * block ciphers check, or not, for possible/potential weak and semi-weak keys
176
   * keys that may be produced in the course of generating round encryption
172
   * that may be produced in the course of generating round encryption and/or
177
   * and/or decryption keys.</p>
173
   * decryption keys.
178
   *
174
   * 
179
   * @return <code>true</code> if the cipher implementations check for weak and
175
   * @return <code>true</code> if the cipher implementations check for weak
180
   * semi-weak keys. Returns <code>false</code> if the cipher implementations
176
   *         and semi-weak keys. Returns <code>false</code> if the cipher
181
   * do not check for weak or semi-weak keys.
177
   *         implementations do not check for weak or semi-weak keys.
182
   */
178
   */
183
  public static final synchronized boolean checkForWeakKeys()
179
  public static final synchronized boolean checkForWeakKeys()
184
  {
180
  {
Lines 189-201 Link Here
189
  }
185
  }
190
186
191
  /**
187
  /**
192
   * <p>A convenience method that returns, as a boolean, the library global
188
   * A convenience method that returns, as a boolean, the library global
193
   * configuration property indicating if RSA decryption (RSADP primitive),
189
   * configuration property indicating if RSA decryption (RSADP primitive),
194
   * does, or not, blinding against timing attacks.</p>
190
   * does, or not, blinding against timing attacks.
195
   *
191
   * 
196
   * @return <code>true</code> if the RSA decryption primitive includes a
192
   * @return <code>true</code> if the RSA decryption primitive includes a
197
   * blinding operation. Returns <code>false</code> if the RSA decryption
193
   *         blinding operation. Returns <code>false</code> if the RSA
198
   * primitive does not include the additional blinding operation.
194
   *         decryption primitive does not include the additional blinding
195
   *         operation.
199
   */
196
   */
200
  public static final synchronized boolean doRSABlinding()
197
  public static final synchronized boolean doRSABlinding()
201
  {
198
  {
Lines 206-216 Link Here
206
  }
203
  }
207
204
208
  /**
205
  /**
209
   * <p>A convenience method to set the global property for reproducibility of
206
   * A convenience method to set the global property for reproducibility of the
210
   * the default PRNG bit stream output.</p>
207
   * default PRNG bit stream output.
211
   *
208
   * 
212
   * @param value if <code>true</code> then the default PRNG bit stream output
209
   * @param value if <code>true</code> then the default PRNG bit stream output
213
   * is the same with every invocation of the VM.
210
   *          is the same with every invocation of the VM.
214
   */
211
   */
215
  public static final synchronized void setReproducible(final boolean value)
212
  public static final synchronized void setReproducible(final boolean value)
216
  {
213
  {
Lines 222-233 Link Here
222
  }
219
  }
223
220
224
  /**
221
  /**
225
   * <p>A convenience method to set the global property for checking for weak
222
   * A convenience method to set the global property for checking for weak and
226
   * and semi-weak cipher keys.</p>
223
   * semi-weak cipher keys.
227
   *
224
   * 
228
   * @param value if <code>true</code> then the cipher implementations will
225
   * @param value if <code>true</code> then the cipher implementations will
229
   * invoke additional checks for weak and semi-weak key values that may get
226
   *          invoke additional checks for weak and semi-weak key values that
230
   * generated.
227
   *          may get generated.
231
   */
228
   */
232
  public static final synchronized void setCheckForWeakKeys(final boolean value)
229
  public static final synchronized void setCheckForWeakKeys(final boolean value)
233
  {
230
  {
Lines 239-249 Link Here
239
  }
236
  }
240
237
241
  /**
238
  /**
242
   * <p>A convenience method to set the global property fo adding a blinding
239
   * A convenience method to set the global property fo adding a blinding
243
   * operation when executing the RSA decryption primitive.</p>
240
   * operation when executing the RSA decryption primitive.
244
   *
241
   * 
245
   * @param value if <code>true</code> then the code for performing the RSA
242
   * @param value if <code>true</code> then the code for performing the RSA
246
   * decryption primitive will include a blinding operation.
243
   *          decryption primitive will include a blinding operation.
247
   */
244
   */
248
  public static final synchronized void setDoRSABlinding(final boolean value)
245
  public static final synchronized void setDoRSABlinding(final boolean value)
249
  {
246
  {
Lines 261-275 Link Here
261
    return singleton;
258
    return singleton;
262
  }
259
  }
263
260
264
  // Instance methods
265
  // -------------------------------------------------------------------------
266
  private void init()
261
  private void init()
267
  {
262
  {
268
    // default values
263
    // default values
269
    props.put(REPRODUCIBLE_PRNG, (reproducible ? "true" : "false"));
264
    props.put(REPRODUCIBLE_PRNG, (reproducible ? "true" : "false"));
270
    props.put(CHECK_WEAK_KEYS, (checkForWeakKeys ? "true" : "false"));
265
    props.put(CHECK_WEAK_KEYS, (checkForWeakKeys ? "true" : "false"));
271
    props.put(DO_RSA_BLINDING, (doRSABlinding ? "true" : "false"));
266
    props.put(DO_RSA_BLINDING, (doRSABlinding ? "true" : "false"));
272
273
    // 1. allow site-wide override by reading a properties file
267
    // 1. allow site-wide override by reading a properties file
274
    String propFile = null;
268
    String propFile = null;
275
    try
269
    try
Lines 309-325 Link Here
309
                       + se.getMessage());
303
                       + se.getMessage());
310
          }
304
          }
311
      }
305
      }
312
313
    // 2. allow vm-specific override by allowing -D options in launcher
306
    // 2. allow vm-specific override by allowing -D options in launcher
314
    handleBooleanProperty(REPRODUCIBLE_PRNG);
307
    handleBooleanProperty(REPRODUCIBLE_PRNG);
315
    handleBooleanProperty(CHECK_WEAK_KEYS);
308
    handleBooleanProperty(CHECK_WEAK_KEYS);
316
    handleBooleanProperty(DO_RSA_BLINDING);
309
    handleBooleanProperty(DO_RSA_BLINDING);
317
318
    // re-sync the 'known' properties
310
    // re-sync the 'known' properties
319
    reproducible = Boolean.valueOf((String) props.get(REPRODUCIBLE_PRNG)).booleanValue();
311
    reproducible = Boolean.valueOf((String) props.get(REPRODUCIBLE_PRNG)).booleanValue();
320
    checkForWeakKeys = Boolean.valueOf((String) props.get(CHECK_WEAK_KEYS)).booleanValue();
312
    checkForWeakKeys = Boolean.valueOf((String) props.get(CHECK_WEAK_KEYS)).booleanValue();
321
    doRSABlinding = Boolean.valueOf((String) props.get(DO_RSA_BLINDING)).booleanValue();
313
    doRSABlinding = Boolean.valueOf((String) props.get(DO_RSA_BLINDING)).booleanValue();
322
323
    // This does not change.
314
    // This does not change.
324
    props.put(VERSION, Registry.VERSION_STRING);
315
    props.put(VERSION, Registry.VERSION_STRING);
325
  }
316
  }
Lines 339-345 Link Here
339
    if (s != null)
330
    if (s != null)
340
      {
331
      {
341
        s = s.trim().toLowerCase();
332
        s = s.trim().toLowerCase();
342
        // we have to test for explicit "true" or "false".  anything else may
333
        // we have to test for explicit "true" or "false". anything else may
343
        // hide valid value set previously
334
        // hide valid value set previously
344
        if (s.equals(TRUE) || s.equals(FALSE))
335
        if (s.equals(TRUE) || s.equals(FALSE))
345
          {
336
          {
(-)Registry.java (-31 / +23 lines)
Lines 44-53 Link Here
44
 */
44
 */
45
public interface Registry
45
public interface Registry
46
{
46
{
47
48
  // Constants
49
  // -------------------------------------------------------------------------
50
51
  /** The name of our Providers. */
47
  /** The name of our Providers. */
52
  String GNU_SECURITY = "GNU";
48
  String GNU_SECURITY = "GNU";
53
  String GNU_CRYPTO = "GNU-CRYPTO";
49
  String GNU_CRYPTO = "GNU-CRYPTO";
Lines 303-340 Link Here
303
  // D (0x44) for DSS, R (0x52) for RSA, H (0x48) for Diffie-Hellman, or S
299
  // D (0x44) for DSS, R (0x52) for RSA, H (0x48) for Diffie-Hellman, or S
304
  // (0x53) for SRP-6, and finally P (0x50) for Public, p (0x70) for private,
300
  // (0x53) for SRP-6, and finally P (0x50) for Public, p (0x70) for private,
305
  // or S (0x53) for signature.
301
  // or S (0x53) for signature.
306
  byte[] MAGIC_RAW_DSS_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x44,
302
  byte[] MAGIC_RAW_DSS_PUBLIC_KEY = new byte[] {
307
                                                0x50 };
303
      0x47, RAW_ENCODING_ID, 0x44, 0x50 };
308
304
309
  byte[] MAGIC_RAW_DSS_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x44,
305
  byte[] MAGIC_RAW_DSS_PRIVATE_KEY = new byte[] {
310
                                                 0x70 };
306
      0x47, RAW_ENCODING_ID, 0x44, 0x70 };
311
307
312
  byte[] MAGIC_RAW_DSS_SIGNATURE = new byte[] { 0x47, RAW_ENCODING_ID, 0x44,
308
  byte[] MAGIC_RAW_DSS_SIGNATURE = new byte[] {
313
                                               0x53 };
309
      0x47, RAW_ENCODING_ID, 0x44, 0x53 };
314
310
315
  byte[] MAGIC_RAW_RSA_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x52,
311
  byte[] MAGIC_RAW_RSA_PUBLIC_KEY = new byte[] {
316
                                                0x50 };
312
      0x47, RAW_ENCODING_ID, 0x52, 0x50 };
317
313
318
  byte[] MAGIC_RAW_RSA_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x52,
314
  byte[] MAGIC_RAW_RSA_PRIVATE_KEY = new byte[] {
319
                                                 0x70 };
315
      0x47, RAW_ENCODING_ID, 0x52, 0x70 };
320
316
321
  byte[] MAGIC_RAW_RSA_PSS_SIGNATURE = new byte[] { 0x47, RAW_ENCODING_ID,
317
  byte[] MAGIC_RAW_RSA_PSS_SIGNATURE = new byte[] {
322
                                                   0x52, 0x53 };
318
      0x47, RAW_ENCODING_ID, 0x52, 0x53 };
323
319
324
  byte[] MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE = new byte[] { 0x47, RAW_ENCODING_ID,
320
  byte[] MAGIC_RAW_RSA_PKCS1V1_5_SIGNATURE = new byte[] {
325
                                                          0x52, 0x54 };
321
      0x47, RAW_ENCODING_ID, 0x52, 0x54 };
326
322
327
  byte[] MAGIC_RAW_DH_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x48,
323
  byte[] MAGIC_RAW_DH_PUBLIC_KEY = new byte[] {
328
                                               0x50 };
324
      0x47, RAW_ENCODING_ID, 0x48, 0x50 };
329
325
330
  byte[] MAGIC_RAW_DH_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x48,
326
  byte[] MAGIC_RAW_DH_PRIVATE_KEY = new byte[] {
331
                                                0x70 };
327
      0x47, RAW_ENCODING_ID, 0x48, 0x70 };
332
328
333
  byte[] MAGIC_RAW_SRP_PUBLIC_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x53,
329
  byte[] MAGIC_RAW_SRP_PUBLIC_KEY = new byte[] {
334
                                                0x50 };
330
      0x47, RAW_ENCODING_ID, 0x53, 0x50 };
335
331
336
  byte[] MAGIC_RAW_SRP_PRIVATE_KEY = new byte[] { 0x47, RAW_ENCODING_ID, 0x53,
332
  byte[] MAGIC_RAW_SRP_PRIVATE_KEY = new byte[] {
337
                                                 0x70 };
333
      0x47, RAW_ENCODING_ID, 0x53, 0x70 };
338
334
339
  // SASL Property names .....................................................
335
  // SASL Property names .....................................................
340
336
Lines 347-354 Link Here
347
  String SASL_PASSWORD = SASL_PREFIX + ".password";
343
  String SASL_PASSWORD = SASL_PREFIX + ".password";
348
344
349
  /** Name of authentication information provider packages. */
345
  /** Name of authentication information provider packages. */
350
  String SASL_AUTH_INFO_PROVIDER_PKGS = SASL_PREFIX
346
  String SASL_AUTH_INFO_PROVIDER_PKGS = SASL_PREFIX + ".auth.info.provider.pkgs";
351
                                        + ".auth.info.provider.pkgs";
352
347
353
  /** SASL authorization ID. */
348
  /** SASL authorization ID. */
354
  String SASL_AUTHORISATION_ID = SASL_PREFIX + ".authorisation.ID";
349
  String SASL_AUTHORISATION_ID = SASL_PREFIX + ".authorisation.ID";
Lines 455-461 Link Here
455
  int GKR_CIPHER_AES_128_OFB = 0;
450
  int GKR_CIPHER_AES_128_OFB = 0;
456
451
457
  int GKR_CIPHER_AES_128_CBC = 1;
452
  int GKR_CIPHER_AES_128_CBC = 1;
458
459
  // Methods
460
  // -------------------------------------------------------------------------
461
}
453
}
(-)prng/BasePRNG.java (-30 / +9 lines)
Lines 41-54 Link Here
41
import java.util.Map;
41
import java.util.Map;
42
42
43
/**
43
/**
44
 * <p>An abstract class to facilitate implementing PRNG algorithms.</p>
44
 * An abstract class to facilitate implementing PRNG algorithms.
45
 */
45
 */
46
public abstract class BasePRNG implements IRandom
46
public abstract class BasePRNG
47
    implements IRandom
47
{
48
{
48
49
  // Constants and variables
50
  // -------------------------------------------------------------------------
51
52
  /** The canonical name prefix of the PRNG algorithm. */
49
  /** The canonical name prefix of the PRNG algorithm. */
53
  protected String name;
50
  protected String name;
54
51
Lines 61-72 Link Here
61
  /** The index into buffer of where the next byte will come from. */
58
  /** The index into buffer of where the next byte will come from. */
62
  protected int ndx;
59
  protected int ndx;
63
60
64
  // Constructor(s)
65
  // -------------------------------------------------------------------------
66
67
  /**
61
  /**
68
   * <p>Trivial constructor for use by concrete subclasses.</p>
62
   * Trivial constructor for use by concrete subclasses.
69
   *
63
   * 
70
   * @param name the canonical name of this instance.
64
   * @param name the canonical name of this instance.
71
   */
65
   */
72
  protected BasePRNG(String name)
66
  protected BasePRNG(String name)
Lines 78-91 Link Here
78
    buffer = new byte[0];
72
    buffer = new byte[0];
79
  }
73
  }
80
74
81
  // Class methods
82
  // -------------------------------------------------------------------------
83
84
  // Instance methods
85
  // -------------------------------------------------------------------------
86
87
  // IRandom interface implementation ----------------------------------------
88
89
  public String name()
75
  public String name()
90
  {
76
  {
91
    return name;
77
    return name;
Lines 101-110 Link Here
101
87
102
  public byte nextByte() throws IllegalStateException, LimitReachedException
88
  public byte nextByte() throws IllegalStateException, LimitReachedException
103
  {
89
  {
104
    if (!initialised)
90
    if (! initialised)
105
      {
91
      throw new IllegalStateException();
106
        throw new IllegalStateException();
92
107
      }
108
    return nextByteInternal();
93
    return nextByteInternal();
109
  }
94
  }
110
95
Lines 117-123 Link Here
117
  public void nextBytes(byte[] out, int offset, int length)
102
  public void nextBytes(byte[] out, int offset, int length)
118
      throws IllegalStateException, LimitReachedException
103
      throws IllegalStateException, LimitReachedException
119
  {
104
  {
120
    if (!initialised)
105
    if (! initialised)
121
      throw new IllegalStateException("not initialized");
106
      throw new IllegalStateException("not initialized");
122
107
123
    if (length == 0)
108
    if (length == 0)
Lines 127-133 Link Here
127
      throw new ArrayIndexOutOfBoundsException("offset=" + offset + " length="
112
      throw new ArrayIndexOutOfBoundsException("offset=" + offset + " length="
128
                                               + length + " limit="
113
                                               + length + " limit="
129
                                               + out.length);
114
                                               + out.length);
130
131
    if (ndx >= buffer.length)
115
    if (ndx >= buffer.length)
132
      {
116
      {
133
        fillBlock();
117
        fillBlock();
Lines 163-171 Link Here
163
    throw new UnsupportedOperationException("random state is non-modifiable");
147
    throw new UnsupportedOperationException("random state is non-modifiable");
164
  }
148
  }
165
149
166
  // Instance methods
167
  // -------------------------------------------------------------------------
168
169
  public boolean isInitialised()
150
  public boolean isInitialised()
170
  {
151
  {
171
    return initialised;
152
    return initialised;
Lines 182-189 Link Here
182
    return buffer[ndx++];
163
    return buffer[ndx++];
183
  }
164
  }
184
165
185
  // abstract methods to implement by subclasses -----------------------------
186
187
  public Object clone() throws CloneNotSupportedException
166
  public Object clone() throws CloneNotSupportedException
188
  {
167
  {
189
    BasePRNG result = (BasePRNG) super.clone();
168
    BasePRNG result = (BasePRNG) super.clone();
(-)prng/EntropySource.java (-1 lines)
Lines 43-49 Link Here
43
 */
43
 */
44
public interface EntropySource
44
public interface EntropySource
45
{
45
{
46
47
  /**
46
  /**
48
   * Returns the estimated quality of this source. This value should be
47
   * Returns the estimated quality of this source. This value should be
49
   * between 0 and 100 (the running quality is computed as a percentage,
48
   * between 0 and 100 (the running quality is computed as a percentage,
(-)prng/IRandom.java (-81 / +75 lines)
Lines 41-180 Link Here
41
import java.util.Map;
41
import java.util.Map;
42
42
43
/**
43
/**
44
 * <p>The basic visible methods of any pseudo-random number generator.</p>
44
 * The basic visible methods of any pseudo-random number generator.
45
 *
45
 * <p>
46
 * <p>The [HAC] defines a PRNG (as implemented in this library) as follows:</p>
46
 * The [HAC] defines a PRNG (as implemented in this library) as follows:
47
 *
48
 * <ul>
47
 * <ul>
49
 *    <li>"5.6 Definition: A pseudorandom bit generator (PRBG) is said to pass
48
 * <li>"5.6 Definition: A pseudorandom bit generator (PRBG) is said to pass the
50
 *    the <em>next-bit test</em> if there is no polynomial-time algorithm which,
49
 * <em>next-bit test</em> if there is no polynomial-time algorithm which, on
51
 *    on input of the first <code>L</code> bits of an output sequence <code>S</code>,
50
 * input of the first <code>L</code> bits of an output sequence <code>S</code>,
52
 *    can predict the <code>(L+1)</code>st bit of <code>S</code> with a
51
 * can predict the <code>(L+1)</code><sup>st</sup> bit of <code>S</code> with a
53
 *    probability significantly grater than <code>1/2</code>."</li>
52
 * probability significantly greater than <code>1/2</code>."</li>
54
 *
53
 * <li>"5.8 Definition: A PRBG that passes the <em>next-bit test</em>
55
 *    <li>"5.8 Definition: A PRBG that passes the <em>next-bit test</em>
54
 * (possibly under some plausible but unproved mathematical assumption such as
56
 *    (possibly under some plausible but unproved mathematical assumption such
55
 * the intractability of factoring integers) is called a <em>cryptographically
57
 *    as the intractability of factoring integers) is called a
56
 * secure pseudorandom bit generator</em> (CSPRBG)."</li>
58
 *    <em>cryptographically secure pseudorandom bit generator</em> (CSPRBG)."</li>
59
 * </ul>
57
 * </ul>
60
 *
58
 * <p>
61
 * <p><b>IMPLEMENTATION NOTE</b>: Although all the concrete classes in this
59
 * <b>IMPLEMENTATION NOTE</b>: Although all the concrete classes in this
62
 * package implement the {@link Cloneable} interface, it is important to note
60
 * package implement the {@link Cloneable} interface, it is important to note
63
 * here that such an operation, for those algorithms that use an underlting
61
 * here that such an operation, for those algorithms that use an underlying
64
 * symmetric key block cipher, <b>DOES NOT</b> clone any session key material
62
 * symmetric key block cipher, <b>DOES NOT</b> clone any session key material
65
 * that may have been used in initialising the source PRNG (the instance to be
63
 * that may have been used in initialising the source PRNG (the instance to be
66
 * cloned). Instead a clone of an already initialised PRNG, that uses and
64
 * cloned). Instead a clone of an already initialised PRNG, that uses an
67
 * underlying symmetric key block cipher, is another instance with a clone of
65
 * underlying symmetric key block cipher, is another instance with a clone of
68
 * the same cipher that operates with the <b>same block size</b> but without any
66
 * the same cipher that operates with the <b>same block size</b> but without
69
 * knowledge of neither key material nor key size.</p>
67
 * any knowledge of neither key material nor key size.
70
 *
68
 * <p>
71
 * <p>References:</p>
69
 * References:
72
 *
73
 * <ol>
70
 * <ol>
74
 *    <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
71
 * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
75
 *    Applied Cryptography.<br>
72
 * Applied Cryptography.<br>
76
 *    CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
73
 * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
77
 *    Menezes, A., van Oorschot, P. and S. Vanstone.</li>
74
 * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
78
 * </ol>
75
 * </ol>
79
 */
76
 */
80
public interface IRandom extends Cloneable
77
public interface IRandom
78
    extends Cloneable
81
{
79
{
82
83
  // Constants
84
  // -------------------------------------------------------------------------
85
86
  // Methods
87
  // -------------------------------------------------------------------------
88
89
  /**
80
  /**
90
   * <p>Returns the canonical name of this instance.</p>
81
   * Returns the canonical name of this instance.
91
   *
82
   * 
92
   * @return the canonical name of this instance. */
83
   * @return the canonical name of this instance.
84
   */
93
  String name();
85
  String name();
94
86
95
  /**
87
  /**
96
   * <p>Initialises the pseudo-random number generator scheme with the
88
   * Initialises the pseudo-random number generator scheme with the appropriate
97
   * appropriate attributes.</p>
89
   * attributes.
98
   *
90
   * 
99
   * @param attributes a set of name-value pairs that describe the desired
91
   * @param attributes a set of name-value pairs that describe the desired
100
   * future instance behaviour.
92
   *          future instance behaviour.
101
   * @exception IllegalArgumentException if at least one of the defined name/
93
   * @exception IllegalArgumentException if at least one of the defined name/
102
   * value pairs contains invalid data.
94
   *              value pairs contains invalid data.
103
   */
95
   */
104
  void init(Map attributes);
96
  void init(Map attributes);
105
97
106
  /**
98
  /**
107
   * <p>Returns the next 8 bits of random data generated from this instance.</p>
99
   * Returns the next 8 bits of random data generated from this instance.
108
   *
100
   * 
109
   * @return the next 8 bits of random data generated from this instance.
101
   * @return the next 8 bits of random data generated from this instance.
110
   * @exception IllegalStateException if the instance is not yet initialised.
102
   * @exception IllegalStateException if the instance is not yet initialised.
111
   * @exception LimitReachedException if this instance has reached its
103
   * @exception LimitReachedException if this instance has reached its
112
   * theoretical limit for generating non-repetitive pseudo-random data.
104
   *              theoretical limit for generating non-repetitive pseudo-random
105
   *              data.
113
   */
106
   */
114
  byte nextByte() throws IllegalStateException, LimitReachedException;
107
  byte nextByte() throws IllegalStateException, LimitReachedException;
115
108
116
  /**
109
  /**
117
   * <p>Fills the designated byte array, starting from byte at index
110
   * Fills the designated byte array, starting from byte at index
118
   * <code>offset</code>, for a maximum of <code>length</code> bytes with the
111
   * <code>offset</code>, for a maximum of <code>length</code> bytes with
119
   * output of this generator instance.
112
   * the output of this generator instance.
120
   *
113
   * 
121
   * @param out the placeholder to contain the generated random bytes.
114
   * @param out the placeholder to contain the generated random bytes.
122
   * @param offset the starting index in <i>out</i> to consider. This method
115
   * @param offset the starting index in <i>out</i> to consider. This method
123
   * does nothing if this parameter is not within <code>0</code> and
116
   *          does nothing if this parameter is not within <code>0</code> and
124
   * <code>out.length</code>.
117
   *          <code>out.length</code>.
125
   * @param length the maximum number of required random bytes. This method
118
   * @param length the maximum number of required random bytes. This method does
126
   * does nothing if this parameter is less than <code>1</code>.
119
   *          nothing if this parameter is less than <code>1</code>.
127
   * @exception IllegalStateException if the instance is not yet initialised.
120
   * @exception IllegalStateException if the instance is not yet initialised.
128
   * @exception LimitReachedException if this instance has reached its
121
   * @exception LimitReachedException if this instance has reached its
129
   * theoretical limit for generating non-repetitive pseudo-random data.
122
   *              theoretical limit for generating non-repetitive pseudo-random
123
   *              data.
130
   */
124
   */
131
  void nextBytes(byte[] out, int offset, int length)
125
  void nextBytes(byte[] out, int offset, int length)
132
      throws IllegalStateException, LimitReachedException;
126
      throws IllegalStateException, LimitReachedException;
133
127
134
  /**
128
  /**
135
   * <p>Supplement, or possibly replace, the random state of this PRNG with
129
   * Supplement, or possibly replace, the random state of this PRNG with a
136
   * a random byte.</p>
130
   * random byte.
137
   *
131
   * <p>
138
   * <p>Implementations are not required to implement this method in any
132
   * Implementations are not required to implement this method in any meaningful
139
   * meaningful way; this may be a no-operation, and implementations may
133
   * way; this may be a no-operation, and implementations may throw an
140
   * throw an {@link UnsupportedOperationException}.</p>
134
   * {@link UnsupportedOperationException}.
141
   *
135
   * 
142
   * @param b The byte to add.
136
   * @param b The byte to add.
143
   */
137
   */
144
  void addRandomByte(byte b);
138
  void addRandomByte(byte b);
145
139
146
  /**
140
  /**
147
   * <p>Supplement, or possibly replace, the random state of this PRNG with
141
   * Supplement, or possibly replace, the random state of this PRNG with a
148
   * a sequence of new random bytes.</p>
142
   * sequence of new random bytes.
149
   *
143
   * <p>
150
   * <p>Implementations are not required to implement this method in any
144
   * Implementations are not required to implement this method in any meaningful
151
   * meaningful way; this may be a no-operation, and implementations may
145
   * way; this may be a no-operation, and implementations may throw an
152
   * throw an {@link UnsupportedOperationException}.</p>
146
   * {@link UnsupportedOperationException}.
153
   *
147
   * 
154
   * @param in The buffer of new random bytes to add.
148
   * @param in The buffer of new random bytes to add.
155
   */
149
   */
156
  void addRandomBytes(byte[] in);
150
  void addRandomBytes(byte[] in);
157
151
158
  /**
152
  /**
159
   * <p>Supplement, or possibly replace, the random state of this PRNG with
153
   * Supplement, or possibly replace, the random state of this PRNG with a
160
   * a sequence of new random bytes.</p>
154
   * sequence of new random bytes.
161
   *
155
   * <p>
162
   * <p>Implementations are not required to implement this method in any
156
   * Implementations are not required to implement this method in any meaningful
163
   * meaningful way; this may be a no-operation, and implementations may
157
   * way; this may be a no-operation, and implementations may throw an
164
   * throw an {@link UnsupportedOperationException}.</p>
158
   * {@link UnsupportedOperationException}.
165
   *
159
   * 
166
   * @param in The buffer of new random bytes to add.
160
   * @param in The buffer of new random bytes to add.
167
   * @param offset The offset from whence to begin reading random bytes.
161
   * @param offset The offset from whence to begin reading random bytes.
168
   * @param length The number of random bytes to add.
162
   * @param length The number of random bytes to add.
169
   * @exception IndexOutOfBoundsException If <i>offset</i>, <i>length</i>,
163
   * @exception IndexOutOfBoundsException If <i>offset</i>, <i>length</i>, or
170
   * or <i>offset</i>+<i>length</i> is out of bounds.
164
   *              <i>offset</i>+<i>length</i> is out of bounds.
171
   */
165
   */
172
  void addRandomBytes(byte[] in, int offset, int length);
166
  void addRandomBytes(byte[] in, int offset, int length);
173
167
174
  /**
168
  /**
175
   * <p>Returns a clone copy of this instance.</p>
169
   * Returns a clone copy of this instance.
176
   *
170
   * 
177
   * @return a clone copy of this instance.
171
   * @return a clone copy of this instance.
178
   */
172
   */
179
  Object clone() throws CloneNotSupportedException;
173
  Object clone() throws CloneNotSupportedException;
180
}
174
}
(-)prng/LimitReachedException.java (-15 / +3 lines)
Lines 42-56 Link Here
42
 * A checked exception that indicates that a pseudo random number generated has
42
 * A checked exception that indicates that a pseudo random number generated has
43
 * reached its theoretical limit in generating random bytes.
43
 * reached its theoretical limit in generating random bytes.
44
 */
44
 */
45
public class LimitReachedException extends Exception
45
public class LimitReachedException
46
    extends Exception
46
{
47
{
47
48
  // Constants and variables
49
  // -------------------------------------------------------------------------
50
51
  // Constructor(s)
52
  // -------------------------------------------------------------------------
53
54
  public LimitReachedException()
48
  public LimitReachedException()
55
  {
49
  {
56
    super();
50
    super();
Lines 60-69 Link Here
60
  {
54
  {
61
    super(msg);
55
    super(msg);
62
  }
56
  }
63
57
}
64
  // Class methods
65
  // -------------------------------------------------------------------------
66
67
  // Instant methods
68
  // -------------------------------------------------------------------------
69
}
(-)prng/MDGenerator.java (-41 / +19 lines)
Lines 45-63 Link Here
45
import java.util.Map;
45
import java.util.Map;
46
46
47
/**
47
/**
48
 * <p>A simple pseudo-random number generator that relies on a hash algorithm,
48
 * A simple pseudo-random number generator that relies on a hash algorithm, that
49
 * that (a) starts its operation by hashing a <code>seed</code>, and then (b)
49
 * (a) starts its operation by hashing a <code>seed</code>, and then (b)
50
 * continuously re-hashing its output. If no hash algorithm name is specified
50
 * continuously re-hashing its output. If no hash algorithm name is specified in
51
 * in the {@link Map} of attributes used to initialise the instance then the
51
 * the {@link Map} of attributes used to initialise the instance then the
52
 * SHA-160 algorithm is used as the underlying hash function. Also, if no
52
 * SHA-160 algorithm is used as the underlying hash function. Also, if no
53
 * <code>seed</code> is given, an empty octet sequence is used.</p>
53
 * <code>seed</code> is given, an empty octet sequence is used.
54
 */
54
 */
55
public class MDGenerator extends BasePRNG implements Cloneable
55
public class MDGenerator
56
    extends BasePRNG
57
    implements Cloneable
56
{
58
{
57
58
  // Constants and variables
59
  // -------------------------------------------------------------------------
60
61
  /** Property name of underlying hash algorithm for this generator. */
59
  /** Property name of underlying hash algorithm for this generator. */
62
  public static final String MD_NAME = "gnu.crypto.prng.md.hash.name";
60
  public static final String MD_NAME = "gnu.crypto.prng.md.hash.name";
63
61
Lines 67-89 Link Here
67
  /** The underlying hash instance. */
65
  /** The underlying hash instance. */
68
  private IMessageDigest md;
66
  private IMessageDigest md;
69
67
70
  // Constructor(s)
71
  // -------------------------------------------------------------------------
72
73
  /** Trivial 0-arguments constructor. */
68
  /** Trivial 0-arguments constructor. */
74
  public MDGenerator()
69
  public MDGenerator()
75
  {
70
  {
76
    super(Registry.MD_PRNG);
71
    super(Registry.MD_PRNG);
77
  }
72
  }
78
73
79
  // Class methods
80
  // -------------------------------------------------------------------------
81
82
  // Instance methods
83
  // -------------------------------------------------------------------------
84
85
  // Implementation of abstract methods in BaseRandom ------------------------
86
87
  public void setup(Map attributes)
74
  public void setup(Map attributes)
88
  {
75
  {
89
    // find out which hash to use
76
    // find out which hash to use
Lines 95-116 Link Here
95
            // ensure we have a reliable implementation of this hash
82
            // ensure we have a reliable implementation of this hash
96
            md = HashFactory.getInstance(Registry.SHA160_HASH);
83
            md = HashFactory.getInstance(Registry.SHA160_HASH);
97
          }
84
          }
98
        else
85
        else // a clone. reset it for reuse
99
          { // a clone. reset it for reuse
86
          md.reset();
100
            md.reset();
101
          }
102
      }
103
    else
104
      { // ensure we have a reliable implementation of this hash
105
        md = HashFactory.getInstance(underlyingMD);
106
      }
87
      }
107
88
    else // ensure we have a reliable implementation of this hash
89
      md = HashFactory.getInstance(underlyingMD);
108
    // get the seeed
90
    // get the seeed
109
    byte[] seed = (byte[]) attributes.get(SEEED);
91
    byte[] seed = (byte[]) attributes.get(SEEED);
110
    if (seed == null)
92
    if (seed == null)
111
      {
93
      seed = new byte[0];
112
        seed = new byte[0];
113
      }
114
94
115
    md.update(seed, 0, seed.length);
95
    md.update(seed, 0, seed.length);
116
  }
96
  }
Lines 122-143 Link Here
122
    md.update(buffer, 0, buffer.length);
102
    md.update(buffer, 0, buffer.length);
123
  }
103
  }
124
104
125
  public void addRandomByte (final byte b)
105
  public void addRandomByte(final byte b)
126
  {
106
  {
127
    if (md == null)
107
    if (md == null)
128
      throw new IllegalStateException ("not initialized");
108
      throw new IllegalStateException("not initialized");
129
    md.update (b);
109
    md.update(b);
130
  }
110
  }
131
111
132
  public void addRandomBytes (final byte[] buf, final int off, final int len)
112
  public void addRandomBytes(final byte[] buf, final int off, final int len)
133
  {
113
  {
134
    if (md == null)
114
    if (md == null)
135
      throw new IllegalStateException ("not initialized");
115
      throw new IllegalStateException("not initialized");
136
    md.update (buf, off, len);
116
    md.update(buf, off, len);
137
  }
117
  }
138
118
139
  // Cloneable interface implementation ---------------------------------------
140
141
  public Object clone() throws CloneNotSupportedException
119
  public Object clone() throws CloneNotSupportedException
142
  {
120
  {
143
    MDGenerator result = (MDGenerator) super.clone();
121
    MDGenerator result = (MDGenerator) super.clone();
(-)prng/PRNGFactory.java (-28 / +12 lines)
Lines 45-100 Link Here
45
import java.util.Set;
45
import java.util.Set;
46
46
47
/**
47
/**
48
 * <p>A Factory to instantiate pseudo random number generators.</p>
48
 * A Factory to instantiate pseudo random number generators.
49
 */
49
 */
50
public class PRNGFactory implements Registry
50
public class PRNGFactory
51
    implements Registry
51
{
52
{
52
53
  // Constants and variables
54
  // -------------------------------------------------------------------------
55
56
  // Constructor(s)
57
  // -------------------------------------------------------------------------
58
59
  /** Trivial constructor to enforce <i>Singleton</i> pattern. */
53
  /** Trivial constructor to enforce <i>Singleton</i> pattern. */
60
  protected PRNGFactory()
54
  protected PRNGFactory()
61
  {
55
  {
62
  }
56
  }
63
57
64
  // Class methods
65
  // -------------------------------------------------------------------------
66
67
  /**
58
  /**
68
   * <p>Returns an instance of a padding algorithm given its name.</p>
59
   * Returns an instance of a padding algorithm given its name.
69
   *
60
   * 
70
   * @param prng the case-insensitive name of the PRNG.
61
   * @param prng the case-insensitive name of the PRNG.
71
   * @return an instance of the pseudo-random number generator.
62
   * @return an instance of the pseudo-random number generator.
72
   * @exception InternalError if the implementation does not pass its self-
63
   * @exception InternalError if the implementation does not pass its self-
73
   * test.
64
   *              test.
74
   */
65
   */
75
  public static final IRandom getInstance(String prng)
66
  public static final IRandom getInstance(String prng)
76
  {
67
  {
77
    if (prng == null)
68
    if (prng == null)
78
      {
69
      return null;
79
        return null;
80
      }
81
70
82
    prng = prng.trim();
71
    prng = prng.trim();
83
    IRandom result = null;
72
    IRandom result = null;
84
    if (prng.equalsIgnoreCase(MD_PRNG))
73
    if (prng.equalsIgnoreCase(MD_PRNG))
85
      {
74
      result = new MDGenerator();
86
        result = new MDGenerator();
87
      }
88
75
89
    return result;
76
    return result;
90
  }
77
  }
91
78
92
  /**
79
  /**
93
   * <p>Returns a {@link Set} of names of padding algorithms supported by this
80
   * Returns a {@link Set} of names of padding algorithms supported by this
94
   * <i>Factory</i>.</p>
81
   * <i>Factory</i>.
95
   *
82
   * 
96
   * @return a {@link Set} of pseudo-random number generator algorithm names
83
   * @return a {@link Set} of pseudo-random number generator algorithm names
97
   * (Strings).
84
   *         (Strings).
98
   */
85
   */
99
  public static final Set getNames()
86
  public static final Set getNames()
100
  {
87
  {
Lines 102-108 Link Here
102
    hs.add(MD_PRNG);
89
    hs.add(MD_PRNG);
103
    return Collections.unmodifiableSet(hs);
90
    return Collections.unmodifiableSet(hs);
104
  }
91
  }
105
106
  // Instance methods
107
  // -------------------------------------------------------------------------
108
}
92
}
(-)prng/RandomEvent.java (-6 / +5 lines)
Lines 41-52 Link Here
41
import java.util.EventObject;
41
import java.util.EventObject;
42
42
43
/**
43
/**
44
 * An interface for entropy accumulators that will be notified of random
44
 * A type for entropy accumulators that will be notified of random events.
45
 * events.
46
 */
45
 */
47
public class RandomEvent extends EventObject
46
public class RandomEvent
47
    extends EventObject
48
{
48
{
49
50
  private final byte sourceNumber;
49
  private final byte sourceNumber;
51
50
52
  private final byte poolNumber;
51
  private final byte poolNumber;
Lines 61-67 Link Here
61
    this.poolNumber = poolNumber;
60
    this.poolNumber = poolNumber;
62
    if (data.length == 0 || data.length > 32)
61
    if (data.length == 0 || data.length > 32)
63
      throw new IllegalArgumentException(
62
      throw new IllegalArgumentException(
64
                                         "random events take between 1 and 32 bytes of data");
63
          "random events take between 1 and 32 bytes of data");
65
    this.data = (byte[]) data.clone();
64
    this.data = (byte[]) data.clone();
66
  }
65
  }
67
66
Lines 79-82 Link Here
79
  {
78
  {
80
    return data;
79
    return data;
81
  }
80
  }
82
}
81
}
(-)prng/RandomEventListener.java (-4 / +4 lines)
Lines 41-50 Link Here
41
import java.util.EventListener;
41
import java.util.EventListener;
42
42
43
/**
43
/**
44
 * An interface for entropy accumulators that will be notified of random
44
 * An interface for entropy accumulators that will be notified of random events.
45
 * events.
46
 */
45
 */
47
public interface RandomEventListener extends EventListener
46
public interface RandomEventListener
47
    extends EventListener
48
{
48
{
49
  void addRandomEvent(RandomEvent event);
49
  void addRandomEvent(RandomEvent event);
50
}
50
}
(-)provider/Gnu.java (-27 / +55 lines)
Lines 42-53 Link Here
42
import java.security.PrivilegedAction;
42
import java.security.PrivilegedAction;
43
import java.security.Provider;
43
import java.security.Provider;
44
44
45
public final class Gnu extends Provider
45
public final class Gnu
46
    extends Provider
46
{
47
{
47
  public Gnu()
48
  public Gnu()
48
  {
49
  {
49
    super("GNU", 1.0, "GNU provider v1.0 implementing SHA-1, MD5, DSA, RSA, X.509 Certificates and CRLs, PKIX certificate path validators, Collection cert stores, Diffie-Hellman key agreement and key pair generator");
50
    super("GNU", 1.0,
50
51
          "GNU provider v1.0 implementing SHA-1, MD5, DSA, RSA, X.509 "
52
          + "Certificates and CRLs, PKIX certificate path validators, "
53
          + "Collection cert stores, Diffie-Hellman key agreement and "
54
          + "key pair generator");
51
    AccessController.doPrivileged (new PrivilegedAction()
55
    AccessController.doPrivileged (new PrivilegedAction()
52
    {
56
    {
53
      public Object run()
57
      public Object run()
Lines 163-191 Link Here
163
        put("Alg.Alias.KeyFactory.PKCS#8", "Encoded");
167
        put("Alg.Alias.KeyFactory.PKCS#8", "Encoded");
164
        put("Alg.Alias.KeyFactory.PKCS8", "Encoded");
168
        put("Alg.Alias.KeyFactory.PKCS8", "Encoded");
165
169
166
        put("MessageDigest.HAVAL", gnu.java.security.jce.hash.HavalSpi.class.getName());
170
        put("MessageDigest.HAVAL",
171
            gnu.java.security.jce.hash.HavalSpi.class.getName());
167
        put("MessageDigest.HAVAL ImplementedIn", "Software");
172
        put("MessageDigest.HAVAL ImplementedIn", "Software");
168
        put("MessageDigest.MD2", gnu.java.security.jce.hash.MD2Spi.class.getName());
173
        put("MessageDigest.MD2",
174
            gnu.java.security.jce.hash.MD2Spi.class.getName());
169
        put("MessageDigest.MD2 ImplementedIn", "Software");
175
        put("MessageDigest.MD2 ImplementedIn", "Software");
170
        put("MessageDigest.MD4", gnu.java.security.jce.hash.MD4Spi.class.getName());
176
        put("MessageDigest.MD4",
177
            gnu.java.security.jce.hash.MD4Spi.class.getName());
171
        put("MessageDigest.MD4 ImplementedIn", "Software");
178
        put("MessageDigest.MD4 ImplementedIn", "Software");
172
        put("MessageDigest.MD5", gnu.java.security.jce.hash.MD5Spi.class.getName());
179
        put("MessageDigest.MD5",
180
            gnu.java.security.jce.hash.MD5Spi.class.getName());
173
        put("MessageDigest.MD5 ImplementedIn", "Software");
181
        put("MessageDigest.MD5 ImplementedIn", "Software");
174
        put("MessageDigest.RIPEMD128", gnu.java.security.jce.hash.RipeMD128Spi.class.getName());
182
        put("MessageDigest.RIPEMD128",
183
            gnu.java.security.jce.hash.RipeMD128Spi.class.getName());
175
        put("MessageDigest.RIPEMD128 ImplementedIn", "Software");
184
        put("MessageDigest.RIPEMD128 ImplementedIn", "Software");
176
        put("MessageDigest.RIPEMD160", gnu.java.security.jce.hash.RipeMD160Spi.class.getName());
185
        put("MessageDigest.RIPEMD160",
186
            gnu.java.security.jce.hash.RipeMD160Spi.class.getName());
177
        put("MessageDigest.RIPEMD160 ImplementedIn", "Software");
187
        put("MessageDigest.RIPEMD160 ImplementedIn", "Software");
178
        put("MessageDigest.SHA-160", gnu.java.security.jce.hash.Sha160Spi.class.getName());
188
        put("MessageDigest.SHA-160",
189
            gnu.java.security.jce.hash.Sha160Spi.class.getName());
179
        put("MessageDigest.SHA-160 ImplementedIn", "Software");
190
        put("MessageDigest.SHA-160 ImplementedIn", "Software");
180
        put("MessageDigest.SHA-256", gnu.java.security.jce.hash.Sha256Spi.class.getName());
191
        put("MessageDigest.SHA-256",
192
            gnu.java.security.jce.hash.Sha256Spi.class.getName());
181
        put("MessageDigest.SHA-256 ImplementedIn", "Software");
193
        put("MessageDigest.SHA-256 ImplementedIn", "Software");
182
        put("MessageDigest.SHA-384", gnu.java.security.jce.hash.Sha384Spi.class.getName());
194
        put("MessageDigest.SHA-384",
195
            gnu.java.security.jce.hash.Sha384Spi.class.getName());
183
        put("MessageDigest.SHA-384 ImplementedIn", "Software");
196
        put("MessageDigest.SHA-384 ImplementedIn", "Software");
184
        put("MessageDigest.SHA-512", gnu.java.security.jce.hash.Sha512Spi.class.getName());
197
        put("MessageDigest.SHA-512",
198
            gnu.java.security.jce.hash.Sha512Spi.class.getName());
185
        put("MessageDigest.SHA-512 ImplementedIn", "Software");
199
        put("MessageDigest.SHA-512 ImplementedIn", "Software");
186
        put("MessageDigest.TIGER", gnu.java.security.jce.hash.TigerSpi.class.getName());
200
        put("MessageDigest.TIGER",
201
            gnu.java.security.jce.hash.TigerSpi.class.getName());
187
        put("MessageDigest.TIGER ImplementedIn", "Software");
202
        put("MessageDigest.TIGER ImplementedIn", "Software");
188
        put("MessageDigest.WHIRLPOOL", gnu.java.security.jce.hash.WhirlpoolSpi.class.getName());
203
        put("MessageDigest.WHIRLPOOL",
204
            gnu.java.security.jce.hash.WhirlpoolSpi.class.getName());
189
        put("MessageDigest.WHIRLPOOL ImplementedIn", "Software");
205
        put("MessageDigest.WHIRLPOOL ImplementedIn", "Software");
190
206
191
        put("Alg.Alias.MessageDigest.SHS", "SHA-160");
207
        put("Alg.Alias.MessageDigest.SHS", "SHA-160");
Lines 224-252 Link Here
224
        put("SecureRandom.SHA1PRNG",
240
        put("SecureRandom.SHA1PRNG",
225
            gnu.java.security.jce.prng.Sha160RandomSpi.class.getName());
241
            gnu.java.security.jce.prng.Sha160RandomSpi.class.getName());
226
242
227
        put("SecureRandom.MD2PRNG", gnu.java.security.jce.prng.MD2RandomSpi.class.getName());
243
        put("SecureRandom.MD2PRNG",
244
            gnu.java.security.jce.prng.MD2RandomSpi.class.getName());
228
        put("SecureRandom.MD2PRNG ImplementedIn", "Software");
245
        put("SecureRandom.MD2PRNG ImplementedIn", "Software");
229
        put("SecureRandom.MD4PRNG", gnu.java.security.jce.prng.MD4RandomSpi.class.getName());
246
        put("SecureRandom.MD4PRNG",
247
            gnu.java.security.jce.prng.MD4RandomSpi.class.getName());
230
        put("SecureRandom.MD4PRNG ImplementedIn", "Software");
248
        put("SecureRandom.MD4PRNG ImplementedIn", "Software");
231
        put("SecureRandom.MD5PRNG", gnu.java.security.jce.prng.MD5RandomSpi.class.getName());
249
        put("SecureRandom.MD5PRNG",
250
            gnu.java.security.jce.prng.MD5RandomSpi.class.getName());
232
        put("SecureRandom.MD5PRNG ImplementedIn", "Software");
251
        put("SecureRandom.MD5PRNG ImplementedIn", "Software");
233
        put("SecureRandom.RIPEMD128PRNG", gnu.java.security.jce.prng.RipeMD128RandomSpi.class.getName());
252
        put("SecureRandom.RIPEMD128PRNG",
253
            gnu.java.security.jce.prng.RipeMD128RandomSpi.class.getName());
234
        put("SecureRandom.RIPEMD128PRNG ImplementedIn", "Software");
254
        put("SecureRandom.RIPEMD128PRNG ImplementedIn", "Software");
235
        put("SecureRandom.RIPEMD160PRNG", gnu.java.security.jce.prng.RipeMD160RandomSpi.class.getName());
255
        put("SecureRandom.RIPEMD160PRNG",
256
            gnu.java.security.jce.prng.RipeMD160RandomSpi.class.getName());
236
        put("SecureRandom.RIPEMD160PRNG ImplementedIn", "Software");
257
        put("SecureRandom.RIPEMD160PRNG ImplementedIn", "Software");
237
        put("SecureRandom.SHA-160PRNG", gnu.java.security.jce.prng.Sha160RandomSpi.class.getName());
258
        put("SecureRandom.SHA-160PRNG",
259
            gnu.java.security.jce.prng.Sha160RandomSpi.class.getName());
238
        put("SecureRandom.SHA-160PRNG ImplementedIn", "Software");
260
        put("SecureRandom.SHA-160PRNG ImplementedIn", "Software");
239
        put("SecureRandom.SHA-256PRNG", gnu.java.security.jce.prng.Sha256RandomSpi.class.getName());
261
        put("SecureRandom.SHA-256PRNG",
262
            gnu.java.security.jce.prng.Sha256RandomSpi.class.getName());
240
        put("SecureRandom.SHA-256PRNG ImplementedIn", "Software");
263
        put("SecureRandom.SHA-256PRNG ImplementedIn", "Software");
241
        put("SecureRandom.SHA-384PRNG", gnu.java.security.jce.prng.Sha384RandomSpi.class.getName());
264
        put("SecureRandom.SHA-384PRNG",
265
            gnu.java.security.jce.prng.Sha384RandomSpi.class.getName());
242
        put("SecureRandom.SHA-384PRNG ImplementedIn", "Software");
266
        put("SecureRandom.SHA-384PRNG ImplementedIn", "Software");
243
        put("SecureRandom.SHA-512PRNG", gnu.java.security.jce.prng.Sha512RandomSpi.class.getName());
267
        put("SecureRandom.SHA-512PRNG",
268
            gnu.java.security.jce.prng.Sha512RandomSpi.class.getName());
244
        put("SecureRandom.SHA-512PRNG ImplementedIn", "Software");
269
        put("SecureRandom.SHA-512PRNG ImplementedIn", "Software");
245
        put("SecureRandom.TIGERPRNG", gnu.java.security.jce.prng.TigerRandomSpi.class.getName());
270
        put("SecureRandom.TIGERPRNG",
271
            gnu.java.security.jce.prng.TigerRandomSpi.class.getName());
246
        put("SecureRandom.TIGERPRNG ImplementedIn", "Software");
272
        put("SecureRandom.TIGERPRNG ImplementedIn", "Software");
247
        put("SecureRandom.HAVALPRNG", gnu.java.security.jce.prng.HavalRandomSpi.class.getName());
273
        put("SecureRandom.HAVALPRNG",
274
            gnu.java.security.jce.prng.HavalRandomSpi.class.getName());
248
        put("SecureRandom.HAVALPRNG ImplementedIn", "Software");
275
        put("SecureRandom.HAVALPRNG ImplementedIn", "Software");
249
        put("SecureRandom.WHIRLPOOLPRNG", gnu.java.security.jce.prng.WhirlpoolRandomSpi.class.getName());
276
        put("SecureRandom.WHIRLPOOLPRNG",
277
            gnu.java.security.jce.prng.WhirlpoolRandomSpi.class.getName());
250
        put("SecureRandom.WHIRLPOOLPRNG ImplementedIn", "Software");
278
        put("SecureRandom.WHIRLPOOLPRNG ImplementedIn", "Software");
251
279
252
        put("Alg.Alias.SecureRandom.SHA-1PRNG", "SHA-160PRNG");
280
        put("Alg.Alias.SecureRandom.SHA-1PRNG", "SHA-160PRNG");
(-)provider/PKIXCertPathValidatorImpl.java (-111 / +95 lines)
Lines 85-135 Link Here
85
import java.util.logging.Logger;
85
import java.util.logging.Logger;
86
86
87
/**
87
/**
88
 * An implementation of the Public Key Infrastructure's X.509
88
 * An implementation of the Public Key Infrastructure's X.509 certificate path
89
 * certificate path validation algorithm.
89
 * validation algorithm.
90
 *
90
 * <p>
91
 * <p>See <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
91
 * See <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
92
 * Internet X.509 Public Key Infrastructure Certificate and
92
 * Public Key Infrastructure Certificate and Certificate Revocation List (CRL)
93
 * Certificate Revocation List (CRL) Profile</a>.
93
 * Profile</a>.
94
 *
94
 * 
95
 * @author Casey Marshall (rsdio@metastatic.org)
95
 * @author Casey Marshall (rsdio@metastatic.org)
96
 */
96
 */
97
public class PKIXCertPathValidatorImpl extends CertPathValidatorSpi
97
public class PKIXCertPathValidatorImpl
98
    extends CertPathValidatorSpi
98
{
99
{
99
  private static final Logger log = Logger.getLogger(PKIXCertPathValidatorImpl.class.getName());
100
  private static final Logger log = Logger.getLogger(PKIXCertPathValidatorImpl.class.getName());
100
  public static final String ANY_POLICY = "2.5.29.32.0";
101
101
102
  // Constructor.
102
  public static final String ANY_POLICY = "2.5.29.32.0";
103
  // -------------------------------------------------------------------------
104
103
105
  public PKIXCertPathValidatorImpl()
104
  public PKIXCertPathValidatorImpl()
106
  {
105
  {
107
    super();
106
    super();
108
  }
107
  }
109
108
110
  // Instance methods.
111
  // -------------------------------------------------------------------------
112
113
  public CertPathValidatorResult engineValidate(CertPath path,
109
  public CertPathValidatorResult engineValidate(CertPath path,
114
                                                CertPathParameters params)
110
                                                CertPathParameters params)
115
    throws CertPathValidatorException, InvalidAlgorithmParameterException
111
      throws CertPathValidatorException, InvalidAlgorithmParameterException
116
  {
112
  {
117
    if (!(params instanceof PKIXParameters))
113
    if (! (params instanceof PKIXParameters))
118
      throw new InvalidAlgorithmParameterException("not a PKIXParameters object");
114
      throw new InvalidAlgorithmParameterException("not a PKIXParameters object");
119
120
    // First check if the certificate path is valid.
115
    // First check if the certificate path is valid.
121
    //
116
    //
122
    // This means that:
117
    // This means that:
123
    //
118
    //
124
    //   (a)  for all x in {1, ..., n-1}, the subject of certificate x is
119
    // (a) for all x in {1, ..., n-1}, the subject of certificate x is
125
    //        the issuer of certificate x+1;
120
    // the issuer of certificate x+1;
126
    //
121
    //
127
    //   (b)  for all x in {1, ..., n}, the certificate was valid at the
122
    // (b) for all x in {1, ..., n}, the certificate was valid at the
128
    //        time in question.
123
    // time in question.
129
    //
124
    //
130
    // Because this is the X.509 algorithm, we also check if all
125
    // Because this is the X.509 algorithm, we also check if all
131
    // cerificates are of type X509Certificate.
126
    // cerificates are of type X509Certificate.
132
133
    PolicyNodeImpl rootNode = new PolicyNodeImpl();
127
    PolicyNodeImpl rootNode = new PolicyNodeImpl();
134
    Set initPolicies = ((PKIXParameters) params).getInitialPolicies();
128
    Set initPolicies = ((PKIXParameters) params).getInitialPolicies();
135
    rootNode.setValidPolicy(ANY_POLICY);
129
    rootNode.setValidPolicy(ANY_POLICY);
Lines 152-158 Link Here
152
      {
146
      {
153
        throw new CertPathValidatorException("invalid certificate path");
147
        throw new CertPathValidatorException("invalid certificate path");
154
      }
148
      }
155
156
    String sigProvider = ((PKIXParameters) params).getSigProvider();
149
    String sigProvider = ((PKIXParameters) params).getSigProvider();
157
    PublicKey prevKey = null;
150
    PublicKey prevKey = null;
158
    Date now = ((PKIXParameters) params).getDate();
151
    Date now = ((PKIXParameters) params).getDate();
Lines 170-176 Link Here
170
            throw new CertPathValidatorException(ce.toString());
163
            throw new CertPathValidatorException(ce.toString());
171
          }
164
          }
172
        Set uce = getCritExts(p[i]);
165
        Set uce = getCritExts(p[i]);
173
        for (Iterator check = checks.iterator(); check.hasNext(); )
166
        for (Iterator check = checks.iterator(); check.hasNext();)
174
          {
167
          {
175
            try
168
            try
176
              {
169
              {
Lines 180-202 Link Here
180
              {
173
              {
181
              }
174
              }
182
          }
175
          }
183
184
        PolicyConstraint constr = null;
176
        PolicyConstraint constr = null;
185
        if (p[i] instanceof GnuPKIExtension)
177
        if (p[i] instanceof GnuPKIExtension)
186
          {
178
          {
187
            Extension pcx =
179
            Extension pcx = ((GnuPKIExtension) p[i]).getExtension(PolicyConstraint.ID);
188
              ((GnuPKIExtension) p[i]).getExtension (PolicyConstraint.ID);
189
            if (pcx != null)
180
            if (pcx != null)
190
              constr = (PolicyConstraint) pcx.getValue();
181
              constr = (PolicyConstraint) pcx.getValue();
191
          }
182
          }
192
        else
183
        else
193
          {
184
          {
194
            byte[] pcx = p[i].getExtensionValue (PolicyConstraint.ID.toString());
185
            byte[] pcx = p[i].getExtensionValue(PolicyConstraint.ID.toString());
195
            if (pcx != null)
186
            if (pcx != null)
196
              {
187
              {
197
                try
188
                try
198
                  {
189
                  {
199
                    constr = new PolicyConstraint (pcx);
190
                    constr = new PolicyConstraint(pcx);
200
                  }
191
                  }
201
                catch (Exception x)
192
                catch (Exception x)
202
                  {
193
                  {
Lines 204-217 Link Here
204
              }
195
              }
205
          }
196
          }
206
        if (constr != null && constr.getRequireExplicitPolicy() >= 0)
197
        if (constr != null && constr.getRequireExplicitPolicy() >= 0)
207
          {
198
          policyConstraints.add(new int[] { p.length - i,
208
            policyConstraints.add (new int[]
199
                                            constr.getRequireExplicitPolicy() });
209
              { p.length-i, constr.getRequireExplicitPolicy() });
200
        updatePolicyTree(p[i], rootNode, p.length - i, (PKIXParameters) params,
210
          }
201
                         checkExplicitPolicy(p.length - i, policyConstraints));
211
212
        updatePolicyTree(p[i], rootNode, p.length-i, (PKIXParameters) params,
213
                         checkExplicitPolicy (p.length-i, policyConstraints));
214
215
        // The rest of the tests involve this cert's relationship with the
202
        // The rest of the tests involve this cert's relationship with the
216
        // next in the path. If this cert is the end entity, we can stop.
203
        // next in the path. If this cert is the end entity, we can stop.
217
        if (i == 0)
204
        if (i == 0)
Lines 228-263 Link Here
228
                // If the DSA public key is missing its parameters, use those
215
                // If the DSA public key is missing its parameters, use those
229
                // from the previous cert's key.
216
                // from the previous cert's key.
230
                if (dsa == null || dsa.getP() == null || dsa.getG() == null
217
                if (dsa == null || dsa.getP() == null || dsa.getG() == null
231
                      || dsa.getQ() == null)
218
                    || dsa.getQ() == null)
232
                  {
219
                  {
233
                    if (prevKey == null)
220
                    if (prevKey == null)
234
                      throw new InvalidKeyException("DSA keys not chainable");
221
                      throw new InvalidKeyException("DSA keys not chainable");
235
                    if (!(prevKey instanceof DSAPublicKey))
222
                    if (! (prevKey instanceof DSAPublicKey))
236
                      throw new InvalidKeyException("DSA keys not chainable");
223
                      throw new InvalidKeyException("DSA keys not chainable");
237
                    dsa = ((DSAPublicKey) prevKey).getParams();
224
                    dsa = ((DSAPublicKey) prevKey).getParams();
238
                    pubKey = new DSSPublicKey(Registry.X509_ENCODING_ID,
225
                    pubKey = new DSSPublicKey(Registry.X509_ENCODING_ID,
239
                                              dsa.getP(),
226
                                              dsa.getP(), dsa.getQ(),
240
                                              dsa.getQ(),
241
                                              dsa.getG(),
227
                                              dsa.getG(),
242
                                              ((DSAPublicKey) pubKey).getY());
228
                                              ((DSAPublicKey) pubKey).getY());
243
                  }
229
                  }
244
              }
230
              }
245
            if (sigProvider == null)
231
            if (sigProvider == null)
246
              p[i-1].verify(pubKey);
232
              p[i - 1].verify(pubKey);
247
            else
233
            else
248
              p[i-1].verify(pubKey, sigProvider);
234
              p[i - 1].verify(pubKey, sigProvider);
249
            prevKey = pubKey;
235
            prevKey = pubKey;
250
          }
236
          }
251
        catch (Exception e)
237
        catch (Exception e)
252
          {
238
          {
253
            throw new CertPathValidatorException(e.toString());
239
            throw new CertPathValidatorException(e.toString());
254
          }
240
          }
255
        if (!p[i].getSubjectDN().equals(p[i-1].getIssuerDN()))
241
        if (! p[i].getSubjectDN().equals(p[i - 1].getIssuerDN()))
256
          throw new CertPathValidatorException("issuer DN mismatch");
242
          throw new CertPathValidatorException("issuer DN mismatch");
257
        boolean[] issuerUid = p[i-1].getIssuerUniqueID();
243
        boolean[] issuerUid = p[i - 1].getIssuerUniqueID();
258
        boolean[] subjectUid = p[i].getSubjectUniqueID();
244
        boolean[] subjectUid = p[i].getSubjectUniqueID();
259
        if (issuerUid != null && subjectUid != null)
245
        if (issuerUid != null && subjectUid != null)
260
          if (!Arrays.equals(issuerUid, subjectUid))
246
          if (! Arrays.equals(issuerUid, subjectUid))
261
            throw new CertPathValidatorException("UID mismatch");
247
            throw new CertPathValidatorException("UID mismatch");
262
248
263
        // Check the certificate against the revocation lists.
249
        // Check the certificate against the revocation lists.
Lines 274-280 Link Here
274
              }
260
              }
275
            List certStores = ((PKIXParameters) params).getCertStores();
261
            List certStores = ((PKIXParameters) params).getCertStores();
276
            List crls = new LinkedList();
262
            List crls = new LinkedList();
277
            for (Iterator it = certStores.iterator(); it.hasNext(); )
263
            for (Iterator it = certStores.iterator(); it.hasNext();)
278
              {
264
              {
279
                CertStore cs = (CertStore) it.next();
265
                CertStore cs = (CertStore) it.next();
280
                try
266
                try
Lines 289-318 Link Here
289
            if (crls.isEmpty())
275
            if (crls.isEmpty())
290
              throw new CertPathValidatorException("no CRLs for issuer");
276
              throw new CertPathValidatorException("no CRLs for issuer");
291
            boolean certOk = false;
277
            boolean certOk = false;
292
            for (Iterator it = crls.iterator(); it.hasNext(); )
278
            for (Iterator it = crls.iterator(); it.hasNext();)
293
              {
279
              {
294
                CRL crl = (CRL) it.next();
280
                CRL crl = (CRL) it.next();
295
                if (!(crl instanceof X509CRL))
281
                if (! (crl instanceof X509CRL))
296
                  continue;
282
                  continue;
297
                X509CRL xcrl = (X509CRL) crl;
283
                X509CRL xcrl = (X509CRL) crl;
298
                if (!checkCRL(xcrl, p, now, p[i], pubKey, certStores))
284
                if (! checkCRL(xcrl, p, now, p[i], pubKey, certStores))
299
                  continue;
285
                  continue;
300
                if (xcrl.isRevoked(p[i-1]))
286
                if (xcrl.isRevoked(p[i - 1]))
301
                  throw new CertPathValidatorException("certificate is revoked");
287
                  throw new CertPathValidatorException("certificate is revoked");
302
                else
288
                else
303
                  certOk = true;
289
                  certOk = true;
304
              }
290
              }
305
            if (!certOk)
291
            if (! certOk)
306
              throw new CertPathValidatorException("certificate's validity could not be determined");
292
              throw new CertPathValidatorException(
293
                  "certificate's validity could not be determined");
307
          }
294
          }
308
      }
295
      }
309
    rootNode.setReadOnly();
296
    rootNode.setReadOnly();
310
311
    // Now ensure that the first certificate in the chain was issued
297
    // Now ensure that the first certificate in the chain was issued
312
    // by a trust anchor.
298
    // by a trust anchor.
313
    Exception cause = null;
299
    Exception cause = null;
314
    Set anchors = ((PKIXParameters) params).getTrustAnchors();
300
    Set anchors = ((PKIXParameters) params).getTrustAnchors();
315
    for (Iterator i = anchors.iterator(); i.hasNext(); )
301
    for (Iterator i = anchors.iterator(); i.hasNext();)
316
      {
302
      {
317
        TrustAnchor anchor = (TrustAnchor) i.next();
303
        TrustAnchor anchor = (TrustAnchor) i.next();
318
        X509Certificate anchorCert = null;
304
        X509Certificate anchorCert = null;
Lines 330-336 Link Here
330
          {
316
          {
331
            if (anchorCert != null)
317
            if (anchorCert != null)
332
              anchorCert.checkValidity(now);
318
              anchorCert.checkValidity(now);
333
            p[p.length-1].verify(anchorKey);
319
            p[p.length - 1].verify(anchorKey);
334
            if (anchorCert != null && anchorCert.getBasicConstraints() >= 0
320
            if (anchorCert != null && anchorCert.getBasicConstraints() >= 0
335
                && anchorCert.getBasicConstraints() < p.length)
321
                && anchorCert.getBasicConstraints() < p.length)
336
              continue;
322
              continue;
Lines 350-356 Link Here
350
                  selector.addIssuerName(anchor.getCAName());
336
                  selector.addIssuerName(anchor.getCAName());
351
                List certStores = ((PKIXParameters) params).getCertStores();
337
                List certStores = ((PKIXParameters) params).getCertStores();
352
                List crls = new LinkedList();
338
                List crls = new LinkedList();
353
                for (Iterator it = certStores.iterator(); it.hasNext(); )
339
                for (Iterator it = certStores.iterator(); it.hasNext();)
354
                  {
340
                  {
355
                    CertStore cs = (CertStore) it.next();
341
                    CertStore cs = (CertStore) it.next();
356
                    try
342
                    try
Lines 364-373 Link Here
364
                  }
350
                  }
365
                if (crls.isEmpty())
351
                if (crls.isEmpty())
366
                  continue;
352
                  continue;
367
                for (Iterator it = crls.iterator(); it.hasNext(); )
353
                for (Iterator it = crls.iterator(); it.hasNext();)
368
                  {
354
                  {
369
                    CRL crl = (CRL) it.next();
355
                    CRL crl = (CRL) it.next();
370
                    if (!(crl instanceof X509CRL))
356
                    if (! (crl instanceof X509CRL))
371
                      continue;
357
                      continue;
372
                    X509CRL xcrl = (X509CRL) crl;
358
                    X509CRL xcrl = (X509CRL) crl;
373
                    try
359
                    try
Lines 381-391 Link Here
381
                    Date nextUpdate = xcrl.getNextUpdate();
367
                    Date nextUpdate = xcrl.getNextUpdate();
382
                    if (nextUpdate != null && nextUpdate.compareTo(now) < 0)
368
                    if (nextUpdate != null && nextUpdate.compareTo(now) < 0)
383
                      continue;
369
                      continue;
384
                    if (xcrl.isRevoked(p[p.length-1]))
370
                    if (xcrl.isRevoked(p[p.length - 1]))
385
                      throw new CertPathValidatorException("certificate is revoked");
371
                      throw new CertPathValidatorException("certificate is revoked");
386
                  }
372
                  }
387
              }
373
              }
388
389
            // The chain is valid; return the result.
374
            // The chain is valid; return the result.
390
            return new PKIXCertPathValidatorResult(anchor, rootNode,
375
            return new PKIXCertPathValidatorResult(anchor, rootNode,
391
                                                   p[0].getPublicKey());
376
                                                   p[0].getPublicKey());
Lines 396-429 Link Here
396
            continue;
381
            continue;
397
          }
382
          }
398
      }
383
      }
399
400
    // The path is not valid.
384
    // The path is not valid.
401
    CertPathValidatorException cpve =
385
    CertPathValidatorException cpve =
402
      new CertPathValidatorException("path validation failed");
386
        new CertPathValidatorException("path validation failed");
403
    if (cause != null)
387
    if (cause != null)
404
      cpve.initCause (cause);
388
      cpve.initCause(cause);
405
    throw cpve;
389
    throw cpve;
406
  }
390
  }
407
391
408
  // Own methods.
409
  // -------------------------------------------------------------------------
410
411
  /**
392
  /**
412
   * Check if a given CRL is acceptable for checking the revocation status
393
   * Check if a given CRL is acceptable for checking the revocation status of
413
   * of certificates in the path being checked.
394
   * certificates in the path being checked.
414
   *
395
   * <p>
415
   * <p>The CRL is accepted iff:</p>
396
   * The CRL is accepted iff:
416
   *
417
   * <ol>
397
   * <ol>
418
   * <li>The <i>nextUpdate</i> field (if present) is in the future.</li>
398
   * <li>The <i>nextUpdate</i> field (if present) is in the future.</li>
419
   * <li>The CRL does not contain any unsupported critical extensions.</li>
399
   * <li>The CRL does not contain any unsupported critical extensions.</li>
420
   * <li>The CRL is signed by one of the certificates in the path, or,</li>
400
   * <li>The CRL is signed by one of the certificates in the path, or,</li>
421
   * <li>The CRL is signed by the given public key and was issued by the
401
   * <li>The CRL is signed by the given public key and was issued by the public
422
   * public key's subject, or,</li>
402
   * key's subject, or,</li>
423
   * <li>The CRL is signed by a certificate in the given cert stores, and
403
   * <li>The CRL is signed by a certificate in the given cert stores, and that
424
   * that cert is signed by one of the certificates in the path.</li>
404
   * cert is signed by one of the certificates in the path.</li>
425
   * </ol>
405
   * </ol>
426
   *
406
   * 
427
   * @param crl The CRL being checked.
407
   * @param crl The CRL being checked.
428
   * @param path The path this CRL is being checked against.
408
   * @param path The path this CRL is being checked against.
429
   * @param now The value to use as 'now'.
409
   * @param now The value to use as 'now'.
Lines 431-439 Link Here
431
   * @param pubKey The public key to check.
411
   * @param pubKey The public key to check.
432
   * @return True if the CRL is acceptable.
412
   * @return True if the CRL is acceptable.
433
   */
413
   */
434
  private static boolean checkCRL(X509CRL crl, X509Certificate[] path, Date now,
414
  private static boolean checkCRL(X509CRL crl, X509Certificate[] path,
435
                                  X509Certificate pubKeyCert, PublicKey pubKey,
415
                                  Date now, X509Certificate pubKeyCert,
436
                                  List certStores)
416
                                  PublicKey pubKey, List certStores)
437
  {
417
  {
438
    Date nextUpdate = crl.getNextUpdate();
418
    Date nextUpdate = crl.getNextUpdate();
439
    if (nextUpdate != null && nextUpdate.compareTo(now) < 0)
419
    if (nextUpdate != null && nextUpdate.compareTo(now) < 0)
Lines 442-453 Link Here
442
      return false;
422
      return false;
443
    for (int i = 0; i < path.length; i++)
423
    for (int i = 0; i < path.length; i++)
444
      {
424
      {
445
        if (!path[i].getSubjectDN().equals(crl.getIssuerDN()))
425
        if (! path[i].getSubjectDN().equals(crl.getIssuerDN()))
446
          continue;
426
          continue;
447
        boolean[] keyUsage = path[i].getKeyUsage();
427
        boolean[] keyUsage = path[i].getKeyUsage();
448
        if (keyUsage != null)
428
        if (keyUsage != null)
449
          {
429
          {
450
            if (!keyUsage[KeyUsage.CRL_SIGN])
430
            if (! keyUsage[KeyUsage.CRL_SIGN])
451
              continue;
431
              continue;
452
          }
432
          }
453
        try
433
        try
Lines 466-472 Link Here
466
            boolean[] keyUsage = pubKeyCert.getKeyUsage();
446
            boolean[] keyUsage = pubKeyCert.getKeyUsage();
467
            if (keyUsage != null)
447
            if (keyUsage != null)
468
              {
448
              {
469
                if (!keyUsage[KeyUsage.CRL_SIGN])
449
                if (! keyUsage[KeyUsage.CRL_SIGN])
470
                  throw new Exception();
450
                  throw new Exception();
471
              }
451
              }
472
            crl.verify(pubKey);
452
            crl.verify(pubKey);
Lines 481-487 Link Here
481
        X509CertSelectorImpl select = new X509CertSelectorImpl();
461
        X509CertSelectorImpl select = new X509CertSelectorImpl();
482
        select.addSubjectName(crl.getIssuerDN());
462
        select.addSubjectName(crl.getIssuerDN());
483
        List certs = new LinkedList();
463
        List certs = new LinkedList();
484
        for (Iterator it = certStores.iterator(); it.hasNext(); )
464
        for (Iterator it = certStores.iterator(); it.hasNext();)
485
          {
465
          {
486
            CertStore cs = (CertStore) it.next();
466
            CertStore cs = (CertStore) it.next();
487
            try
467
            try
Lines 492-508 Link Here
492
              {
472
              {
493
              }
473
              }
494
          }
474
          }
495
        for (Iterator it = certs.iterator(); it.hasNext(); )
475
        for (Iterator it = certs.iterator(); it.hasNext();)
496
          {
476
          {
497
            X509Certificate c = (X509Certificate) it.next();
477
            X509Certificate c = (X509Certificate) it.next();
498
            for (int i = 0; i < path.length; i++)
478
            for (int i = 0; i < path.length; i++)
499
              {
479
              {
500
                if (!c.getIssuerDN().equals(path[i].getSubjectDN()))
480
                if (! c.getIssuerDN().equals(path[i].getSubjectDN()))
501
                  continue;
481
                  continue;
502
                boolean[] keyUsage = c.getKeyUsage();
482
                boolean[] keyUsage = c.getKeyUsage();
503
                if (keyUsage != null)
483
                if (keyUsage != null)
504
                  {
484
                  {
505
                    if (!keyUsage[KeyUsage.CRL_SIGN])
485
                    if (! keyUsage[KeyUsage.CRL_SIGN])
506
                      continue;
486
                      continue;
507
                  }
487
                  }
508
                try
488
                try
Lines 534-543 Link Here
534
    if (cert instanceof GnuPKIExtension)
514
    if (cert instanceof GnuPKIExtension)
535
      {
515
      {
536
        Collection exts = ((GnuPKIExtension) cert).getExtensions();
516
        Collection exts = ((GnuPKIExtension) cert).getExtensions();
537
        for (Iterator it = exts.iterator(); it.hasNext(); )
517
        for (Iterator it = exts.iterator(); it.hasNext();)
538
          {
518
          {
539
            Extension ext = (Extension) it.next();
519
            Extension ext = (Extension) it.next();
540
            if (ext.isCritical() && !ext.isSupported())
520
            if (ext.isCritical() && ! ext.isSupported())
541
              s.add(ext.getOid().toString());
521
              s.add(ext.getOid().toString());
542
          }
522
          }
543
      }
523
      }
Lines 550-562 Link Here
550
   * Perform a basic sanity check on the CA certificate at <code>index</code>.
530
   * Perform a basic sanity check on the CA certificate at <code>index</code>.
551
   */
531
   */
552
  private static void basicSanity(X509Certificate[] path, int index)
532
  private static void basicSanity(X509Certificate[] path, int index)
553
    throws CertPathValidatorException
533
      throws CertPathValidatorException
554
  {
534
  {
555
    X509Certificate cert = path[index];
535
    X509Certificate cert = path[index];
556
    int pathLen = 0;
536
    int pathLen = 0;
557
    for (int i = index - 1; i > 0; i--)
537
    for (int i = index - 1; i > 0; i--)
558
      {
538
      {
559
        if (!path[i].getIssuerDN().equals(path[i].getSubjectDN()))
539
        if (! path[i].getIssuerDN().equals(path[i].getSubjectDN()))
560
          pathLen++;
540
          pathLen++;
561
      }
541
      }
562
    Extension e = null;
542
    Extension e = null;
Lines 577-599 Link Here
577
    if (e == null)
557
    if (e == null)
578
      throw new CertPathValidatorException("no basicConstraints");
558
      throw new CertPathValidatorException("no basicConstraints");
579
    BasicConstraints bc = (BasicConstraints) e.getValue();
559
    BasicConstraints bc = (BasicConstraints) e.getValue();
580
    if (!bc.isCA())
560
    if (! bc.isCA())
581
      throw new CertPathValidatorException("certificate cannot be used to verify signatures");
561
      throw new CertPathValidatorException(
582
    if (bc.getPathLengthConstraint() >= 0 && bc.getPathLengthConstraint() < pathLen)
562
          "certificate cannot be used to verify signatures");
563
    if (bc.getPathLengthConstraint() >= 0
564
        && bc.getPathLengthConstraint() < pathLen)
583
      throw new CertPathValidatorException("path is too long");
565
      throw new CertPathValidatorException("path is too long");
584
566
585
    boolean[] keyUsage = cert.getKeyUsage();
567
    boolean[] keyUsage = cert.getKeyUsage();
586
    if (keyUsage != null)
568
    if (keyUsage != null)
587
      {
569
      {
588
        if (!keyUsage[KeyUsage.KEY_CERT_SIGN])
570
        if (! keyUsage[KeyUsage.KEY_CERT_SIGN])
589
          throw new CertPathValidatorException("certificate cannot be used to sign certificates");
571
          throw new CertPathValidatorException(
572
              "certificate cannot be used to sign certificates");
590
      }
573
      }
591
  }
574
  }
592
575
593
  private static void updatePolicyTree(X509Certificate cert, PolicyNodeImpl root,
576
  private static void updatePolicyTree(X509Certificate cert,
594
                                       int depth, PKIXParameters params,
577
                                       PolicyNodeImpl root, int depth,
578
                                       PKIXParameters params,
595
                                       boolean explicitPolicy)
579
                                       boolean explicitPolicy)
596
    throws CertPathValidatorException
580
      throws CertPathValidatorException
597
  {
581
  {
598
    if (Configuration.DEBUG)
582
    if (Configuration.DEBUG)
599
      log.fine("updatePolicyTree depth == " + depth);
583
      log.fine("updatePolicyTree depth == " + depth);
Lines 624-630 Link Here
624
              }
608
              }
625
          }
609
          }
626
      }
610
      }
627
    while (!stack.isEmpty());
611
    while (! stack.isEmpty());
628
612
629
    Extension e = null;
613
    Extension e = null;
630
    CertificatePolicies policies = null;
614
    CertificatePolicies policies = null;
Lines 647-664 Link Here
647
        log.fine("nodes are == " + nodes);
631
        log.fine("nodes are == " + nodes);
648
        log.fine("cert policies are == " + cp);
632
        log.fine("cert policies are == " + cp);
649
      }
633
      }
650
    for (Iterator it = nodes.iterator(); it.hasNext(); )
634
    for (Iterator it = nodes.iterator(); it.hasNext();)
651
      {
635
      {
652
        PolicyNodeImpl parent = (PolicyNodeImpl) it.next();
636
        PolicyNodeImpl parent = (PolicyNodeImpl) it.next();
653
        if (Configuration.DEBUG)
637
        if (Configuration.DEBUG)
654
          log.fine("adding policies to " + parent);
638
          log.fine("adding policies to " + parent);
655
        for (Iterator it2 = cp.iterator(); it2.hasNext(); )
639
        for (Iterator it2 = cp.iterator(); it2.hasNext();)
656
          {
640
          {
657
            OID policy = (OID) it2.next();
641
            OID policy = (OID) it2.next();
658
            if (Configuration.DEBUG)
642
            if (Configuration.DEBUG)
659
              log.fine("trying to add policy == " + policy);
643
              log.fine("trying to add policy == " + policy);
660
            if (policy.toString().equals(ANY_POLICY) &&
644
            if (policy.toString().equals(ANY_POLICY)
661
                params.isAnyPolicyInhibited())
645
                && params.isAnyPolicyInhibited())
662
              continue;
646
              continue;
663
            PolicyNodeImpl child = new PolicyNodeImpl();
647
            PolicyNodeImpl child = new PolicyNodeImpl();
664
            child.setValidPolicy(policy.toString());
648
            child.setValidPolicy(policy.toString());
Lines 673-700 Link Here
673
                parent.addChild(child);
657
                parent.addChild(child);
674
                match = true;
658
                match = true;
675
              }
659
              }
676
            else if (ANY_POLICY.equals (policy.toString()))
660
            else if (ANY_POLICY.equals(policy.toString()))
677
              {
661
              {
678
                parent.addChild (child);
662
                parent.addChild(child);
679
                match = true;
663
                match = true;
680
              }
664
              }
681
            if (match && policies != null)
665
            if (match && policies != null)
682
              {
666
              {
683
                List qualifiers = policies.getPolicyQualifierInfos (policy);
667
                List qualifiers = policies.getPolicyQualifierInfos(policy);
684
                if (qualifiers != null)
668
                if (qualifiers != null)
685
                  child.addAllPolicyQualifiers (qualifiers);
669
                  child.addAllPolicyQualifiers(qualifiers);
686
              }
670
              }
687
          }
671
          }
688
      }
672
      }
689
    if (!match && (params.isExplicitPolicyRequired() || explicitPolicy))
673
    if (! match && (params.isExplicitPolicyRequired() || explicitPolicy))
690
      throw new CertPathValidatorException("policy tree building failed");
674
      throw new CertPathValidatorException("policy tree building failed");
691
  }
675
  }
692
676
693
  private boolean checkExplicitPolicy (int depth, List explicitPolicies)
677
  private boolean checkExplicitPolicy(int depth, List explicitPolicies)
694
  {
678
  {
695
    if (Configuration.DEBUG)
679
    if (Configuration.DEBUG)
696
      log.fine("checkExplicitPolicy depth=" + depth);
680
      log.fine("checkExplicitPolicy depth=" + depth);
697
    for (Iterator it = explicitPolicies.iterator(); it.hasNext(); )
681
    for (Iterator it = explicitPolicies.iterator(); it.hasNext();)
698
      {
682
      {
699
        int[] i = (int[]) it.next();
683
        int[] i = (int[]) it.next();
700
        int caDepth = i[0];
684
        int caDepth = i[0];
(-)provider/X509CertificateFactory.java (-36 / +25 lines)
Lines 59-88 Link Here
59
import java.util.LinkedList;
59
import java.util.LinkedList;
60
import java.util.List;
60
import java.util.List;
61
61
62
public class X509CertificateFactory extends CertificateFactorySpi
62
public class X509CertificateFactory
63
    extends CertificateFactorySpi
63
{
64
{
64
65
  // Constants.
66
  // ------------------------------------------------------------------------
67
68
  public static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----";
65
  public static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----";
66
69
  public static final String END_CERTIFICATE = "-----END CERTIFICATE-----";
67
  public static final String END_CERTIFICATE = "-----END CERTIFICATE-----";
68
70
  public static final String BEGIN_X509_CRL = "-----BEGIN X509 CRL-----";
69
  public static final String BEGIN_X509_CRL = "-----BEGIN X509 CRL-----";
71
  public static final String END_X509_CRL = "-----END X509 CRL-----";
72
70
73
  // Constructors.
71
  public static final String END_X509_CRL = "-----END X509 CRL-----";
74
  // ------------------------------------------------------------------------
75
72
76
  public X509CertificateFactory()
73
  public X509CertificateFactory()
77
  {
74
  {
78
    super();
75
    super();
79
  }
76
  }
80
77
81
  // Instance methods.
82
  // ------------------------------------------------------------------------
83
84
  public Certificate engineGenerateCertificate(InputStream inStream)
78
  public Certificate engineGenerateCertificate(InputStream inStream)
85
    throws CertificateException
79
      throws CertificateException
86
  {
80
  {
87
    try
81
    try
88
      {
82
      {
Lines 91-103 Link Here
91
    catch (IOException ioe)
85
    catch (IOException ioe)
92
      {
86
      {
93
        CertificateException ce = new CertificateException(ioe.getMessage());
87
        CertificateException ce = new CertificateException(ioe.getMessage());
94
        ce.initCause (ioe);
88
        ce.initCause(ioe);
95
        throw ce;
89
        throw ce;
96
      }
90
      }
97
  }
91
  }
98
92
99
  public Collection engineGenerateCertificates(InputStream inStream)
93
  public Collection engineGenerateCertificates(InputStream inStream)
100
    throws CertificateException
94
      throws CertificateException
101
  {
95
  {
102
    LinkedList certs = new LinkedList();
96
    LinkedList certs = new LinkedList();
103
    while (true)
97
    while (true)
Lines 113-119 Link Here
113
        catch (IOException ioe)
107
        catch (IOException ioe)
114
          {
108
          {
115
            CertificateException ce = new CertificateException(ioe.getMessage());
109
            CertificateException ce = new CertificateException(ioe.getMessage());
116
            ce.initCause (ioe);
110
            ce.initCause(ioe);
117
            throw ce;
111
            throw ce;
118
          }
112
          }
119
      }
113
      }
Lines 129-141 Link Here
129
    catch (IOException ioe)
123
    catch (IOException ioe)
130
      {
124
      {
131
        CRLException crle = new CRLException(ioe.getMessage());
125
        CRLException crle = new CRLException(ioe.getMessage());
132
        crle.initCause (ioe);
126
        crle.initCause(ioe);
133
        throw crle;
127
        throw crle;
134
      }
128
      }
135
  }
129
  }
136
130
137
  public Collection engineGenerateCRLs(InputStream inStream)
131
  public Collection engineGenerateCRLs(InputStream inStream)
138
    throws CRLException
132
      throws CRLException
139
  {
133
  {
140
    LinkedList crls = new LinkedList();
134
    LinkedList crls = new LinkedList();
141
    while (true)
135
    while (true)
Lines 151-157 Link Here
151
        catch (IOException ioe)
145
        catch (IOException ioe)
152
          {
146
          {
153
            CRLException crle = new CRLException(ioe.getMessage());
147
            CRLException crle = new CRLException(ioe.getMessage());
154
            crle.initCause (ioe);
148
            crle.initCause(ioe);
155
            throw crle;
149
            throw crle;
156
          }
150
          }
157
      }
151
      }
Lines 164-176 Link Here
164
  }
158
  }
165
159
166
  public CertPath engineGenerateCertPath(InputStream in)
160
  public CertPath engineGenerateCertPath(InputStream in)
167
    throws CertificateEncodingException
161
      throws CertificateEncodingException
168
  {
162
  {
169
    return new X509CertPath(in);
163
    return new X509CertPath(in);
170
  }
164
  }
171
165
172
  public CertPath engineGenerateCertPath(InputStream in, String encoding)
166
  public CertPath engineGenerateCertPath(InputStream in, String encoding)
173
    throws CertificateEncodingException
167
      throws CertificateEncodingException
174
  {
168
  {
175
    return new X509CertPath(in, encoding);
169
    return new X509CertPath(in, encoding);
176
  }
170
  }
Lines 180-200 Link Here
180
    return X509CertPath.ENCODINGS.iterator();
174
    return X509CertPath.ENCODINGS.iterator();
181
  }
175
  }
182
176
183
  // Own methods.
184
  // ------------------------------------------------------------------------
185
186
  private X509Certificate generateCert(InputStream inStream)
177
  private X509Certificate generateCert(InputStream inStream)
187
    throws IOException, CertificateException
178
      throws IOException, CertificateException
188
  {
179
  {
189
    if (inStream == null)
180
    if (inStream == null)
190
      throw new CertificateException("missing input stream");
181
      throw new CertificateException("missing input stream");
191
    if (!inStream.markSupported())
182
    if (! inStream.markSupported())
192
      inStream = new BufferedInputStream(inStream, 8192);
183
      inStream = new BufferedInputStream(inStream, 8192);
193
    inStream.mark(20);
184
    inStream.mark(20);
194
    int i = inStream.read();
185
    int i = inStream.read();
195
    if (i == -1)
186
    if (i == -1)
196
      throw new EOFException();
187
      throw new EOFException();
197
198
    // If the input is in binary DER format, the first byte MUST be
188
    // If the input is in binary DER format, the first byte MUST be
199
    // 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the
189
    // 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the
200
    // UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set.
190
    // UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set.
Lines 217-225 Link Here
217
              }
207
              }
218
            while (i != '\n' && i != '\r');
208
            while (i != '\n' && i != '\r');
219
          }
209
          }
220
        while (!line.toString().equals(BEGIN_CERTIFICATE));
210
        while (! line.toString().equals(BEGIN_CERTIFICATE));
221
        X509Certificate ret = new X509Certificate(
211
        X509Certificate ret = new X509Certificate(
222
           new BufferedInputStream(new Base64InputStream(inStream), 8192));
212
            new BufferedInputStream(new Base64InputStream(inStream), 8192));
223
        line.setLength(0);
213
        line.setLength(0);
224
        line.append('-'); // Base64InputStream will eat this.
214
        line.append('-'); // Base64InputStream will eat this.
225
        do
215
        do
Lines 232-238 Link Here
232
          }
222
          }
233
        while (i != '\n' && i != '\r');
223
        while (i != '\n' && i != '\r');
234
        // XXX ???
224
        // XXX ???
235
        if (!line.toString().equals(END_CERTIFICATE))
225
        if (! line.toString().equals(END_CERTIFICATE))
236
          throw new CertificateException("no end-of-certificate marker");
226
          throw new CertificateException("no end-of-certificate marker");
237
        return ret;
227
        return ret;
238
      }
228
      }
Lines 243-260 Link Here
243
      }
233
      }
244
  }
234
  }
245
235
246
  private X509CRL generateCRL(InputStream inStream)
236
  private X509CRL generateCRL(InputStream inStream) throws IOException,
247
    throws IOException, CRLException
237
      CRLException
248
  {
238
  {
249
    if (inStream == null)
239
    if (inStream == null)
250
      throw new CRLException("missing input stream");
240
      throw new CRLException("missing input stream");
251
    if (!inStream.markSupported())
241
    if (! inStream.markSupported())
252
      inStream = new BufferedInputStream(inStream, 8192);
242
      inStream = new BufferedInputStream(inStream, 8192);
253
    inStream.mark(20);
243
    inStream.mark(20);
254
    int i = inStream.read();
244
    int i = inStream.read();
255
    if (i == -1)
245
    if (i == -1)
256
      throw new EOFException();
246
      throw new EOFException();
257
258
    // If the input is in binary DER format, the first byte MUST be
247
    // If the input is in binary DER format, the first byte MUST be
259
    // 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the
248
    // 0x30, which stands for the ASN.1 [UNIVERSAL 16], which is the
260
    // UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set.
249
    // UNIVERSAL SEQUENCE, with the CONSTRUCTED bit (0x20) set.
Lines 277-285 Link Here
277
              }
266
              }
278
            while (i != '\n' && i != '\r');
267
            while (i != '\n' && i != '\r');
279
          }
268
          }
280
        while (!line.toString().startsWith(BEGIN_X509_CRL));
269
        while (! line.toString().startsWith(BEGIN_X509_CRL));
281
        X509CRL ret = new X509CRL(
270
        X509CRL ret = new X509CRL(
282
           new BufferedInputStream(new Base64InputStream(inStream), 8192));
271
            new BufferedInputStream(new Base64InputStream(inStream), 8192));
283
        line.setLength(0);
272
        line.setLength(0);
284
        line.append('-'); // Base64InputStream will eat this.
273
        line.append('-'); // Base64InputStream will eat this.
285
        do
274
        do
Lines 292-298 Link Here
292
          }
281
          }
293
        while (i != '\n' && i != '\r');
282
        while (i != '\n' && i != '\r');
294
        // XXX ???
283
        // XXX ???
295
        if (!line.toString().startsWith(END_X509_CRL))
284
        if (! line.toString().startsWith(END_X509_CRL))
296
          throw new CRLException("no end-of-CRL marker");
285
          throw new CRLException("no end-of-CRL marker");
297
        return ret;
286
        return ret;
298
      }
287
      }
(-)sig/BaseSignature.java (-70 / +28 lines)
Lines 49-63 Link Here
49
import java.util.Random;
49
import java.util.Random;
50
50
51
/**
51
/**
52
 * <p>A base abstract class to facilitate implementations of concrete
52
 * A base abstract class to facilitate implementations of concrete Signatures.
53
 * Signatures.</p>
54
 */
53
 */
55
public abstract class BaseSignature implements ISignature
54
public abstract class BaseSignature
55
    implements ISignature
56
{
56
{
57
58
  // Constants and variables
59
  // -------------------------------------------------------------------------
60
61
  /** The canonical name of this signature scheme. */
57
  /** The canonical name of this signature scheme. */
62
  protected String schemeName;
58
  protected String schemeName;
63
59
Lines 79-87 Link Here
79
  /** Our default source of randomness. */
75
  /** Our default source of randomness. */
80
  private PRNG prng = null;
76
  private PRNG prng = null;
81
77
82
  // Constructor(s)
83
  // -------------------------------------------------------------------------
84
85
  /**
78
  /**
86
   * Trivial constructor.
79
   * Trivial constructor.
87
   * 
80
   * 
Lines 101-114 Link Here
101
    this.md = md;
94
    this.md = md;
102
  }
95
  }
103
96
104
  // Class methods
105
  // -------------------------------------------------------------------------
106
107
  // Instance methods
108
  // -------------------------------------------------------------------------
109
110
  // gnu.crypto.sig.ISignature interface implementation ----------------------
111
112
  public String name()
97
  public String name()
113
  {
98
  {
114
    return schemeName + "-" + md.name();
99
    return schemeName + "-" + md.name();
Lines 117-167 Link Here
117
  public void setupVerify(Map attributes) throws IllegalArgumentException
102
  public void setupVerify(Map attributes) throws IllegalArgumentException
118
  {
103
  {
119
    setup(attributes);
104
    setup(attributes);
120
121
    // do we have a public key?
105
    // do we have a public key?
122
    PublicKey key = (PublicKey) attributes.get(VERIFIER_KEY);
106
    PublicKey key = (PublicKey) attributes.get(VERIFIER_KEY);
123
    if (key != null)
107
    if (key != null)
124
      {
108
      setupForVerification(key);
125
        setupForVerification(key);
126
      }
127
  }
109
  }
128
110
129
  public void setupSign(Map attributes) throws IllegalArgumentException
111
  public void setupSign(Map attributes) throws IllegalArgumentException
130
  {
112
  {
131
    setup(attributes);
113
    setup(attributes);
132
133
    // do we have a private key?
114
    // do we have a private key?
134
    PrivateKey key = (PrivateKey) attributes.get(SIGNER_KEY);
115
    PrivateKey key = (PrivateKey) attributes.get(SIGNER_KEY);
135
    if (key != null)
116
    if (key != null)
136
      {
117
      setupForSigning(key);
137
        setupForSigning(key);
138
      }
139
  }
118
  }
140
119
141
  public void update(byte b)
120
  public void update(byte b)
142
  {
121
  {
143
    if (md == null)
122
    if (md == null)
144
      {
123
      throw new IllegalStateException();
145
        throw new IllegalStateException();
124
146
      }
147
    md.update(b);
125
    md.update(b);
148
  }
126
  }
149
127
150
  public void update(byte[] b, int off, int len)
128
  public void update(byte[] b, int off, int len)
151
  {
129
  {
152
    if (md == null)
130
    if (md == null)
153
      {
131
      throw new IllegalStateException();
154
        throw new IllegalStateException();
132
155
      }
156
    md.update(b, off, len);
133
    md.update(b, off, len);
157
  }
134
  }
158
135
159
  public Object sign()
136
  public Object sign()
160
  {
137
  {
161
    if (md == null || privateKey == null)
138
    if (md == null || privateKey == null)
162
      {
139
      throw new IllegalStateException();
163
        throw new IllegalStateException();
164
      }
165
140
166
    return generateSignature();
141
    return generateSignature();
167
  }
142
  }
Lines 169-183 Link Here
169
  public boolean verify(Object sig)
144
  public boolean verify(Object sig)
170
  {
145
  {
171
    if (md == null || publicKey == null)
146
    if (md == null || publicKey == null)
172
      {
147
      throw new IllegalStateException();
173
        throw new IllegalStateException();
174
      }
175
148
176
    return verifySignature(sig);
149
    return verifySignature(sig);
177
  }
150
  }
178
151
179
  // abstract methods to be implemented by concrete subclasses ---------------
180
181
  public abstract Object clone();
152
  public abstract Object clone();
182
153
183
  protected abstract void setupForVerification(PublicKey key)
154
  protected abstract void setupForVerification(PublicKey key)
Lines 191-198 Link Here
191
  protected abstract boolean verifySignature(Object signature)
162
  protected abstract boolean verifySignature(Object signature)
192
      throws IllegalStateException;
163
      throws IllegalStateException;
193
164
194
  // Other instance methods --------------------------------------------------
195
196
  /** Initialises the internal fields of this instance. */
165
  /** Initialises the internal fields of this instance. */
197
  protected void init()
166
  protected void init()
198
  {
167
  {
Lines 204-236 Link Here
204
  }
173
  }
205
174
206
  /**
175
  /**
207
   * <p>Fills the designated byte array with random data.</p>
176
   * Fills the designated byte array with random data.
208
   *
177
   * 
209
   * @param buffer the byte array to fill with random data.
178
   * @param buffer the byte array to fill with random data.
210
   */
179
   */
211
  protected void nextRandomBytes(byte[] buffer)
180
  protected void nextRandomBytes(byte[] buffer)
212
  {
181
  {
213
    if (rnd != null)
182
    if (rnd != null)
214
      {
183
      rnd.nextBytes(buffer);
215
        rnd.nextBytes(buffer);
216
      }
217
    else if (irnd != null)
184
    else if (irnd != null)
218
      {
185
      try
219
        try
186
        {
220
          {
187
          irnd.nextBytes(buffer, 0, buffer.length);
221
            irnd.nextBytes(buffer, 0, buffer.length);
188
        }
222
          }
189
      catch (IllegalStateException x)
223
        catch (IllegalStateException x)
190
        {
224
          {
191
          throw new RuntimeException("nextRandomBytes(): " + x);
225
            throw new RuntimeException("nextRandomBytes(): "
192
        }
226
                                       + String.valueOf(x));
193
      catch (LimitReachedException x)
227
          }
194
        {
228
        catch (LimitReachedException x)
195
          throw new RuntimeException("nextRandomBytes(): " + x);
229
          {
196
        }
230
            throw new RuntimeException("nextRandomBytes(): "
231
                                       + String.valueOf(x));
232
          }
233
      }
234
    else
197
    else
235
      getDefaultPRNG().nextBytes(buffer);
198
      getDefaultPRNG().nextBytes(buffer);
236
  }
199
  }
Lines 238-254 Link Here
238
  private void setup(Map attributes)
201
  private void setup(Map attributes)
239
  {
202
  {
240
    init();
203
    init();
241
242
    // do we have a Random or SecureRandom, or should we use our own?
204
    // do we have a Random or SecureRandom, or should we use our own?
243
    Object obj = attributes.get(SOURCE_OF_RANDOMNESS);
205
    Object obj = attributes.get(SOURCE_OF_RANDOMNESS);
244
    if (obj instanceof Random)
206
    if (obj instanceof Random)
245
      {
207
      rnd = (Random) obj;
246
        rnd = (Random) obj;
247
      }
248
    else if (obj instanceof IRandom)
208
    else if (obj instanceof IRandom)
249
      {
209
      irnd = (IRandom) obj;
250
        irnd = (IRandom) obj;
251
      }
252
  }
210
  }
253
211
254
  private PRNG getDefaultPRNG()
212
  private PRNG getDefaultPRNG()
(-)sig/ISignature.java (-58 / +51 lines)
Lines 41-68 Link Here
41
import java.util.Map;
41
import java.util.Map;
42
42
43
/**
43
/**
44
 * <p>The visible methods of every signature-with-appendix scheme.</p>
44
 * The visible methods of every signature-with-appendix scheme.
45
 *
45
 * <p>
46
 * <p>The Handbook of Applied Cryptography (HAC), by A. Menezes &amp; al. states:
46
 * The Handbook of Applied Cryptography (HAC), by A. Menezes &amp; al. states:
47
 * "Digital signature schemes which require the message as input to the
47
 * "Digital signature schemes which require the message as input to the
48
 * verification algorithm are called <i>digital signature schemes with
48
 * verification algorithm are called <i>digital signature schemes with appendix</i>.
49
 * appendix</i>. ... They rely on cryptographic hash functions rather than
49
 * ... They rely on cryptographic hash functions rather than customised
50
 * customised redundancy functions, and are less prone to existential forgery
50
 * redundancy functions, and are less prone to existential forgery attacks."
51
 * attacks."</p>
51
 * <p>
52
 *
52
 * References:
53
 * <p>References:</p>
54
 * <ol>
53
 * <ol>
55
 *    <li><a href="http://www.cacr.math.uwaterloo.ca/hac/">Handbook of Applied
54
 * <li><a href="http://www.cacr.math.uwaterloo.ca/hac/">Handbook of Applied
56
 *    Cryptography</a>, Alfred J. Menezes, Paul C. van Oorschot and Scott A.
55
 * Cryptography</a>, Alfred J. Menezes, Paul C. van Oorschot and Scott A.
57
 *    Vanstone. Section 11.2.2 Digital signature schemes with appendix.</li>
56
 * Vanstone. Section 11.2.2 Digital signature schemes with appendix.</li>
58
 * </ol>
57
 * </ol>
59
 */
58
 */
60
public interface ISignature extends Cloneable
59
public interface ISignature
60
    extends Cloneable
61
{
61
{
62
63
  // Constants
64
  // -------------------------------------------------------------------------
65
66
  /** Property name of the verifier's public key. */
62
  /** Property name of the verifier's public key. */
67
  public static final String VERIFIER_KEY = "gnu.crypto.sig.public.key";
63
  public static final String VERIFIER_KEY = "gnu.crypto.sig.public.key";
68
64
Lines 71-166 Link Here
71
67
72
  /**
68
  /**
73
   * Property name of an optional {@link java.security.SecureRandom},
69
   * Property name of an optional {@link java.security.SecureRandom},
74
   * {@link java.util.Random}, or {@link gnu.java.security.prng.IRandom} instance to
70
   * {@link java.util.Random}, or {@link gnu.java.security.prng.IRandom}
75
   * use. The default is to use a classloader singleton from
71
   * instance to use. The default is to use a classloader singleton from
76
   * {@link gnu.java.security.util.PRNG}.
72
   * {@link gnu.java.security.util.PRNG}.
77
   */
73
   */
78
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.sig.prng";
74
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.sig.prng";
79
75
80
  // Methods
81
  // -------------------------------------------------------------------------
82
83
  /**
76
  /**
84
   * <p>Returns the canonical name of this signature scheme.</p>
77
   * Returns the canonical name of this signature scheme.
85
   *
78
   * 
86
   * @return the canonical name of this instance.
79
   * @return the canonical name of this instance.
87
   */
80
   */
88
  String name();
81
  String name();
89
82
90
  /**
83
  /**
91
   * <p>Initialises this instance for signature verification.</p>
84
   * Initialises this instance for signature verification.
92
   *
85
   * 
93
   * @param attributes the attributes to use for setting up this instance.
86
   * @param attributes the attributes to use for setting up this instance.
94
   * @throws IllegalArgumentException if the designated public key is not
87
   * @throws IllegalArgumentException if the designated public key is not
95
   * appropriate for this signature scheme.
88
   *           appropriate for this signature scheme.
96
   * @see #SOURCE_OF_RANDOMNESS
89
   * @see #SOURCE_OF_RANDOMNESS
97
   * @see #VERIFIER_KEY
90
   * @see #VERIFIER_KEY
98
   */
91
   */
99
  void setupVerify(Map attributes) throws IllegalArgumentException;
92
  void setupVerify(Map attributes) throws IllegalArgumentException;
100
93
101
  /**
94
  /**
102
   * <p>Initialises this instance for signature generation.</p>
95
   * Initialises this instance for signature generation.
103
   *
96
   * 
104
   * @param attributes the attributes to use for setting up this instance.
97
   * @param attributes the attributes to use for setting up this instance.
105
   * @throws IllegalArgumentException if the designated private key is not
98
   * @throws IllegalArgumentException if the designated private key is not
106
   * appropriate for this signature scheme.
99
   *           appropriate for this signature scheme.
107
   * @see #SOURCE_OF_RANDOMNESS
100
   * @see #SOURCE_OF_RANDOMNESS
108
   * @see #SIGNER_KEY
101
   * @see #SIGNER_KEY
109
   */
102
   */
110
  void setupSign(Map attributes) throws IllegalArgumentException;
103
  void setupSign(Map attributes) throws IllegalArgumentException;
111
104
112
  /**
105
  /**
113
   * <p>Digests one byte of a message for signing or verification purposes.</p>
106
   * Digests one byte of a message for signing or verification purposes.
114
   *
107
   * 
115
   * @param b the message byte to digest.
108
   * @param b the message byte to digest.
116
   * @throws IllegalStateException if this instance was not setup for
109
   * @throws IllegalStateException if this instance was not setup for signature
117
   * signature generation/verification.
110
   *           generation/verification.
118
   */
111
   */
119
  void update(byte b) throws IllegalStateException;
112
  void update(byte b) throws IllegalStateException;
120
113
121
  /**
114
  /**
122
   * <p>Digests a sequence of bytes from a message for signing or verification
115
   * Digests a sequence of bytes from a message for signing or verification
123
   * purposes.</p>
116
   * purposes.
124
   *
117
   * 
125
   * @param buffer the byte sequence to consider.
118
   * @param buffer the byte sequence to consider.
126
   * @param offset the byte poisition in <code>buffer</code> of the first byte
119
   * @param offset the byte poisition in <code>buffer</code> of the first byte
127
   * to consider.
120
   *          to consider.
128
   * @param length the number of bytes in <code>buffer</code> starting from the
121
   * @param length the number of bytes in <code>buffer</code> starting from
129
   * byte at index <code>offset</code> to digest.
122
   *          the byte at index <code>offset</code> to digest.
130
   * @throws IllegalStateException if this instance was not setup for
123
   * @throws IllegalStateException if this instance was not setup for signature
131
   * signature generation/verification.
124
   *           generation/verification.
132
   */
125
   */
133
  void update(byte[] buffer, int offset, int length)
126
  void update(byte[] buffer, int offset, int length)
134
      throws IllegalStateException;
127
      throws IllegalStateException;
135
128
136
  /**
129
  /**
137
   * <p>Terminates a signature generation phase by digesting and processing the
130
   * Terminates a signature generation phase by digesting and processing the
138
   * context of the underlying message digest algorithm instance.</p>
131
   * context of the underlying message digest algorithm instance.
139
   *
132
   * 
140
   * @return a {@link Object} representing the native output of the signature
133
   * @return a {@link Object} representing the native output of the signature
141
   * scheme implementation.
134
   *         scheme implementation.
142
   * @throws IllegalStateException if this instance was not setup for
135
   * @throws IllegalStateException if this instance was not setup for signature
143
   * signature generation.
136
   *           generation.
144
   */
137
   */
145
  Object sign() throws IllegalStateException;
138
  Object sign() throws IllegalStateException;
146
139
147
  /**
140
  /**
148
   * <p>Terminates a signature verification phase by digesting and processing
141
   * Terminates a signature verification phase by digesting and processing the
149
   * the context of the underlying message digest algorithm instance.</p>
142
   * context of the underlying message digest algorithm instance.
150
   *
143
   * 
151
   * @param signature a native signature object previously generated by an
144
   * @param signature a native signature object previously generated by an
152
   * invocation of the <code>sign()</code> method.
145
   *          invocation of the <code>sign()</code> method.
153
   * @return <code>true</code> iff the outpout of the verification phase
146
   * @return <code>true</code> iff the outpout of the verification phase
154
   * confirms that the designated signature object has been generated using the
147
   *         confirms that the designated signature object has been generated
155
   * corresponding public key of the recepient.
148
   *         using the corresponding public key of the recepient.
156
   * @throws IllegalStateException if this instance was not setup for
149
   * @throws IllegalStateException if this instance was not setup for signature
157
   * signature verification.
150
   *           verification.
158
   */
151
   */
159
  boolean verify(Object signature) throws IllegalStateException;
152
  boolean verify(Object signature) throws IllegalStateException;
160
153
161
  /**
154
  /**
162
   * <p>Returns a clone copy of this instance.</p>
155
   * Returns a clone copy of this instance.
163
   *
156
   * 
164
   * @return a clone copy of this instance.
157
   * @return a clone copy of this instance.
165
   */
158
   */
166
  Object clone();
159
  Object clone();
(-)sig/ISignatureCodec.java (-9 / +2 lines)
Lines 41-63 Link Here
41
import gnu.java.security.Registry;
41
import gnu.java.security.Registry;
42
42
43
/**
43
/**
44
 * <p>The visible methods of an object that knows how to encode and decode
44
 * The visible methods of an object that knows how to encode and decode
45
 * cryptographic signatures. Codecs are useful for (a) externalising signature
45
 * cryptographic signatures. Codecs are useful for (a) externalising signature
46
 * output data for storage and on-the-wire transmission, as well as (b) re-
46
 * output data for storage and on-the-wire transmission, as well as (b) re-
47
 * creating their internal Java representation from external sources.</p>
47
 * creating their internal Java representation from external sources.
48
 */
48
 */
49
public interface ISignatureCodec
49
public interface ISignatureCodec
50
{
50
{
51
52
  // Constants
53
  // -------------------------------------------------------------------------
54
55
  /** Constant identifying the <i>Raw</i> encoding format. */
51
  /** Constant identifying the <i>Raw</i> encoding format. */
56
  int RAW_FORMAT = Registry.RAW_ENCODING_ID;
52
  int RAW_FORMAT = Registry.RAW_ENCODING_ID;
57
53
58
  // Method(s)
59
  // -------------------------------------------------------------------------
60
61
  int getFormatID();
54
  int getFormatID();
62
55
63
  byte[] encodeSignature(Object signature);
56
  byte[] encodeSignature(Object signature);
(-)sig/SignatureFactory.java (-18 / +6 lines)
Lines 53-90 Link Here
53
{
53
{
54
  private static Set names;
54
  private static Set names;
55
55
56
  // Constructor(s)
57
  // -------------------------------------------------------------------------
58
59
  /** Trivial constructor to enforce Singleton pattern. */
56
  /** Trivial constructor to enforce Singleton pattern. */
60
  private SignatureFactory()
57
  private SignatureFactory()
61
  {
58
  {
62
    super();
59
    super();
63
  }
60
  }
64
61
65
  // Class methods
66
  // -------------------------------------------------------------------------
67
68
  /**
62
  /**
69
   * Returns an instance of a signature-with-appendix scheme given its name.
63
   * Returns an instance of a signature-with-appendix scheme given its name.
70
   *
64
   * 
71
   * @param ssa the case-insensitive signature-with-appendix scheme name.
65
   * @param ssa the case-insensitive signature-with-appendix scheme name.
72
   * @return an instance of the scheme, or <code>null</code> if none found.
66
   * @return an instance of the scheme, or <code>null</code> if none found.
73
   */
67
   */
74
  public static final ISignature getInstance(String ssa)
68
  public static final ISignature getInstance(String ssa)
75
  {
69
  {
76
    if (ssa == null)
70
    if (ssa == null)
77
      {
71
      return null;
78
        return null;
79
      }
80
72
81
    ssa = ssa.trim();
73
    ssa = ssa.trim();
82
    ssa = ssa.toLowerCase();
74
    ssa = ssa.toLowerCase();
83
    ISignature result = null;
75
    ISignature result = null;
84
    if (ssa.equalsIgnoreCase(Registry.DSA_SIG) || ssa.equals(Registry.DSS_SIG))
76
    if (ssa.equalsIgnoreCase(Registry.DSA_SIG) || ssa.equals(Registry.DSS_SIG))
85
      {
77
      result = new DSSSignature();
86
        result = new DSSSignature();
87
      }
88
    else if (ssa.startsWith(Registry.RSA_SIG_PREFIX))
78
    else if (ssa.startsWith(Registry.RSA_SIG_PREFIX))
89
      result = RSASignatureFactory.getInstance(ssa);
79
      result = RSASignatureFactory.getInstance(ssa);
90
80
Lines 92-100 Link Here
92
  }
82
  }
93
83
94
  /**
84
  /**
95
   * Returns a {@link Set} of signature-with-appendix scheme names supported
85
   * Returns a {@link Set} of signature-with-appendix scheme names supported by
96
   * by this <i>Factory</i>.
86
   * this <i>Factory</i>.
97
   *
87
   * 
98
   * @return a {@link Set} of signature-with-appendix scheme names (Strings).
88
   * @return a {@link Set} of signature-with-appendix scheme names (Strings).
99
   */
89
   */
100
  public static synchronized final Set getNames()
90
  public static synchronized final Set getNames()
Lines 104-113 Link Here
104
        HashSet hs = new HashSet();
94
        HashSet hs = new HashSet();
105
        hs.add(Registry.DSS_SIG);
95
        hs.add(Registry.DSS_SIG);
106
        hs.addAll(RSASignatureFactory.getNames());
96
        hs.addAll(RSASignatureFactory.getNames());
107
108
        names = Collections.unmodifiableSet(hs);
97
        names = Collections.unmodifiableSet(hs);
109
      }
98
      }
110
111
    return names;
99
    return names;
112
  }
100
  }
113
}
101
}
(-)sig/dss/DSSSignature.java (-137 / +67 lines)
Lines 55-126 Link Here
55
import java.util.Random;
55
import java.util.Random;
56
56
57
/**
57
/**
58
 * <p>The DSS (Digital Signature Standard) algorithm makes use of the following
58
 * The DSS (Digital Signature Standard) algorithm makes use of the following
59
 * parameters:</p>
59
 * parameters:
60
 *
61
 * <ol>
60
 * <ol>
62
 *    <li>p: A prime modulus, where <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup>
61
 * <li>p: A prime modulus, where
63
 *    </code> for <code>512 &lt;= L &lt;= 1024</code> and <code>L</code> a
62
 * <code>2<sup>L-1</sup> &lt; p &lt; 2<sup>L</sup> </code> for <code>512 &lt;= L
64
 *    multiple of <code>64</code>.</li>
63
 * &lt;= 1024</code> and <code>L</code> a multiple of <code>64</code>.</li>
65
 *    <li>q: A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup>
64
 * <li>q: A prime divisor of <code>p - 1</code>, where <code>2<sup>159</sup>
66
 *    &lt; q &lt; 2<sup>160</sup></code>.</li>
65
 *    &lt; q &lt; 2<sup>160</sup></code>.</li>
67
 *    <li>g: Where <code>g = h<sup>(p-1)</sup>/q mod p</code>, where
66
 * <li>g: Where <code>g = h<sup>(p-1)</sup>/q mod p</code>, where
68
 *    <code>h</code> is any integer with <code>1 &lt; h &lt; p - 1</code> such
67
 * <code>h</code> is any integer with <code>1 &lt; h &lt; p - 1</code> such
69
 *    that <code>h<sup> (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order
68
 * that <code>h<sup> (p-1)</sup>/q mod p > 1</code> (<code>g</code> has order
70
 *    <code>q mod p</code>).</li>
69
 * <code>q mod p</code>).</li>
71
 *    <li>x: A randomly or pseudorandomly generated integer with <code>0 &lt; x
70
 * <li>x: A randomly or pseudorandomly generated integer with <code>0 &lt; x
72
 *    &lt; q</code>.</li>
71
 *    &lt; q</code>.</li>
73
 *    <li>y: <code>y = g<sup>x</sup> mod p</code>.</li>
72
 * <li>y: <code>y = g<sup>x</sup> mod p</code>.</li>
74
 *    <li>k: A randomly or pseudorandomly generated integer with <code>0 &lt; k
73
 * <li>k: A randomly or pseudorandomly generated integer with <code>0 &lt; k
75
 *    &lt; q</code>.</li>
74
 *    &lt; q</code>.</li>
76
 * </ol>
75
 * </ol>
77
 *
76
 * <p>
78
 * <p>The integers <code>p</code>, <code>q</code>, and <code>g</code> can be
77
 * The integers <code>p</code>, <code>q</code>, and <code>g</code> can be
79
 * public and can be common to a group of users. A user's private and public
78
 * public and can be common to a group of users. A user's private and public
80
 * keys are <code>x</code> and <code>y</code>, respectively. They are normally
79
 * keys are <code>x</code> and <code>y</code>, respectively. They are
81
 * fixed for a period of time. Parameters <code>x</code> and <code>k</code> are
80
 * normally fixed for a period of time. Parameters <code>x</code> and
82
 * used for signature generation only, and must be kept secret. Parameter
81
 * <code>k</code> are used for signature generation only, and must be kept
83
 * <code>k</code> must be regenerated for each signature.</p>
82
 * secret. Parameter <code>k</code> must be regenerated for each signature.
84
 *
83
 * <p>
85
 * <p>The signature of a message <code>M</code> is the pair of numbers <code>r</code>
84
 * The signature of a message <code>M</code> is the pair of numbers
86
 * and <code>s</code> computed according to the equations below:</p>
85
 * <code>r</code> and <code>s</code> computed according to the equations below:
87
 *
88
 * <ul>
86
 * <ul>
89
 *    <li><code>r = (g<sup>k</sup> mod p) mod q</code> and</li>
87
 * <li><code>r = (g<sup>k</sup> mod p) mod q</code> and</li>
90
 *    <li><code>s = (k<sup>-1</sup>(SHA(M) + xr)) mod q</code>.</li>
88
 * <li><code>s = (k<sup>-1</sup>(SHA(M) + xr)) mod q</code>.</li>
91
 * </ul>
89
 * </ul>
92
 *
90
 * <p>
93
 * <p>In the above, <code>k<sup>-1</sup></code> is the multiplicative inverse of
91
 * In the above, <code>k<sup>-1</sup></code> is the multiplicative inverse of
94
 * <code>k</code>, <code>mod q</code>; i.e., <code>(k<sup>-1</sup> k) mod q = 1
92
 * <code>k</code>, <code>mod q</code>; i.e., <code>(k<sup>-1</sup> k) mod q =
95
 * </code> and <code>0 &lt; k-1 &lt; q</code>. The value of <code>SHA(M)</code>
93
 * 1</code> and <code>0 &lt; k-1 &lt; q</code>. The value of <code>SHA(M)</code>
96
 * is a 160-bit string output by the Secure Hash Algorithm specified in FIPS 180.
94
 * is a 160-bit string output by the Secure Hash Algorithm specified in FIPS
97
 * For use in computing <code>s</code>, this string must be converted to an
95
 * 180. For use in computing <code>s</code>, this string must be converted to
98
 * integer.</p>
96
 * an integer.
99
 *
97
 * <p>
100
 * <p>As an option, one may wish to check if <code>r == 0</code> or <code>s == 0
98
 * As an option, one may wish to check if <code>r == 0</code> or <code>s == 0
101
 * </code>. If either <code>r == 0</code> or <code>s == 0</code>, a new value
99
 * </code>.
102
 * of <code>k</code> should be generated and the signature should be
100
 * If either <code>r == 0</code> or <code>s == 0</code>, a new value of
103
 * recalculated (it is extremely unlikely that <code>r == 0</code> or <code>s ==
101
 * <code>k</code> should be generated and the signature should be recalculated
104
 * 0</code> if signatures are generated properly).</p>
102
 * (it is extremely unlikely that <code>r == 0</code> or <code>s == 0</code> if
105
 *
103
 * signatures are generated properly).
106
 * <p>The signature is transmitted along with the message to the verifier.</p>
104
 * <p>
107
 *
105
 * The signature is transmitted along with the message to the verifier.
108
 * <p>References:</p>
106
 * <p>
107
 * References:
109
 * <ol>
108
 * <ol>
110
 *    <li><a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital
109
 * <li><a href="http://www.itl.nist.gov/fipspubs/fip186.htm">Digital Signature
111
 *    Signature Standard (DSS)</a>, Federal Information Processing Standards
110
 * Standard (DSS)</a>, Federal Information Processing Standards Publication
112
 *    Publication 186. National Institute of Standards and Technology.</li>
111
 * 186. National Institute of Standards and Technology.</li>
113
 * </ol>
112
 * </ol>
114
 */
113
 */
115
public class DSSSignature extends BaseSignature
114
public class DSSSignature
115
    extends BaseSignature
116
{
116
{
117
118
  // Constants and variables
119
  // -------------------------------------------------------------------------
120
121
  // Constructor(s)
122
  // -------------------------------------------------------------------------
123
124
  /** Trivial 0-arguments constructor. */
117
  /** Trivial 0-arguments constructor. */
125
  public DSSSignature()
118
  public DSSSignature()
126
  {
119
  {
Lines 137-152 Link Here
137
    this.md = (IMessageDigest) that.md.clone();
130
    this.md = (IMessageDigest) that.md.clone();
138
  }
131
  }
139
132
140
  // Class methods
141
  // -------------------------------------------------------------------------
142
143
  public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h)
133
  public static final BigInteger[] sign(final DSAPrivateKey k, final byte[] h)
144
  {
134
  {
145
    final DSSSignature sig = new DSSSignature();
135
    final DSSSignature sig = new DSSSignature();
146
    final Map attributes = new HashMap();
136
    final Map attributes = new HashMap();
147
    attributes.put(ISignature.SIGNER_KEY, k);
137
    attributes.put(ISignature.SIGNER_KEY, k);
148
    sig.setupSign(attributes);
138
    sig.setupSign(attributes);
149
150
    return sig.computeRS(h);
139
    return sig.computeRS(h);
151
  }
140
  }
152
141
Lines 157-167 Link Here
157
    final Map attributes = new HashMap();
146
    final Map attributes = new HashMap();
158
    attributes.put(ISignature.SIGNER_KEY, k);
147
    attributes.put(ISignature.SIGNER_KEY, k);
159
    if (rnd != null)
148
    if (rnd != null)
160
      {
149
      attributes.put(ISignature.SOURCE_OF_RANDOMNESS, rnd);
161
        attributes.put(ISignature.SOURCE_OF_RANDOMNESS, rnd);
162
      }
163
    sig.setupSign(attributes);
164
150
151
    sig.setupSign(attributes);
165
    return sig.computeRS(h);
152
    return sig.computeRS(h);
166
  }
153
  }
167
154
Lines 172-182 Link Here
172
    final Map attributes = new HashMap();
159
    final Map attributes = new HashMap();
173
    attributes.put(ISignature.SIGNER_KEY, k);
160
    attributes.put(ISignature.SIGNER_KEY, k);
174
    if (irnd != null)
161
    if (irnd != null)
175
      {
162
      attributes.put(ISignature.SOURCE_OF_RANDOMNESS, irnd);
176
        attributes.put(ISignature.SOURCE_OF_RANDOMNESS, irnd);
177
      }
178
    sig.setupSign(attributes);
179
163
164
    sig.setupSign(attributes);
180
    return sig.computeRS(h);
165
    return sig.computeRS(h);
181
  }
166
  }
182
167
Lines 187-199 Link Here
187
    final Map attributes = new HashMap();
172
    final Map attributes = new HashMap();
188
    attributes.put(ISignature.VERIFIER_KEY, k);
173
    attributes.put(ISignature.VERIFIER_KEY, k);
189
    sig.setupVerify(attributes);
174
    sig.setupVerify(attributes);
190
191
    return sig.checkRS(rs, h);
175
    return sig.checkRS(rs, h);
192
  }
176
  }
193
177
194
  // Implementation of abstract methods in superclass
195
  // -------------------------------------------------------------------------
196
197
  public Object clone()
178
  public Object clone()
198
  {
179
  {
199
    return new DSSSignature(this);
180
    return new DSSSignature(this);
Lines 202-282 Link Here
202
  protected void setupForVerification(PublicKey k)
183
  protected void setupForVerification(PublicKey k)
203
      throws IllegalArgumentException
184
      throws IllegalArgumentException
204
  {
185
  {
205
    if (!(k instanceof DSAPublicKey))
186
    if (! (k instanceof DSAPublicKey))
206
      {
187
      throw new IllegalArgumentException();
207
        throw new IllegalArgumentException();
188
208
      }
209
    this.publicKey = k;
189
    this.publicKey = k;
210
  }
190
  }
211
191
212
  protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
192
  protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
213
  {
193
  {
214
    if (!(k instanceof DSAPrivateKey))
194
    if (! (k instanceof DSAPrivateKey))
215
      {
195
      throw new IllegalArgumentException();
216
        throw new IllegalArgumentException();
196
217
      }
218
    this.privateKey = k;
197
    this.privateKey = k;
219
  }
198
  }
220
199
221
  protected Object generateSignature() throws IllegalStateException
200
  protected Object generateSignature() throws IllegalStateException
222
  {
201
  {
223
    //      BigInteger p = ((DSAPrivateKey) privateKey).getParams().getP();
224
    //      BigInteger q = ((DSAPrivateKey) privateKey).getParams().getQ();
225
    //      BigInteger g = ((DSAPrivateKey) privateKey).getParams().getG();
226
    //      BigInteger x = ((DSAPrivateKey) privateKey).getX();
227
    //      BigInteger m = new BigInteger(1, md.digest());
228
    //      BigInteger k, r, s;
229
    //
230
    //      byte[] kb = new byte[20]; // we'll use 159 bits only
231
    //      while (true) {
232
    //         this.nextRandomBytes(kb);
233
    //         k = new BigInteger(1, kb);
234
    //         k.clearBit(159);
235
    //         r = g.modPow(k, p).mod(q);
236
    //         if (r.equals(BigInteger.ZERO)) {
237
    //            continue;
238
    //         }
239
    //         s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
240
    //         if (s.equals(BigInteger.ZERO)) {
241
    //            continue;
242
    //         }
243
    //         break;
244
    //      }
245
    final BigInteger[] rs = computeRS(md.digest());
202
    final BigInteger[] rs = computeRS(md.digest());
246
247
    //      return encodeSignature(r, s);
248
    return encodeSignature(rs[0], rs[1]);
203
    return encodeSignature(rs[0], rs[1]);
249
  }
204
  }
250
205
251
  protected boolean verifySignature(Object sig) throws IllegalStateException
206
  protected boolean verifySignature(Object sig) throws IllegalStateException
252
  {
207
  {
253
    final BigInteger[] rs = decodeSignature(sig);
208
    final BigInteger[] rs = decodeSignature(sig);
254
    //      BigInteger r = rs[0];
255
    //      BigInteger s = rs[1];
256
    //
257
    //      BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
258
    //      BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
259
    //      BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
260
    //      BigInteger y = ((DSAPublicKey) publicKey).getY();
261
    //      BigInteger w = s.modInverse(q);
262
    //
263
    //      byte bytes[] = md.digest();
264
    //      BigInteger u1 = w.multiply(new BigInteger(1, bytes)).mod(q);
265
    //      BigInteger u2 = r.multiply(w).mod(q);
266
    //
267
    //      BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
268
    //      return v.equals(r);
269
    return checkRS(rs, md.digest());
209
    return checkRS(rs, md.digest());
270
  }
210
  }
271
211
272
  // Other instance methods
273
  // -------------------------------------------------------------------------
274
275
  /**
212
  /**
276
   * Returns the output of a signature generation phase.<p>
213
   * Returns the output of a signature generation phase.
277
   *
214
   * 
278
   * @return an object encapsulating the DSS signature pair <code>r</code> and
215
   * @return an object encapsulating the DSS signature pair <code>r</code> and
279
   * <code>s</code>.
216
   *         <code>s</code>.
280
   */
217
   */
281
  private Object encodeSignature(BigInteger r, BigInteger s)
218
  private Object encodeSignature(BigInteger r, BigInteger s)
282
  {
219
  {
Lines 284-292 Link Here
284
  }
221
  }
285
222
286
  /**
223
  /**
287
   * Returns the output of a previously generated signature object as a pair
224
   * Returns the output of a previously generated signature object as a pair of
288
   * of {@link java.math.BigInteger}.<p>
225
   * {@link java.math.BigInteger}.
289
   *
226
   * 
290
   * @return the DSS signature pair <code>r</code> and <code>s</code>.
227
   * @return the DSS signature pair <code>r</code> and <code>s</code>.
291
   */
228
   */
292
  private BigInteger[] decodeSignature(Object signature)
229
  private BigInteger[] decodeSignature(Object signature)
Lines 302-308 Link Here
302
    final BigInteger x = ((DSAPrivateKey) privateKey).getX();
239
    final BigInteger x = ((DSAPrivateKey) privateKey).getX();
303
    final BigInteger m = new BigInteger(1, digestBytes);
240
    final BigInteger m = new BigInteger(1, digestBytes);
304
    BigInteger k, r, s;
241
    BigInteger k, r, s;
305
306
    final byte[] kb = new byte[20]; // we'll use 159 bits only
242
    final byte[] kb = new byte[20]; // we'll use 159 bits only
307
    while (true)
243
    while (true)
308
      {
244
      {
Lines 311-327 Link Here
311
        k.clearBit(159);
247
        k.clearBit(159);
312
        r = g.modPow(k, p).mod(q);
248
        r = g.modPow(k, p).mod(q);
313
        if (r.equals(BigInteger.ZERO))
249
        if (r.equals(BigInteger.ZERO))
314
          {
250
          continue;
315
            continue;
251
316
          }
317
        s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
252
        s = m.add(x.multiply(r)).multiply(k.modInverse(q)).mod(q);
318
        if (s.equals(BigInteger.ZERO))
253
        if (s.equals(BigInteger.ZERO))
319
          {
254
          continue;
320
            continue;
255
321
          }
322
        break;
256
        break;
323
      }
257
      }
324
325
    return new BigInteger[] { r, s };
258
    return new BigInteger[] { r, s };
326
  }
259
  }
327
260
Lines 329-344 Link Here
329
  {
262
  {
330
    final BigInteger r = rs[0];
263
    final BigInteger r = rs[0];
331
    final BigInteger s = rs[1];
264
    final BigInteger s = rs[1];
332
333
    final BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
265
    final BigInteger g = ((DSAPublicKey) publicKey).getParams().getG();
334
    final BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
266
    final BigInteger p = ((DSAPublicKey) publicKey).getParams().getP();
335
    final BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
267
    final BigInteger q = ((DSAPublicKey) publicKey).getParams().getQ();
336
    final BigInteger y = ((DSAPublicKey) publicKey).getY();
268
    final BigInteger y = ((DSAPublicKey) publicKey).getY();
337
    final BigInteger w = s.modInverse(q);
269
    final BigInteger w = s.modInverse(q);
338
339
    final BigInteger u1 = w.multiply(new BigInteger(1, digestBytes)).mod(q);
270
    final BigInteger u1 = w.multiply(new BigInteger(1, digestBytes)).mod(q);
340
    final BigInteger u2 = r.multiply(w).mod(q);
271
    final BigInteger u2 = r.multiply(w).mod(q);
341
342
    final BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
272
    final BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
343
    return v.equals(r);
273
    return v.equals(r);
344
  }
274
  }
(-)sig/dss/DSSSignatureRawCodec.java (-65 / +40 lines)
Lines 45-105 Link Here
45
import java.math.BigInteger;
45
import java.math.BigInteger;
46
46
47
/**
47
/**
48
 * <p>An object that implements the {@link ISignatureCodec} operations for the
48
 * An object that implements the {@link ISignatureCodec} operations for the
49
 * <i>Raw</i> format to use with DSS signatures.</p>
49
 * <i>Raw</i> format to use with DSS signatures.
50
 */
50
 */
51
public class DSSSignatureRawCodec implements ISignatureCodec
51
public class DSSSignatureRawCodec
52
    implements ISignatureCodec
52
{
53
{
53
54
  // Constants and variables
55
  // -------------------------------------------------------------------------
56
57
  // Constructor(s)
58
  // -------------------------------------------------------------------------
59
60
  // implicit 0-arguments constructor
61
62
  // Class methods
63
  // -------------------------------------------------------------------------
64
65
  // Instance methods
66
  // -------------------------------------------------------------------------
67
68
  // gnu.crypto.sig.ISignatureCodec interface implementation -----------------
69
70
  public int getFormatID()
54
  public int getFormatID()
71
  {
55
  {
72
    return RAW_FORMAT;
56
    return RAW_FORMAT;
73
  }
57
  }
74
58
75
  /**
59
  /**
76
   * <p>Returns the encoded form of the designated DSS (Digital Signature
60
   * Returns the encoded form of the designated DSS (Digital Signature Standard)
77
   * Standard) signature object according to the <i>Raw</i> format supported by
61
   * signature object according to the <i>Raw</i> format supported by this
78
   * this library.</p>
62
   * library.
79
   *
63
   * <p>
80
   * <p>The <i>Raw</i> format for a DSA signature, in this implementation, is a
64
   * The <i>Raw</i> format for a DSA signature, in this implementation, is a
81
   * byte sequence consisting of the following:</p>
65
   * byte sequence consisting of the following:
82
   *
83
   * <ol>
66
   * <ol>
84
   *		<li>4-byte magic consisting of the value of the literal
67
   * <li>4-byte magic consisting of the value of the literal
85
   *    {@link Registry#MAGIC_RAW_DSS_SIGNATURE},</li>
68
   * {@link Registry#MAGIC_RAW_DSS_SIGNATURE},</li>
86
   *		<li>1-byte version consisting of the constant: 0x01,</li>
69
   * <li>1-byte version consisting of the constant: 0x01,</li>
87
   *		<li>4-byte count of following bytes representing the DSS parameter
70
   * <li>4-byte count of following bytes representing the DSS parameter
88
   *		<code>r</code> in internet order,</li>
71
   * <code>r</code> in internet order,</li>
89
   *		<li>n-bytes representation of a {@link BigInteger} obtained by invoking
72
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
90
   *    the <code>toByteArray()</code> method on the DSS parameter <code>r</code>,</li>
73
   * the <code>toByteArray()</code> method on the DSS parameter <code>r</code>,
91
   *		<li>4-byte count of following bytes representing the DSS parameter
74
   * </li>
92
   *		<code>s</code>,</li>
75
   * <li>4-byte count of following bytes representing the DSS parameter
93
   *		<li>n-bytes representation of a {@link BigInteger} obtained by invoking
76
   * <code>s</code>,</li>
94
   *    the <code>toByteArray()</code> method on the DSS parameter <code>s</code>.</li>
77
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
78
   * the <code>toByteArray()</code> method on the DSS parameter <code>s</code>.
79
   * </li>
95
   * </ol>
80
   * </ol>
96
   *
81
   * 
97
   * @param signature the signature to encode, consisting of the two DSS
82
   * @param signature the signature to encode, consisting of the two DSS
98
   * parameters <code>r</code> and <code>s</code> as a {@link java.math.BigInteger}
83
   *          parameters <code>r</code> and <code>s</code> as a
99
   * array.
84
   *          {@link BigInteger} array.
100
   * @return the <i>Raw</i> format encoding of the designated signature.
85
   * @return the <i>Raw</i> format encoding of the designated signature.
101
   * @exception IllegalArgumentException if the designated signature is not a
86
   * @exception IllegalArgumentException if the designated signature is not a
102
   * DSS (Digital Signature Standard) one.
87
   *              DSS (Digital Signature Standard) one.
103
   */
88
   */
104
  public byte[] encodeSignature(Object signature)
89
  public byte[] encodeSignature(Object signature)
105
  {
90
  {
Lines 112-149 Link Here
112
      }
97
      }
113
    catch (Exception x)
98
    catch (Exception x)
114
      {
99
      {
115
        throw new IllegalArgumentException("key");
100
        throw new IllegalArgumentException("signature");
116
      }
101
      }
117
118
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
102
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
119
120
    // magic
103
    // magic
121
    baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[0]);
104
    baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[0]);
122
    baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[1]);
105
    baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[1]);
123
    baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[2]);
106
    baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[2]);
124
    baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[3]);
107
    baos.write(Registry.MAGIC_RAW_DSS_SIGNATURE[3]);
125
126
    // version
108
    // version
127
    baos.write(0x01);
109
    baos.write(0x01);
128
129
    // r
110
    // r
130
    byte[] buffer = r.toByteArray();
111
    byte[] buffer = r.toByteArray();
131
    int length = buffer.length;
112
    int length = buffer.length;
132
    baos.write(length >>> 24);
113
    baos.write( length >>> 24);
133
    baos.write((length >>> 16) & 0xFF);
114
    baos.write((length >>> 16) & 0xFF);
134
    baos.write((length >>> 8) & 0xFF);
115
    baos.write((length >>> 8) & 0xFF);
135
    baos.write(length & 0xFF);
116
    baos.write(length & 0xFF);
136
    baos.write(buffer, 0, length);
117
    baos.write(buffer, 0, length);
137
138
    // s
118
    // s
139
    buffer = s.toByteArray();
119
    buffer = s.toByteArray();
140
    length = buffer.length;
120
    length = buffer.length;
141
    baos.write(length >>> 24);
121
    baos.write( length >>> 24);
142
    baos.write((length >>> 16) & 0xFF);
122
    baos.write((length >>> 16) & 0xFF);
143
    baos.write((length >>> 8) & 0xFF);
123
    baos.write((length >>> 8) & 0xFF);
144
    baos.write(length & 0xFF);
124
    baos.write(length & 0xFF);
145
    baos.write(buffer, 0, length);
125
    baos.write(buffer, 0, length);
146
147
    return baos.toByteArray();
126
    return baos.toByteArray();
148
  }
127
  }
149
128
Lines 154-189 Link Here
154
        || k[1] != Registry.MAGIC_RAW_DSS_SIGNATURE[1]
133
        || k[1] != Registry.MAGIC_RAW_DSS_SIGNATURE[1]
155
        || k[2] != Registry.MAGIC_RAW_DSS_SIGNATURE[2]
134
        || k[2] != Registry.MAGIC_RAW_DSS_SIGNATURE[2]
156
        || k[3] != Registry.MAGIC_RAW_DSS_SIGNATURE[3])
135
        || k[3] != Registry.MAGIC_RAW_DSS_SIGNATURE[3])
157
      {
136
      throw new IllegalArgumentException("magic");
158
        throw new IllegalArgumentException("magic");
159
      }
160
161
    // version
137
    // version
162
    if (k[4] != 0x01)
138
    if (k[4] != 0x01)
163
      {
139
      throw new IllegalArgumentException("version");
164
        throw new IllegalArgumentException("version");
165
      }
166
140
167
    int i = 5;
141
    int i = 5;
168
    int l;
142
    int l;
169
    byte[] buffer;
143
    byte[] buffer;
170
171
    // r
144
    // r
172
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
145
    l =  k[i++]         << 24
173
        | (k[i++] & 0xFF);
146
      | (k[i++] & 0xFF) << 16
147
      | (k[i++] & 0xFF) << 8
148
      | (k[i++] & 0xFF);
174
    buffer = new byte[l];
149
    buffer = new byte[l];
175
    System.arraycopy(k, i, buffer, 0, l);
150
    System.arraycopy(k, i, buffer, 0, l);
176
    i += l;
151
    i += l;
177
    BigInteger r = new BigInteger(1, buffer);
152
    BigInteger r = new BigInteger(1, buffer);
178
179
    // s
153
    // s
180
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
154
    l =  k[i++]         << 24
181
        | (k[i++] & 0xFF);
155
      | (k[i++] & 0xFF) << 16
156
      | (k[i++] & 0xFF) << 8
157
      | (k[i++] & 0xFF);
182
    buffer = new byte[l];
158
    buffer = new byte[l];
183
    System.arraycopy(k, i, buffer, 0, l);
159
    System.arraycopy(k, i, buffer, 0, l);
184
    i += l;
160
    i += l;
185
    BigInteger s = new BigInteger(1, buffer);
161
    BigInteger s = new BigInteger(1, buffer);
186
187
    return new BigInteger[] { r, s };
162
    return new BigInteger[] { r, s };
188
  }
163
  }
189
}
164
}
(-)sig/rsa/EME_PKCS1_V1_5.java (-87 / +55 lines)
Lines 47-71 Link Here
47
import java.util.Random;
47
import java.util.Random;
48
48
49
/**
49
/**
50
 * <p>An implementation of the EME-PKCS1-V1.5 encoding and decoding methods.</p>
50
 * An implementation of the EME-PKCS1-V1.5 encoding and decoding methods.
51
 *
51
 * <p>
52
 * <p>EME-PKCS1-V1.5 is parameterised by the entity <code>k</code> which is the
52
 * EME-PKCS1-V1.5 is parameterised by the entity <code>k</code> which is the
53
 * byte count of an RSA public shared modulus.</p>
53
 * byte count of an RSA public shared modulus.
54
 *
54
 * <p>
55
 * <p>References:</p>
55
 * References:
56
 * <ol>
56
 * <ol>
57
 *    <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
57
 * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
58
 *    Standards (PKCS) #1:</a><br>
58
 * Standards (PKCS) #1:</a><br>
59
 *    RSA Cryptography Specifications Version 2.1.<br>
59
 * RSA Cryptography Specifications Version 2.1.<br>
60
 *    Jakob Jonsson and Burt Kaliski.</li>
60
 * Jakob Jonsson and Burt Kaliski.</li>
61
 * </ol>
61
 * </ol>
62
 */
62
 */
63
public class EME_PKCS1_V1_5
63
public class EME_PKCS1_V1_5
64
{
64
{
65
66
  // Constants and variables
67
  // -------------------------------------------------------------------------
68
69
  private int k;
65
  private int k;
70
66
71
  private ByteArrayOutputStream baos = new ByteArrayOutputStream();
67
  private ByteArrayOutputStream baos = new ByteArrayOutputStream();
Lines 73-81 Link Here
73
  /** Our default source of randomness. */
69
  /** Our default source of randomness. */
74
  private PRNG prng = PRNG.getInstance();
70
  private PRNG prng = PRNG.getInstance();
75
71
76
  // Constructor(s)
77
  // -------------------------------------------------------------------------
78
79
  private EME_PKCS1_V1_5(final int k)
72
  private EME_PKCS1_V1_5(final int k)
80
  {
73
  {
81
    super();
74
    super();
Lines 83-97 Link Here
83
    this.k = k;
76
    this.k = k;
84
  }
77
  }
85
78
86
  // Class methods
87
  // -------------------------------------------------------------------------
88
89
  public static final EME_PKCS1_V1_5 getInstance(final int k)
79
  public static final EME_PKCS1_V1_5 getInstance(final int k)
90
  {
80
  {
91
    if (k < 0)
81
    if (k < 0)
92
      {
82
      throw new IllegalArgumentException("k must be a positive integer");
93
        throw new IllegalArgumentException("k must be a positive integer");
83
94
      }
95
    return new EME_PKCS1_V1_5(k);
84
    return new EME_PKCS1_V1_5(k);
96
  }
85
  }
97
86
Lines 102-135 Link Here
102
    return EME_PKCS1_V1_5.getInstance(k);
91
    return EME_PKCS1_V1_5.getInstance(k);
103
  }
92
  }
104
93
105
  // Instance methods
106
  // -------------------------------------------------------------------------
107
108
  /**
94
  /**
109
   * <p>Generates an octet string <code>PS</code> of length <code>k - mLen -
95
   * Generates an octet string <code>PS</code> of length <code>k - mLen -
110
   * 3</code> consisting of pseudo-randomly generated nonzero octets. The
96
   * 3</code> consisting of pseudo-randomly generated nonzero octets. The length
111
   * length of <code>PS</code> will be at least eight octets.</p>
97
   * of <code>PS</code> will be at least eight octets.
112
   *
98
   * <p>
113
   * <p>The method then concatenates <code>PS</code>, the message <code>M</code>,
99
   * The method then concatenates <code>PS</code>, the message <code>M</code>,
114
   * and other padding to form an encoded message <code>EM</code> of length
100
   * and other padding to form an encoded message <code>EM</code> of length
115
   * <code>k</code> octets as:</p>
101
   * <code>k</code> octets as:
116
   *
117
   * <pre>
102
   * <pre>
118
   *    EM = 0x00 || 0x02 || PS || 0x00 || M.
103
   *     EM = 0x00 || 0x02 || PS || 0x00 || M.
119
   * </pre>
104
   * </pre>
120
   *
105
   * <p>
121
   * <p>This method uses a default PRNG to obtain the padding bytes.</p>
106
   * This method uses a default PRNG to obtain the padding bytes.
122
   *
107
   * 
123
   * @param M the message to encode.
108
   * @param M the message to encode.
124
   * @return the encoded message <code>EM</code>.
109
   * @return the encoded message <code>EM</code>.
125
   */
110
   */
126
  public byte[] encode(final byte[] M)
111
  public byte[] encode(final byte[] M)
127
  {
112
  {
128
    // a. Generate an octet string PS of length k - mLen - 3 consisting
113
    // a. Generate an octet string PS of length k - mLen - 3 consisting
129
    //    of pseudo-randomly generated nonzero octets.  The length of PS
114
    // of pseudo-randomly generated nonzero octets. The length of PS
130
    //    will be at least eight octets.
115
    // will be at least eight octets.
131
    final byte[] PS = new byte[k - M.length - 3];
116
    final byte[] PS = new byte[k - M.length - 3];
132
133
    // FIXME. This should be configurable, somehow.
117
    // FIXME. This should be configurable, somehow.
134
    prng.nextBytes(PS);
118
    prng.nextBytes(PS);
135
    int i = 0;
119
    int i = 0;
Lines 139-155 Link Here
139
          PS[i] = 1;
123
          PS[i] = 1;
140
      }
124
      }
141
    // b. Concatenate PS, the message M, and other padding to form an
125
    // b. Concatenate PS, the message M, and other padding to form an
142
    //    encoded message EM of length k octets as
126
    // encoded message EM of length k octets as
143
    //
127
    //
144
    //    EM = 0x00 || 0x02 || PS || 0x00 || M.
128
    // EM = 0x00 || 0x02 || PS || 0x00 || M.
145
    return assembleEM(PS, M);
129
    return assembleEM(PS, M);
146
  }
130
  }
147
131
148
  /**
132
  /**
149
   * <p>Similar to {@link #encode(byte[])} method, except that the source of
133
   * Similar to {@link #encode(byte[])} method, except that the source of
150
   * randomness to use for obtaining the padding bytes (an instance of
134
   * randomness to use for obtaining the padding bytes (an instance of
151
   * {@link IRandom}) is given as a parameter.</p>
135
   * {@link IRandom}) is given as a parameter.
152
   *
136
   * 
153
   * @param M the message to encode.
137
   * @param M the message to encode.
154
   * @param irnd the {@link IRandom} instance to use as a source of randomness.
138
   * @param irnd the {@link IRandom} instance to use as a source of randomness.
155
   * @return the encoded message <code>EM</code>.
139
   * @return the encoded message <code>EM</code>.
Lines 183-196 Link Here
183
      {
167
      {
184
        throw new RuntimeException("encode(): " + String.valueOf(x));
168
        throw new RuntimeException("encode(): " + String.valueOf(x));
185
      }
169
      }
186
187
    return assembleEM(PS, M);
170
    return assembleEM(PS, M);
188
  }
171
  }
189
172
190
  /**
173
  /**
191
   * <p>Similar to the {@link #encode(byte[], IRandom)} method, except that
174
   * Similar to the {@link #encode(byte[], IRandom)} method, except that the
192
   * the source of randmoness is an instance of {@link Random}.
175
   * source of randmoness is an instance of {@link Random}.
193
   *
176
   * 
194
   * @param M the message to encode.
177
   * @param M the message to encode.
195
   * @param rnd the {@link Random} instance to use as a source of randomness.
178
   * @param rnd the {@link Random} instance to use as a source of randomness.
196
   * @return the encoded message <code>EM</code>.
179
   * @return the encoded message <code>EM</code>.
Lines 213-245 Link Here
213
          }
196
          }
214
        break;
197
        break;
215
      }
198
      }
216
217
    return assembleEM(PS, M);
199
    return assembleEM(PS, M);
218
  }
200
  }
219
201
220
  /**
202
  /**
221
   * <p>Separate the encoded message <code>EM</code> into an octet string
203
   * Separate the encoded message <code>EM</code> into an octet string
222
   * <code>PS</code> consisting of nonzero octets and a message <code>M</code>
204
   * <code>PS</code> consisting of nonzero octets and a message <code>M</code>
223
   * as:</p>
205
   * as:
224
   *
225
   * <pre>
206
   * <pre>
226
   *    EM = 0x00 || 0x02 || PS || 0x00 || M.
207
   *     EM = 0x00 || 0x02 || PS || 0x00 || M.
227
   * </pre>
208
   * </pre>
228
   *
209
   * <p>
229
   * <p>If the first octet of <code>EM</code> does not have hexadecimal value
210
   * If the first octet of <code>EM</code> does not have hexadecimal value
230
   * <code>0x00</code>, if the second octet of <code>EM</code> does not have
211
   * <code>0x00</code>, if the second octet of <code>EM</code> does not
231
   * hexadecimal value <code>0x02</code>, if there is no octet with hexadecimal
212
   * have hexadecimal value <code>0x02</code>, if there is no octet with
232
   * value <code>0x00</code> to separate <code>PS</code> from <code>M</code>,
213
   * hexadecimal value <code>0x00</code> to separate <code>PS</code> from
233
   * or if the length of <code>PS</code> is less than <code>8</code> octets,
214
   * <code>M</code>, or if the length of <code>PS</code> is less than
234
   * output "decryption error" and stop.</p>
215
   * <code>8</code> octets, output "decryption error" and stop.
235
216
   * 
236
   * @param EM the designated encoded message.
217
   * @param EM the designated encoded message.
237
   * @return the decoded message <code>M</code> framed in the designated
218
   * @return the decoded message <code>M</code> framed in the designated
238
   * <code>EM</code> value.
219
   *         <code>EM</code> value.
239
   * @throws IllegalArgumentException if the length of the designated entity
220
   * @throws IllegalArgumentException if the length of the designated entity
240
   * <code>EM</code> is different than <code>k</code> (the length in bytes of
221
   *           <code>EM</code> is different than <code>k</code> (the length
241
   * the public shared modulus), or if any of the conditions described above
222
   *           in bytes of the public shared modulus), or if any of the
242
   * is detected.
223
   *           conditions described above is detected.
243
   */
224
   */
244
  public byte[] decode(final byte[] EM)
225
  public byte[] decode(final byte[] EM)
245
  {
226
  {
Lines 252-297 Link Here
252
    // the second octet of EM does not have hexadecimal value 0x02, if
233
    // the second octet of EM does not have hexadecimal value 0x02, if
253
    // there is no octet with hexadecimal value 0x00 to separate PS from
234
    // there is no octet with hexadecimal value 0x00 to separate PS from
254
    // M, or if the length of PS is less than 8 octets, output
235
    // M, or if the length of PS is less than 8 octets, output
255
    // "decryption error" and stop.  (See the note below.)
236
    // "decryption error" and stop. (See the note below.)
256
    final int emLen = EM.length;
237
    final int emLen = EM.length;
257
    if (emLen != k)
238
    if (emLen != k)
258
      {
239
      throw new IllegalArgumentException("decryption error");
259
        throw new IllegalArgumentException("decryption error");
260
      }
261
    if (EM[0] != 0x00)
240
    if (EM[0] != 0x00)
262
      {
241
      throw new IllegalArgumentException("decryption error");
263
        throw new IllegalArgumentException("decryption error");
264
      }
265
    if (EM[1] != 0x02)
242
    if (EM[1] != 0x02)
266
      {
243
      throw new IllegalArgumentException("decryption error");
267
        throw new IllegalArgumentException("decryption error");
268
      }
269
    int i = 2;
244
    int i = 2;
270
    for (; i < emLen; i++)
245
    for (; i < emLen; i++)
271
      {
246
      {
272
        if (EM[i] == 0x00)
247
        if (EM[i] == 0x00)
273
          {
248
          break;
274
            break;
275
          }
276
      }
249
      }
277
    if (i >= emLen || i < 11)
250
    if (i >= emLen || i < 11)
278
      {
251
      throw new IllegalArgumentException("decryption error");
279
        throw new IllegalArgumentException("decryption error");
280
      }
281
    i++;
252
    i++;
282
    final byte[] result = new byte[emLen - i];
253
    final byte[] result = new byte[emLen - i];
283
    System.arraycopy(EM, i, result, 0, result.length);
254
    System.arraycopy(EM, i, result, 0, result.length);
284
    return result;
255
    return result;
285
  }
256
  }
286
257
287
  // helper methods ----------------------------------------------------------
288
289
  private byte[] assembleEM(final byte[] PS, final byte[] M)
258
  private byte[] assembleEM(final byte[] PS, final byte[] M)
290
  {
259
  {
291
    // b. Concatenate PS, the message M, and other padding to form an
260
    // b. Concatenate PS, the message M, and other padding to form an
292
    //    encoded message EM of length k octets as
261
    // encoded message EM of length k octets as
293
    //
262
    //
294
    //    EM = 0x00 || 0x02 || PS || 0x00 || M.
263
    // EM = 0x00 || 0x02 || PS || 0x00 || M.
295
    baos.reset();
264
    baos.reset();
296
    baos.write(0x00);
265
    baos.write(0x00);
297
    baos.write(0x02);
266
    baos.write(0x02);
Lines 300-306 Link Here
300
    baos.write(M, 0, M.length);
269
    baos.write(M, 0, M.length);
301
    final byte[] result = baos.toByteArray();
270
    final byte[] result = baos.toByteArray();
302
    baos.reset();
271
    baos.reset();
303
304
    return result;
272
    return result;
305
  }
273
  }
306
}
274
}
(-)sig/rsa/EMSA_PKCS1_V1_5.java (-122 / +68 lines)
Lines 45-56 Link Here
45
import java.io.ByteArrayOutputStream;
45
import java.io.ByteArrayOutputStream;
46
46
47
/**
47
/**
48
 * <p>An implementation of the EMSA-PKCS1-V1.5 encoding scheme.</p>
48
 * An implementation of the EMSA-PKCS1-V1.5 encoding scheme.
49
 *
49
 * <p>
50
 * <p>EMSA-PKCS1-V1.5 is parameterised by the choice of hash function Hash and
50
 * EMSA-PKCS1-V1.5 is parameterised by the choice of hash function Hash and
51
 * hLen which denotes the length in octets of the hash function output.</p>
51
 * hLen which denotes the length in octets of the hash function output.
52
 *
52
 * <p>
53
 * <p>References:</p>
53
 * References:
54
 * <ol>
54
 * <ol>
55
 *    <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
55
 *    <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
56
 *    Standards (PKCS) #1:</a><br>
56
 *    Standards (PKCS) #1:</a><br>
Lines 58-69 Link Here
58
 *    Jakob Jonsson and Burt Kaliski.</li>
58
 *    Jakob Jonsson and Burt Kaliski.</li>
59
 * </ol>
59
 * </ol>
60
 */
60
 */
61
public class EMSA_PKCS1_V1_5 implements Cloneable
61
public class EMSA_PKCS1_V1_5
62
    implements Cloneable
62
{
63
{
63
64
  // Constants and variables
65
  // -------------------------------------------------------------------------
66
67
  /* Notes.
64
  /* Notes.
68
   1. For the six hash functions mentioned in Appendix B.1, the DER encoding
65
   1. For the six hash functions mentioned in Appendix B.1, the DER encoding
69
   T of the DigestInfo value is equal to the following:
66
   T of the DigestInfo value is equal to the following:
Lines 75-141 Link Here
75
   SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H
72
   SHA-384: (0x)30 41 30 0d 06 09 60 86 48 01 65 03 04 02 02 05 00 04 30 || H
76
   SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H
73
   SHA-512: (0x)30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40 || H
77
   */
74
   */
78
  private static final byte[] MD2_PREFIX = { (byte) 0x30, (byte) 0x20,
75
  private static final byte[] MD2_PREFIX = {
79
                                            (byte) 0x30, (byte) 0x0c,
76
      (byte) 0x30, (byte) 0x20, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
80
                                            (byte) 0x06, (byte) 0x08,
77
      (byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
81
                                            (byte) 0x2a, (byte) 0x86,
78
      (byte) 0xf7, (byte) 0x0d, (byte) 0x02, (byte) 0x02, (byte) 0x05,
82
                                            (byte) 0x48, (byte) 0x86,
79
      (byte) 0x00, (byte) 0x04, (byte) 0x10
83
                                            (byte) 0xf7, (byte) 0x0d,
80
  };
84
                                            (byte) 0x02, (byte) 0x02,
81
85
                                            (byte) 0x05, (byte) 0x00,
82
  private static final byte[] MD5_PREFIX = {
86
                                            (byte) 0x04, (byte) 0x10 };
83
      (byte) 0x30, (byte) 0x20, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
87
84
      (byte) 0x08, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
88
  private static final byte[] MD5_PREFIX = { (byte) 0x30, (byte) 0x20,
85
      (byte) 0xf7, (byte) 0x0d, (byte) 0x02, (byte) 0x05, (byte) 0x05,
89
                                            (byte) 0x30, (byte) 0x0c,
86
      (byte) 0x00, (byte) 0x04, (byte) 0x10
90
                                            (byte) 0x06, (byte) 0x08,
87
  };
91
                                            (byte) 0x2a, (byte) 0x86,
88
92
                                            (byte) 0x48, (byte) 0x86,
89
  private static final byte[] SHA160_PREFIX = {
93
                                            (byte) 0xf7, (byte) 0x0d,
90
      (byte) 0x30, (byte) 0x21, (byte) 0x30, (byte) 0x09, (byte) 0x06,
94
                                            (byte) 0x02, (byte) 0x05,
91
      (byte) 0x05, (byte) 0x2b, (byte) 0x0e, (byte) 0x03, (byte) 0x02,
95
                                            (byte) 0x05, (byte) 0x00,
92
      (byte) 0x1a, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x14
96
                                            (byte) 0x04, (byte) 0x10 };
93
  };
97
94
98
  private static final byte[] SHA160_PREFIX = { (byte) 0x30, (byte) 0x21,
95
  private static final byte[] SHA256_PREFIX = {
99
                                               (byte) 0x30, (byte) 0x09,
96
      (byte) 0x30, (byte) 0x31, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
100
                                               (byte) 0x06, (byte) 0x05,
97
      (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
101
                                               (byte) 0x2b, (byte) 0x0e,
98
      (byte) 0x65, (byte) 0x03, (byte) 0x04, (byte) 0x02, (byte) 0x01,
102
                                               (byte) 0x03, (byte) 0x02,
99
      (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x20
103
                                               (byte) 0x1a, (byte) 0x05,
100
  };
104
                                               (byte) 0x00, (byte) 0x04,
101
105
                                               (byte) 0x14 };
102
  private static final byte[] SHA384_PREFIX = {
106
103
      (byte) 0x30, (byte) 0x41, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
107
  private static final byte[] SHA256_PREFIX = { (byte) 0x30, (byte) 0x31,
104
      (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
108
                                               (byte) 0x30, (byte) 0x0d,
105
      (byte) 0x65, (byte) 0x03, (byte) 0x04, (byte) 0x02, (byte) 0x02,
109
                                               (byte) 0x06, (byte) 0x09,
106
      (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x30
110
                                               (byte) 0x60, (byte) 0x86,
107
  };
111
                                               (byte) 0x48, (byte) 0x01,
108
112
                                               (byte) 0x65, (byte) 0x03,
109
  private static final byte[] SHA512_PREFIX = {
113
                                               (byte) 0x04, (byte) 0x02,
110
      (byte) 0x30, (byte) 0x51, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
114
                                               (byte) 0x01, (byte) 0x05,
111
      (byte) 0x09, (byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01,
115
                                               (byte) 0x00, (byte) 0x04,
112
      (byte) 0x65, (byte) 0x03, (byte) 0x04, (byte) 0x02, (byte) 0x03,
116
                                               (byte) 0x20 };
113
      (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x40
117
114
  };
118
  private static final byte[] SHA384_PREFIX = { (byte) 0x30, (byte) 0x41,
119
                                               (byte) 0x30, (byte) 0x0d,
120
                                               (byte) 0x06, (byte) 0x09,
121
                                               (byte) 0x60, (byte) 0x86,
122
                                               (byte) 0x48, (byte) 0x01,
123
                                               (byte) 0x65, (byte) 0x03,
124
                                               (byte) 0x04, (byte) 0x02,
125
                                               (byte) 0x02, (byte) 0x05,
126
                                               (byte) 0x00, (byte) 0x04,
127
                                               (byte) 0x30 };
128
129
  private static final byte[] SHA512_PREFIX = { (byte) 0x30, (byte) 0x51,
130
                                               (byte) 0x30, (byte) 0x0d,
131
                                               (byte) 0x06, (byte) 0x09,
132
                                               (byte) 0x60, (byte) 0x86,
133
                                               (byte) 0x48, (byte) 0x01,
134
                                               (byte) 0x65, (byte) 0x03,
135
                                               (byte) 0x04, (byte) 0x02,
136
                                               (byte) 0x03, (byte) 0x05,
137
                                               (byte) 0x00, (byte) 0x04,
138
                                               (byte) 0x40 };
139
115
140
  /** The underlying hash function to use with this instance. */
116
  /** The underlying hash function to use with this instance. */
141
  private IMessageDigest hash;
117
  private IMessageDigest hash;
Lines 146-156 Link Here
146
  /** The DER part of DigestInfo not containing the hash value itself. */
122
  /** The DER part of DigestInfo not containing the hash value itself. */
147
  private byte[] prefix;
123
  private byte[] prefix;
148
124
149
  // Constructor(s)
150
  // -------------------------------------------------------------------------
151
152
  /**
125
  /**
153
   * <p>Trivial private constructor to enforce use through Factory method.</p>
126
   * Trivial private constructor to enforce use through Factory method.
154
   *
127
   *
155
   * @param hash the message digest instance to use with this scheme instance.
128
   * @param hash the message digest instance to use with this scheme instance.
156
   */
129
   */
Lines 162-202 Link Here
162
    hLen = hash.hashSize();
135
    hLen = hash.hashSize();
163
    final String name = hash.name();
136
    final String name = hash.name();
164
    if (name.equals(Registry.MD2_HASH))
137
    if (name.equals(Registry.MD2_HASH))
165
      {
138
      prefix = MD2_PREFIX;
166
        prefix = MD2_PREFIX;
167
      }
168
    else if (name.equals(Registry.MD5_HASH))
139
    else if (name.equals(Registry.MD5_HASH))
169
      {
140
      prefix = MD5_PREFIX;
170
        prefix = MD5_PREFIX;
171
      }
172
    else if (name.equals(Registry.SHA160_HASH))
141
    else if (name.equals(Registry.SHA160_HASH))
173
      {
142
      prefix = SHA160_PREFIX;
174
        prefix = SHA160_PREFIX;
175
      }
176
    else if (name.equals(Registry.SHA256_HASH))
143
    else if (name.equals(Registry.SHA256_HASH))
177
      {
144
      prefix = SHA256_PREFIX;
178
        prefix = SHA256_PREFIX;
179
      }
180
    else if (name.equals(Registry.SHA384_HASH))
145
    else if (name.equals(Registry.SHA384_HASH))
181
      {
146
      prefix = SHA384_PREFIX;
182
        prefix = SHA384_PREFIX;
183
      }
184
    else if (name.equals(Registry.SHA512_HASH))
147
    else if (name.equals(Registry.SHA512_HASH))
185
      {
148
      prefix = SHA512_PREFIX;
186
        prefix = SHA512_PREFIX;
187
      }
188
    else
149
    else
189
      {
150
      throw new UnsupportedOperationException(); // should not happen
190
        throw new UnsupportedOperationException(); // should not happen
191
      }
192
  }
151
  }
193
152
194
  // Class methods
195
  // -------------------------------------------------------------------------
196
197
  /**
153
  /**
198
   * <p>Returns an instance of this object given a designated name of a hash
154
   * Returns an instance of this object given a designated name of a hash
199
   * function.</p>
155
   * function.
200
   *
156
   *
201
   * @param mdName the canonical name of a hash function.
157
   * @param mdName the canonical name of a hash function.
202
   * @return an instance of this object configured for use with the designated
158
   * @return an instance of this object configured for use with the designated
Lines 208-239 Link Here
208
  {
164
  {
209
    final IMessageDigest hash = HashFactory.getInstance(mdName);
165
    final IMessageDigest hash = HashFactory.getInstance(mdName);
210
    final String name = hash.name();
166
    final String name = hash.name();
211
    if (!(name.equals(Registry.MD2_HASH) || name.equals(Registry.MD5_HASH)
167
    if (! (name.equals(Registry.MD2_HASH)
168
          || name.equals(Registry.MD5_HASH)
212
          || name.equals(Registry.SHA160_HASH)
169
          || name.equals(Registry.SHA160_HASH)
213
          || name.equals(Registry.SHA256_HASH)
170
          || name.equals(Registry.SHA256_HASH)
214
          || name.equals(Registry.SHA384_HASH) || name.equals(Registry.SHA512_HASH)))
171
          || name.equals(Registry.SHA384_HASH)
215
      {
172
          || name.equals(Registry.SHA512_HASH)))
216
        throw new UnsupportedOperationException("hash with no OID: " + name);
173
      throw new UnsupportedOperationException("hash with no OID: " + name);
217
      }
174
218
    return new EMSA_PKCS1_V1_5(hash);
175
    return new EMSA_PKCS1_V1_5(hash);
219
  }
176
  }
220
177
221
  // Instance methods
222
  // -------------------------------------------------------------------------
223
224
  // Cloneable interface implementation --------------------------------------
225
226
  public Object clone()
178
  public Object clone()
227
  {
179
  {
228
    return getInstance(hash.name());
180
    return getInstance(hash.name());
229
  }
181
  }
230
182
231
  // own methods -------------------------------------------------------------
232
233
  /**
183
  /**
234
   * <p>Frames the hash of a message, along with an ID of the hash function in
184
   * Frames the hash of a message, along with an ID of the hash function in
235
   * a DER sequence according to the specifications of EMSA-PKCS1-V1.5 as
185
   * a DER sequence according to the specifications of EMSA-PKCS1-V1.5 as
236
   * described in RFC-3447 (see class documentation).</p>
186
   * described in RFC-3447 (see class documentation).
237
   *
187
   *
238
   * @param mHash the byte sequence resulting from applying the message digest
188
   * @param mHash the byte sequence resulting from applying the message digest
239
   * algorithm Hash to the message <i>M</i>.
189
   * algorithm Hash to the message <i>M</i>.
Lines 270-286 Link Here
270
    // 3. If emLen < tLen + 11, output "intended encoded message length too
220
    // 3. If emLen < tLen + 11, output "intended encoded message length too
271
    //    short" and stop.
221
    //    short" and stop.
272
    if (emLen < tLen + 11)
222
    if (emLen < tLen + 11)
273
      {
223
      throw new IllegalArgumentException("emLen too short");
274
        throw new IllegalArgumentException("emLen too short");
275
      }
276
    // 4. Generate an octet string PS consisting of emLen - tLen - 3 octets
224
    // 4. Generate an octet string PS consisting of emLen - tLen - 3 octets
277
    //    with hexadecimal value 0xff.  The length of PS will be at least 8
225
    //    with hexadecimal value 0xff.  The length of PS will be at least 8
278
    //    octets.
226
    //    octets.
279
    final byte[] PS = new byte[emLen - tLen - 3];
227
    final byte[] PS = new byte[emLen - tLen - 3];
280
    for (int i = 0; i < PS.length; i++)
228
    for (int i = 0; i < PS.length; i++)
281
      {
229
      PS[i] = (byte) 0xFF;
282
        PS[i] = (byte) 0xFF;
283
      }
284
    // 5. Concatenate PS, the DER encoding T, and other padding to form the
230
    // 5. Concatenate PS, the DER encoding T, and other padding to form the
285
    //    encoded message EM as: EM = 0x00 || 0x01 || PS || 0x00 || T.
231
    //    encoded message EM as: EM = 0x00 || 0x01 || PS || 0x00 || T.
286
    baos.reset();
232
    baos.reset();
(-)sig/rsa/EMSA_PSS.java (-108 / +79 lines)
Lines 47-89 Link Here
47
import java.util.logging.Logger;
47
import java.util.logging.Logger;
48
48
49
/**
49
/**
50
 * <p>An implementation of the EMSA-PSS encoding/decoding scheme.</p>
50
 * An implementation of the EMSA-PSS encoding/decoding scheme.
51
 *
51
 * <p>
52
 * <p>EMSA-PSS coincides with EMSA4 in IEEE P1363a D5 except that EMSA-PSS acts
52
 * EMSA-PSS coincides with EMSA4 in IEEE P1363a D5 except that EMSA-PSS acts on
53
 * on octet strings and not on bit strings. In particular, the bit lengths of
53
 * octet strings and not on bit strings. In particular, the bit lengths of the
54
 * the hash and the salt must be multiples of 8 in EMSA-PSS. Moreover, EMSA4
54
 * hash and the salt must be multiples of 8 in EMSA-PSS. Moreover, EMSA4 outputs
55
 * outputs an integer of a desired bit length rather than an octet string.</p>
55
 * an integer of a desired bit length rather than an octet string.
56
 *
56
 * <p>
57
 * <p>EMSA-PSS is parameterized by the choice of hash function Hash and mask
57
 * EMSA-PSS is parameterized by the choice of hash function Hash and mask
58
 * generation function MGF. In this submission, MGF is based on a Hash
58
 * generation function MGF. In this submission, MGF is based on a Hash
59
 * definition that coincides with the corresponding definitions in IEEE Std
59
 * definition that coincides with the corresponding definitions in IEEE Std
60
 * 1363-2000, PKCS #1 v2.0, and the draft ANSI X9.44. In PKCS #1 v2.0 and the
60
 * 1363-2000, PKCS #1 v2.0, and the draft ANSI X9.44. In PKCS #1 v2.0 and the
61
 * draft ANSI X9.44, the recommended hash function is SHA-1, while IEEE Std
61
 * draft ANSI X9.44, the recommended hash function is SHA-1, while IEEE Std
62
 * 1363-2000 recommends SHA-1 and RIPEMD-160.</p>
62
 * 1363-2000 recommends SHA-1 and RIPEMD-160.
63
 *
63
 * <p>
64
 * <p>References:</p>
64
 * References:
65
 * <ol>
65
 * <ol>
66
 *    <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
66
 * <li><a
67
 *    RSA-PSS Signature Scheme with Appendix, part B.</a><br>
67
 * href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
68
 *    Primitive specification and supporting documentation.<br>
68
 * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
69
 *    Jakob Jonsson and Burt Kaliski.</li>
69
 * Primitive specification and supporting documentation.<br>
70
 * Jakob Jonsson and Burt Kaliski.</li>
70
 * </ol>
71
 * </ol>
71
 */
72
 */
72
public class EMSA_PSS implements Cloneable
73
public class EMSA_PSS
74
    implements Cloneable
73
{
75
{
74
  private static final Logger log = Logger.getLogger(EMSA_PSS.class.getName());
76
  private static final Logger log = Logger.getLogger(EMSA_PSS.class.getName());
77
75
  /** The underlying hash function to use with this instance. */
78
  /** The underlying hash function to use with this instance. */
76
  private IMessageDigest hash;
79
  private IMessageDigest hash;
77
80
78
  /** The output size of the hash function in octets. */
81
  /** The output size of the hash function in octets. */
79
  private int hLen;
82
  private int hLen;
80
83
81
  // Constructor(s)
82
  // -------------------------------------------------------------------------
83
84
  /**
84
  /**
85
   * <p>Trivial private constructor to enforce use through Factory method.</p>
85
   * Trivial private constructor to enforce use through Factory method.
86
   *
86
   * 
87
   * @param hash the message digest instance to use with this scheme instance.
87
   * @param hash the message digest instance to use with this scheme instance.
88
   */
88
   */
89
  private EMSA_PSS(IMessageDigest hash)
89
  private EMSA_PSS(IMessageDigest hash)
Lines 94-109 Link Here
94
    hLen = hash.hashSize();
94
    hLen = hash.hashSize();
95
  }
95
  }
96
96
97
  // Class methods
98
  // -------------------------------------------------------------------------
99
100
  /**
97
  /**
101
   * <p>Returns an instance of this object given a designated name of a hash
98
   * Returns an instance of this object given a designated name of a hash
102
   * function.</p>
99
   * function.
103
   *
100
   * 
104
   * @param mdName the canonical name of a hash function.
101
   * @param mdName the canonical name of a hash function.
105
   * @return an instance of this object configured for use with the designated
102
   * @return an instance of this object configured for use with the designated
106
   * options.
103
   *         options.
107
   */
104
   */
108
  public static EMSA_PSS getInstance(String mdName)
105
  public static EMSA_PSS getInstance(String mdName)
109
  {
106
  {
Lines 111-161 Link Here
111
    return new EMSA_PSS(hash);
108
    return new EMSA_PSS(hash);
112
  }
109
  }
113
110
114
  // Instance methods
115
  // -------------------------------------------------------------------------
116
117
  // Cloneable interface implementation --------------------------------------
118
119
  public Object clone()
111
  public Object clone()
120
  {
112
  {
121
    return getInstance(hash.name());
113
    return getInstance(hash.name());
122
  }
114
  }
123
115
124
  // own methods -------------------------------------------------------------
125
126
  /**
116
  /**
127
   * <p>The encoding operation EMSA-PSS-Encode computes the hash of a message
117
   * The encoding operation EMSA-PSS-Encode computes the hash of a message
128
   * <code>M</code> using a hash function and maps the result to an encoded
118
   * <code>M</code> using a hash function and maps the result to an encoded
129
   * message <code>EM</code> of a specified length using a mask generation
119
   * message <code>EM</code> of a specified length using a mask generation
130
   * function.</p>
120
   * function.
131
   *
121
   * 
132
   * @param mHash the byte sequence resulting from applying the message digest
122
   * @param mHash the byte sequence resulting from applying the message digest
133
   * algorithm Hash to the message <i>M</i>.
123
   *          algorithm Hash to the message <i>M</i>.
134
   * @param emBits the maximal bit length of the integer OS2IP(EM), at least
124
   * @param emBits the maximal bit length of the integer OS2IP(EM), at least
135
   * <code>8.hLen + 8.sLen + 9</code>.
125
   *          <code>8.hLen + 8.sLen + 9</code>.
136
   * @param salt the salt to use when encoding the output.
126
   * @param salt the salt to use when encoding the output.
137
   * @return the encoded message <code>EM</code>, an octet string of length
127
   * @return the encoded message <code>EM</code>, an octet string of length
138
   * <code>emLen = CEILING(emBits / 8)</code>.
128
   *         <code>emLen = CEILING(emBits / 8)</code>.
139
   * @exception IllegalArgumentException if an exception occurs.
129
   * @exception IllegalArgumentException if an exception occurs.
140
   *
141
   */
130
   */
142
  public byte[] encode(byte[] mHash, int emBits, byte[] salt)
131
  public byte[] encode(byte[] mHash, int emBits, byte[] salt)
143
  {
132
  {
144
    int sLen = salt.length;
133
    int sLen = salt.length;
145
146
    // 1. If the length of M is greater than the input limitation for the hash
134
    // 1. If the length of M is greater than the input limitation for the hash
147
    // function (2**61 - 1 octets for SHA-1) then output "message too long"
135
    // function (2**61 - 1 octets for SHA-1) then output "message too long"
148
    // and stop.
136
    // and stop.
149
    // 2. Let mHash = Hash(M), an octet string of length hLen.
137
    // 2. Let mHash = Hash(M), an octet string of length hLen.
150
    if (hLen != mHash.length)
138
    if (hLen != mHash.length)
151
      {
139
      throw new IllegalArgumentException("wrong hash");
152
        throw new IllegalArgumentException("wrong hash");
153
      }
154
    // 3. If emBits < 8.hLen + 8.sLen + 9, output 'encoding error' and stop.
140
    // 3. If emBits < 8.hLen + 8.sLen + 9, output 'encoding error' and stop.
155
    if (emBits < (8 * hLen + 8 * sLen + 9))
141
    if (emBits < (8 * hLen + 8 * sLen + 9))
156
      {
142
      throw new IllegalArgumentException("encoding error");
157
        throw new IllegalArgumentException("encoding error");
158
      }
159
    int emLen = (emBits + 7) / 8;
143
    int emLen = (emBits + 7) / 8;
160
    // 4. Generate a random octet string salt of length sLen; if sLen = 0,
144
    // 4. Generate a random octet string salt of length sLen; if sLen = 0,
161
    // then salt is the empty string.
145
    // then salt is the empty string.
Lines 169-177 Link Here
169
    synchronized (hash)
153
    synchronized (hash)
170
      {
154
      {
171
        for (i = 0; i < 8; i++)
155
        for (i = 0; i < 8; i++)
172
          {
156
          hash.update((byte) 0x00);
173
            hash.update((byte) 0x00);
157
174
          }
175
        hash.update(mHash, 0, hLen);
158
        hash.update(mHash, 0, hLen);
176
        hash.update(salt, 0, sLen);
159
        hash.update(salt, 0, sLen);
177
        H = hash.digest();
160
        H = hash.digest();
Lines 191-199 Link Here
191
      }
174
      }
192
    // 10. Let maskedDB = DB XOR dbMask.
175
    // 10. Let maskedDB = DB XOR dbMask.
193
    for (i = 0; i < DB.length; i++)
176
    for (i = 0; i < DB.length; i++)
194
      {
177
      DB[i] = (byte)(DB[i] ^ dbMask[i]);
195
        DB[i] = (byte) (DB[i] ^ dbMask[i]);
196
      }
197
    // 11. Set the leftmost 8emLen - emBits bits of the leftmost octet in
178
    // 11. Set the leftmost 8emLen - emBits bits of the leftmost octet in
198
    // maskedDB to zero.
179
    // maskedDB to zero.
199
    DB[0] &= (0xFF >>> (8 * emLen - emBits));
180
    DB[0] &= (0xFF >>> (8 * emLen - emBits));
Lines 208-221 Link Here
208
  }
189
  }
209
190
210
  /**
191
  /**
211
   * <p>The decoding operation EMSA-PSS-Decode recovers the message hash from
192
   * The decoding operation EMSA-PSS-Decode recovers the message hash from an
212
   * an encoded message <code>EM</code> and compares it to the hash of
193
   * encoded message <code>EM</code> and compares it to the hash of
213
   * <code>M</code>.</p>
194
   * <code>M</code>.
214
   *
195
   * 
215
   * @param mHash the byte sequence resulting from applying the message digest
196
   * @param mHash the byte sequence resulting from applying the message digest
216
   * algorithm Hash to the message <i>M</i>.
197
   *          algorithm Hash to the message <i>M</i>.
217
   * @param EM the <i>encoded message</i>, an octet string of length
198
   * @param EM the <i>encoded message</i>, an octet string of length
218
   * <code>emLen = CEILING(emBits/8).
199
   *          <code>emLen = CEILING(emBits/8).
219
   * @param emBits the maximal bit length of the integer OS2IP(EM), at least
200
   * @param emBits the maximal bit length of the integer OS2IP(EM), at least
220
   * <code>8.hLen + 8.sLen + 9</code>.
201
   * <code>8.hLen + 8.sLen + 9</code>.
221
   * @param sLen the length, in octets, of the expected salt.
202
   * @param sLen the length, in octets, of the expected salt.
Lines 234-246 Link Here
234
        log.fine("sLen: " + String.valueOf(sLen));
215
        log.fine("sLen: " + String.valueOf(sLen));
235
      }
216
      }
236
    if (sLen < 0)
217
    if (sLen < 0)
237
      {
218
      throw new IllegalArgumentException("sLen");
238
        throw new IllegalArgumentException("sLen");
239
      }
240
241
    // 1. If the length of M is greater than the input limitation for the hash
219
    // 1. If the length of M is greater than the input limitation for the hash
242
    //    function (2**61 ? 1 octets for SHA-1) then output 'inconsistent' and
220
    // function (2**61 ? 1 octets for SHA-1) then output 'inconsistent' and
243
    //    stop.
221
    // stop.
244
    // 2. Let mHash = Hash(M), an octet string of length hLen.
222
    // 2. Let mHash = Hash(M), an octet string of length hLen.
245
    if (hLen != mHash.length)
223
    if (hLen != mHash.length)
246
      {
224
      {
Lines 252-263 Link Here
252
    if (emBits < (8 * hLen + 8 * sLen + 9))
230
    if (emBits < (8 * hLen + 8 * sLen + 9))
253
      {
231
      {
254
        if (Configuration.DEBUG)
232
        if (Configuration.DEBUG)
255
          log.fine("emBits < (8hLen + 8sLen + 9); sLen: " + String.valueOf(sLen));
233
          log.fine("emBits < (8hLen + 8sLen + 9); sLen: "
234
                   + String.valueOf(sLen));
256
        throw new IllegalArgumentException("decoding error");
235
        throw new IllegalArgumentException("decoding error");
257
      }
236
      }
258
    int emLen = (emBits + 7) / 8;
237
    int emLen = (emBits + 7) / 8;
259
    // 4. If the rightmost octet of EM does not have hexadecimal value bc,
238
    // 4. If the rightmost octet of EM does not have hexadecimal value bc,
260
    //    output 'inconsistent' and stop.
239
    // output 'inconsistent' and stop.
261
    if ((EM[EM.length - 1] & 0xFF) != 0xBC)
240
    if ((EM[EM.length - 1] & 0xFF) != 0xBC)
262
      {
241
      {
263
        if (Configuration.DEBUG)
242
        if (Configuration.DEBUG)
Lines 265-273 Link Here
265
        return false;
244
        return false;
266
      }
245
      }
267
    // 5. Let maskedDB be the leftmost emLen ? hLen ? 1 octets of EM, and let
246
    // 5. Let maskedDB be the leftmost emLen ? hLen ? 1 octets of EM, and let
268
    //    H be the next hLen octets.
247
    // H be the next hLen octets.
269
    // 6. If the leftmost 8.emLen ? emBits bits of the leftmost octet in
248
    // 6. If the leftmost 8.emLen ? emBits bits of the leftmost octet in
270
    //    maskedDB are not all equal to zero, output 'inconsistent' and stop.
249
    // maskedDB are not all equal to zero, output 'inconsistent' and stop.
271
    if ((EM[0] & (0xFF << (8 - (8 * emLen - emBits)))) != 0)
250
    if ((EM[0] & (0xFF << (8 - (8 * emLen - emBits)))) != 0)
272
      {
251
      {
273
        if (Configuration.DEBUG)
252
        if (Configuration.DEBUG)
Lines 283-291 Link Here
283
    // 8. Let DB = maskedDB XOR dbMask.
262
    // 8. Let DB = maskedDB XOR dbMask.
284
    int i;
263
    int i;
285
    for (i = 0; i < DB.length; i++)
264
    for (i = 0; i < DB.length; i++)
286
      {
265
      DB[i] = (byte)(DB[i] ^ dbMask[i]);
287
        DB[i] = (byte) (DB[i] ^ dbMask[i]);
288
      }
289
    // 9. Set the leftmost 8.emLen ? emBits bits of DB to zero.
266
    // 9. Set the leftmost 8.emLen ? emBits bits of DB to zero.
290
    DB[0] &= (0xFF >>> (8 * emLen - emBits));
267
    DB[0] &= (0xFF >>> (8 * emLen - emBits));
291
    if (Configuration.DEBUG)
268
    if (Configuration.DEBUG)
Lines 294-304 Link Here
294
        log.fine("DB (decode): " + Util.toString(DB));
271
        log.fine("DB (decode): " + Util.toString(DB));
295
      }
272
      }
296
    // 10. If the emLen -hLen -sLen -2 leftmost octets of DB are not zero or
273
    // 10. If the emLen -hLen -sLen -2 leftmost octets of DB are not zero or
297
    //     if the octet at position emLen -hLen -sLen -1 is not equal to 0x01,
274
    // if the octet at position emLen -hLen -sLen -1 is not equal to 0x01,
298
    //     output 'inconsistent' and stop.
275
    // output 'inconsistent' and stop.
299
    // IMPORTANT (rsn): this is an error in the specs, the index of the 0x01
276
    // IMPORTANT (rsn): this is an error in the specs, the index of the 0x01
300
    // byte should be emLen -hLen -sLen -2 and not -1! authors have been
277
    // byte should be emLen -hLen -sLen -2 and not -1! authors have been advised
301
    // advised
302
    for (i = 0; i < (emLen - hLen - sLen - 2); i++)
278
    for (i = 0; i < (emLen - hLen - sLen - 2); i++)
303
      {
279
      {
304
        if (DB[i] != 0)
280
        if (DB[i] != 0)
Lines 319-334 Link Here
319
    byte[] salt = new byte[sLen];
295
    byte[] salt = new byte[sLen];
320
    System.arraycopy(DB, DB.length - sLen, salt, 0, sLen);
296
    System.arraycopy(DB, DB.length - sLen, salt, 0, sLen);
321
    // 12. Let M0 = 00 00 00 00 00 00 00 00 || mHash || salt;
297
    // 12. Let M0 = 00 00 00 00 00 00 00 00 || mHash || salt;
322
    //     M0 is an octet string of length 8 + hLen + sLen with eight initial
298
    // M0 is an octet string of length 8 + hLen + sLen with eight initial
323
    //     zero octets.
299
    // zero octets.
324
    // 13. Let H0 = Hash(M0), an octet string of length hLen.
300
    // 13. Let H0 = Hash(M0), an octet string of length hLen.
325
    byte[] H0;
301
    byte[] H0;
326
    synchronized (hash)
302
    synchronized (hash)
327
      {
303
      {
328
        for (i = 0; i < 8; i++)
304
        for (i = 0; i < 8; i++)
329
          {
305
          hash.update((byte) 0x00);
330
            hash.update((byte) 0x00);
306
331
          }
332
        hash.update(mHash, 0, hLen);
307
        hash.update(mHash, 0, hLen);
333
        hash.update(salt, 0, sLen);
308
        hash.update(salt, 0, sLen);
334
        H0 = hash.digest();
309
        H0 = hash.digest();
Lines 337-370 Link Here
337
    return Arrays.equals(H, H0);
312
    return Arrays.equals(H, H0);
338
  }
313
  }
339
314
340
  // helper methods ----------------------------------------------------------
341
342
  /**
315
  /**
343
   * <p>A mask generation function takes an octet string of variable length
316
   * A mask generation function takes an octet string of variable length and a
344
   * and a desired output length as input, and outputs an octet string of the
317
   * desired output length as input, and outputs an octet string of the desired
345
   * desired length. There may be restrictions on the length of the input and
318
   * length. There may be restrictions on the length of the input and output
346
   * output octet strings, but such bounds are generally very large. Mask
319
   * octet strings, but such bounds are generally very large. Mask generation
347
   * generation functions are deterministic; the octet string output is
320
   * functions are deterministic; the octet string output is completely
348
   * completely determined by the input octet string. The output of a mask
321
   * determined by the input octet string. The output of a mask generation
349
   * generation function should be pseudorandom, that is, it should be
322
   * function should be pseudorandom, that is, it should be infeasible to
350
   * infeasible to predict, given one part of the output but not the input,
323
   * predict, given one part of the output but not the input, another part of
351
   * another part of the output. The provable security of RSA-PSS relies on
324
   * the output. The provable security of RSA-PSS relies on the random nature of
352
   * the random nature of the output of the mask generation function, which in
325
   * the output of the mask generation function, which in turn relies on the
353
   * turn relies on the random nature of the underlying hash function.</p>
326
   * random nature of the underlying hash function.
354
   *
327
   * 
355
   * @param Z a seed.
328
   * @param Z a seed.
356
   * @param l the desired output length in octets.
329
   * @param l the desired output length in octets.
357
   * @return the mask.
330
   * @return the mask.
358
   * @exception IllegalArgumentException if the desired output length is too
331
   * @exception IllegalArgumentException if the desired output length is too
359
   * long.
332
   *              long.
360
   */
333
   */
361
  private byte[] MGF(byte[] Z, int l)
334
  private byte[] MGF(byte[] Z, int l)
362
  {
335
  {
363
    // 1. If l > (2**32).hLen, output 'mask too long' and stop.
336
    // 1. If l > (2**32).hLen, output 'mask too long' and stop.
364
    if (l < 1 || (l & 0xFFFFFFFFL) > ((hLen & 0xFFFFFFFFL) << 32L))
337
    if (l < 1 || (l & 0xFFFFFFFFL) > ((hLen & 0xFFFFFFFFL) << 32L))
365
      {
338
      throw new IllegalArgumentException("mask too long");
366
        throw new IllegalArgumentException("mask too long");
367
      }
368
    // 2. Let T be the empty octet string.
339
    // 2. Let T be the empty octet string.
369
    byte[] result = new byte[l];
340
    byte[] result = new byte[l];
370
    // 3. For i = 0 to CEILING(l/hLen) ? 1, do
341
    // 3. For i = 0 to CEILING(l/hLen) ? 1, do
Lines 379-392 Link Here
379
    int length;
350
    int length;
380
    for (int i = 0; i < limit; i++)
351
    for (int i = 0; i < limit; i++)
381
      {
352
      {
382
        //    3.1 Convert i to an octet string C of length 4 with the primitive
353
        // 3.1 Convert i to an octet string C of length 4 with the primitive
383
        //        I2OSP: C = I2OSP(i, 4).
354
        // I2OSP: C = I2OSP(i, 4).
384
        //    3.2 Concatenate the hash of the seed Z and C to the octet string T:
355
        // 3.2 Concatenate the hash of the seed Z and C to the octet string T:
385
        //        T = T || Hash(Z || C)
356
        // T = T || Hash(Z || C)
386
        hashZC = (IMessageDigest) hashZ.clone();
357
        hashZC = (IMessageDigest) hashZ.clone();
387
        hashZC.update((byte) (i >>> 24));
358
        hashZC.update((byte)(i >>> 24));
388
        hashZC.update((byte) (i >>> 16));
359
        hashZC.update((byte)(i >>> 16));
389
        hashZC.update((byte) (i >>> 8));
360
        hashZC.update((byte)(i >>> 8));
390
        hashZC.update((byte) i);
361
        hashZC.update((byte) i);
391
        t = hashZC.digest();
362
        t = hashZC.digest();
392
        length = l - sofar;
363
        length = l - sofar;
(-)sig/rsa/RSA.java (-107 / +75 lines)
Lines 49-79 Link Here
49
import java.security.interfaces.RSAPublicKey;
49
import java.security.interfaces.RSAPublicKey;
50
50
51
/**
51
/**
52
 * <p>Utility methods related to the RSA algorithm.</p>
52
 * Utility methods related to the RSA algorithm.
53
 *
53
 * <p>
54
 * <p>References:</p>
54
 * References:
55
 * <ol>
55
 * <ol>
56
 *    <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
56
 * <li><a
57
 *    RSA-PSS Signature Scheme with Appendix, part B.</a><br>
57
 * href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
58
 *    Primitive specification and supporting documentation.<br>
58
 * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
59
 *    Jakob Jonsson and Burt Kaliski.</li>
59
 * Primitive specification and supporting documentation.<br>
60
 *
60
 * Jakob Jonsson and Burt Kaliski.</li>
61
 *    <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
61
 * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
62
 *    Standards (PKCS) #1:</a><br>
62
 * Standards (PKCS) #1:</a><br>
63
 *    RSA Cryptography Specifications Version 2.1.<br>
63
 * RSA Cryptography Specifications Version 2.1.<br>
64
 *    Jakob Jonsson and Burt Kaliski.</li>
64
 * Jakob Jonsson and Burt Kaliski.</li>
65
 *
65
 * <li><a href="http://crypto.stanford.edu/~dabo/abstracts/ssl-timing.html">
66
 *    <li><a href="http://crypto.stanford.edu/~dabo/abstracts/ssl-timing.html">
66
 * Remote timing attacks are practical</a><br>
67
 *    Remote timing attacks are practical</a><br>
67
 * D. Boneh and D. Brumley.</li>
68
 *    D. Boneh and D. Brumley.</li>
69
 * </ol>
68
 * </ol>
70
 */
69
 */
71
public class RSA
70
public class RSA
72
{
71
{
73
74
  // Constants and variables
75
  // -------------------------------------------------------------------------
76
77
  private static final BigInteger ZERO = BigInteger.ZERO;
72
  private static final BigInteger ZERO = BigInteger.ZERO;
78
73
79
  private static final BigInteger ONE = BigInteger.ONE;
74
  private static final BigInteger ONE = BigInteger.ONE;
Lines 81-117 Link Here
81
  /** Our default source of randomness. */
76
  /** Our default source of randomness. */
82
  private static final PRNG prng = PRNG.getInstance();
77
  private static final PRNG prng = PRNG.getInstance();
83
78
84
  // Constructor(s)
85
  // -------------------------------------------------------------------------
86
87
  /** Trivial private constructor to enforce Singleton pattern. */
79
  /** Trivial private constructor to enforce Singleton pattern. */
88
  private RSA()
80
  private RSA()
89
  {
81
  {
90
    super();
82
    super();
91
  }
83
  }
92
84
93
  // Class methods
94
  // -------------------------------------------------------------------------
95
96
  // Signature and verification methods --------------------------------------
97
98
  /**
85
  /**
99
   * <p>An implementation of the <b>RSASP</b> method: Assuming that the
86
   * An implementation of the <b>RSASP</b> method: Assuming that the designated
100
   * designated RSA private key is a valid one, this method computes a
87
   * RSA private key is a valid one, this method computes a <i>signature
101
   * <i>signature representative</i> for a designated <i>message
88
   * representative</i> for a designated <i>message representative</i> signed
102
   * representative</i> signed by the holder of the designated RSA private
89
   * by the holder of the designated RSA private key.
103
   * key.<p>
90
   * 
104
   *
105
   * @param K the RSA private key.
91
   * @param K the RSA private key.
106
   * @param m the <i>message representative</i>: an integer between
92
   * @param m the <i>message representative</i>: an integer between
107
   * <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
93
   *          <code>0</code> and <code>n - 1</code>, where <code>n</code>
108
   * <i>modulus</i>.
94
   *          is the RSA <i>modulus</i>.
109
   * @return the <i>signature representative</i>, an integer between
95
   * @return the <i>signature representative</i>, an integer between
110
   * <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
96
   *         <code>0</code> and <code>n - 1</code>, where <code>n</code>
111
   * <i>modulus</i>.
97
   *         is the RSA <i>modulus</i>.
112
   * @throws ClassCastException if <code>K</code> is not an RSA one.
98
   * @throws ClassCastException if <code>K</code> is not an RSA one.
113
   * @throws IllegalArgumentException if <code>m</code> (the <i>message
99
   * @throws IllegalArgumentException if <code>m</code> (the <i>message
114
   * representative</i>) is out of range.
100
   *           representative</i>) is out of range.
115
   */
101
   */
116
  public static final BigInteger sign(final PrivateKey K, final BigInteger m)
102
  public static final BigInteger sign(final PrivateKey K, final BigInteger m)
117
  {
103
  {
Lines 121-147 Link Here
121
      }
107
      }
122
    catch (IllegalArgumentException x)
108
    catch (IllegalArgumentException x)
123
      {
109
      {
124
        throw new IllegalArgumentException(
110
        throw new IllegalArgumentException("message representative out of range");
125
                                           "message representative out of range");
126
      }
111
      }
127
  }
112
  }
128
113
129
  /**
114
  /**
130
   * <p>An implementation of the <b>RSAVP</b> method: Assuming that the
115
   * An implementation of the <b>RSAVP</b> method: Assuming that the designated
131
   * designated RSA public key is a valid one, this method computes a
116
   * RSA public key is a valid one, this method computes a <i>message
132
   * <i>message representative</i> for the designated <i>signature
117
   * representative</i> for the designated <i>signature representative</i>
133
   * representative</i> generated by an RSA private key, for a message
118
   * generated by an RSA private key, for a message intended for the holder of
134
   * intended for the holder of the designated RSA public key.</p>
119
   * the designated RSA public key.
135
   *
120
   * 
136
   * @param K the RSA public key.
121
   * @param K the RSA public key.
137
   * @param s the <i>signature representative</i>, an integer between
122
   * @param s the <i>signature representative</i>, an integer between
138
   * <code>0</code> and <code>n - 1</code>, where <code>n</code> is the RSA
123
   *          <code>0</code> and <code>n - 1</code>, where <code>n</code>
139
   * <i>modulus</i>.
124
   *          is the RSA <i>modulus</i>.
140
   * @return a <i>message representative</i>: an integer between <code>0</code>
125
   * @return a <i>message representative</i>: an integer between <code>0</code>
141
   * and <code>n - 1</code>, where <code>n</code> is the RSA <i>modulus</i>.
126
   *         and <code>n - 1</code>, where <code>n</code> is the RSA
127
   *         <i>modulus</i>.
142
   * @throws ClassCastException if <code>K</code> is not an RSA one.
128
   * @throws ClassCastException if <code>K</code> is not an RSA one.
143
   * @throws IllegalArgumentException if <code>s</code> (the <i>signature
129
   * @throws IllegalArgumentException if <code>s</code> (the <i>signature
144
   * representative</i>) is out of range.
130
   *           representative</i>) is out of range.
145
   */
131
   */
146
  public static final BigInteger verify(final PublicKey K, final BigInteger s)
132
  public static final BigInteger verify(final PublicKey K, final BigInteger s)
147
  {
133
  {
Lines 151-175 Link Here
151
      }
137
      }
152
    catch (IllegalArgumentException x)
138
    catch (IllegalArgumentException x)
153
      {
139
      {
154
        throw new IllegalArgumentException(
140
        throw new IllegalArgumentException("signature representative out of range");
155
                                           "signature representative out of range");
156
      }
141
      }
157
  }
142
  }
158
143
159
  // Encryption and decryption methods ---------------------------------------
160
161
  /**
144
  /**
162
   * <p>An implementation of the <code>RSAEP</code> algorithm.</p>
145
   * An implementation of the <code>RSAEP</code> algorithm.
163
   *
146
   * 
164
   * @param K the recipient's RSA public key.
147
   * @param K the recipient's RSA public key.
165
   * @param m the message representative as an MPI.
148
   * @param m the message representative as an MPI.
166
   * @return the resulting MPI --an MPI between <code>0</code> and
149
   * @return the resulting MPI --an MPI between <code>0</code> and
167
   * <code>n - 1</code> (<code>n</code> being the public shared modulus)-- that
150
   *         <code>n - 1</code> (<code>n</code> being the public shared
168
   * will eventually be padded with an appropriate framing/padding scheme.
151
   *         modulus)-- that will eventually be padded with an appropriate
152
   *         framing/padding scheme.
169
   * @throws ClassCastException if <code>K</code> is not an RSA one.
153
   * @throws ClassCastException if <code>K</code> is not an RSA one.
170
   * @throws IllegalArgumentException if <code>m</code>, the message
154
   * @throws IllegalArgumentException if <code>m</code>, the message
171
   * representative is not between <code>0</code> and <code>n - 1</code>
155
   *           representative is not between <code>0</code> and
172
   * (<code>n</code> being the public shared modulus).
156
   *           <code>n - 1</code> (<code>n</code> being the public shared
157
   *           modulus).
173
   */
158
   */
174
  public static final BigInteger encrypt(final PublicKey K, final BigInteger m)
159
  public static final BigInteger encrypt(final PublicKey K, final BigInteger m)
175
  {
160
  {
Lines 179-200 Link Here
179
      }
164
      }
180
    catch (IllegalArgumentException x)
165
    catch (IllegalArgumentException x)
181
      {
166
      {
182
        throw new IllegalArgumentException(
167
        throw new IllegalArgumentException("message representative out of range");
183
                                           "message representative out of range");
184
      }
168
      }
185
  }
169
  }
186
170
187
  /**
171
  /**
188
   * <p>An implementation of the <code>RSADP</code> algorithm.</p>
172
   * An implementation of the <code>RSADP</code> algorithm.
189
   *
173
   * 
190
   * @param K the recipient's RSA private key.
174
   * @param K the recipient's RSA private key.
191
   * @param c the ciphertext representative as an MPI.
175
   * @param c the ciphertext representative as an MPI.
192
   * @return the message representative, an MPI between <code>0</code> and
176
   * @return the message representative, an MPI between <code>0</code> and
193
   * <code>n - 1</code> (<code>n</code> being the shared public modulus).
177
   *         <code>n - 1</code> (<code>n</code> being the shared public
178
   *         modulus).
194
   * @throws ClassCastException if <code>K</code> is not an RSA one.
179
   * @throws ClassCastException if <code>K</code> is not an RSA one.
195
   * @throws IllegalArgumentException if <code>c</code>, the ciphertext
180
   * @throws IllegalArgumentException if <code>c</code>, the ciphertext
196
   * representative is not between <code>0</code> and <code>n - 1</code>
181
   *           representative is not between <code>0</code> and
197
   * (<code>n</code> being the shared public modulus).
182
   *           <code>n - 1</code> (<code>n</code> being the shared public
183
   *           modulus).
198
   */
184
   */
199
  public static final BigInteger decrypt(final PrivateKey K, final BigInteger c)
185
  public static final BigInteger decrypt(final PrivateKey K, final BigInteger c)
200
  {
186
  {
Lines 204-225 Link Here
204
      }
190
      }
205
    catch (IllegalArgumentException x)
191
    catch (IllegalArgumentException x)
206
      {
192
      {
207
        throw new IllegalArgumentException(
193
        throw new IllegalArgumentException("ciphertext representative out of range");
208
                                           "ciphertext representative out of range");
209
      }
194
      }
210
  }
195
  }
211
196
212
  // Conversion methods ------------------------------------------------------
213
214
  /**
197
  /**
215
   * <p>Converts a <i>multi-precision integer</i> (MPI) <code>s</code> into an
198
   * Converts a <i>multi-precision integer</i> (MPI) <code>s</code> into an
216
   * octet sequence of length <code>k</code>.</p>
199
   * octet sequence of length <code>k</code>.
217
   *
200
   * 
218
   * @param s the multi-precision integer to convert.
201
   * @param s the multi-precision integer to convert.
219
   * @param k the length of the output.
202
   * @param k the length of the output.
220
   * @return the result of the transform.
203
   * @return the result of the transform.
221
   * @exception IllegalArgumentException if the length in octets of meaningful
204
   * @exception IllegalArgumentException if the length in octets of meaningful
222
   * bytes of <code>s</code> is greater than <code>k</code>.
205
   *              bytes of <code>s</code> is greater than <code>k</code>.
223
   */
206
   */
224
  public static final byte[] I2OSP(final BigInteger s, final int k)
207
  public static final byte[] I2OSP(final BigInteger s, final int k)
225
  {
208
  {
Lines 236-244 Link Here
236
        for (int i = 0; i < limit; i++)
219
        for (int i = 0; i < limit; i++)
237
          {
220
          {
238
            if (result[i] != 0x00)
221
            if (result[i] != 0x00)
239
              {
222
              throw new IllegalArgumentException("integer too large");
240
                throw new IllegalArgumentException("integer too large");
241
              }
242
          }
223
          }
243
        final byte[] newResult = new byte[k];
224
        final byte[] newResult = new byte[k];
244
        System.arraycopy(result, limit, newResult, 0, k);
225
        System.arraycopy(result, limit, newResult, 0, k);
Lines 247-263 Link Here
247
    return result;
228
    return result;
248
  }
229
  }
249
230
250
  // helper methods ----------------------------------------------------------
251
252
  private static final BigInteger RSAEP(final RSAPublicKey K, final BigInteger m)
231
  private static final BigInteger RSAEP(final RSAPublicKey K, final BigInteger m)
253
  {
232
  {
254
    // 1. If the representative m is not between 0 and n - 1, output
233
    // 1. If the representative m is not between 0 and n - 1, output
255
    //    "representative out of range" and stop.
234
    // "representative out of range" and stop.
256
    final BigInteger n = K.getModulus();
235
    final BigInteger n = K.getModulus();
257
    if (m.compareTo(ZERO) < 0 || m.compareTo(n.subtract(ONE)) > 0)
236
    if (m.compareTo(ZERO) < 0 || m.compareTo(n.subtract(ONE)) > 0)
258
      {
237
      throw new IllegalArgumentException();
259
        throw new IllegalArgumentException();
260
      }
261
    // 2. Let c = m^e mod n.
238
    // 2. Let c = m^e mod n.
262
    final BigInteger e = K.getPublicExponent();
239
    final BigInteger e = K.getPublicExponent();
263
    final BigInteger result = m.modPow(e, n);
240
    final BigInteger result = m.modPow(e, n);
Lines 268-283 Link Here
268
  private static final BigInteger RSADP(final RSAPrivateKey K, BigInteger c)
245
  private static final BigInteger RSADP(final RSAPrivateKey K, BigInteger c)
269
  {
246
  {
270
    // 1. If the representative c is not between 0 and n - 1, output
247
    // 1. If the representative c is not between 0 and n - 1, output
271
    //    "representative out of range" and stop.
248
    // "representative out of range" and stop.
272
    final BigInteger n = K.getModulus();
249
    final BigInteger n = K.getModulus();
273
    if (c.compareTo(ZERO) < 0 || c.compareTo(n.subtract(ONE)) > 0)
250
    if (c.compareTo(ZERO) < 0 || c.compareTo(n.subtract(ONE)) > 0)
274
      {
251
      throw new IllegalArgumentException();
275
        throw new IllegalArgumentException();
276
      }
277
278
    // 2. The representative m is computed as follows.
252
    // 2. The representative m is computed as follows.
279
    BigInteger result;
253
    BigInteger result;
280
    if (!(K instanceof RSAPrivateCrtKey))
254
    if (! (K instanceof RSAPrivateCrtKey))
281
      {
255
      {
282
        // a. If the first form (n, d) of K is used, let m = c^d mod n.
256
        // a. If the first form (n, d) of K is used, let m = c^d mod n.
283
        final BigInteger d = K.getPrivateExponent();
257
        final BigInteger d = K.getPrivateExponent();
Lines 303-340 Link Here
303
            final BigInteger x = r.modPow(e, n).multiply(c).mod(n);
277
            final BigInteger x = r.modPow(e, n).multiply(c).mod(n);
304
            c = x;
278
            c = x;
305
          }
279
          }
306
307
        // b. If the second form (p, q, dP, dQ, qInv) and (r_i, d_i, t_i)
280
        // b. If the second form (p, q, dP, dQ, qInv) and (r_i, d_i, t_i)
308
        //    of K is used, proceed as follows:
281
        // of K is used, proceed as follows:
309
        final BigInteger p = ((RSAPrivateCrtKey) K).getPrimeP();
282
        final BigInteger p = ((RSAPrivateCrtKey) K).getPrimeP();
310
        final BigInteger q = ((RSAPrivateCrtKey) K).getPrimeQ();
283
        final BigInteger q = ((RSAPrivateCrtKey) K).getPrimeQ();
311
        final BigInteger dP = ((RSAPrivateCrtKey) K).getPrimeExponentP();
284
        final BigInteger dP = ((RSAPrivateCrtKey) K).getPrimeExponentP();
312
        final BigInteger dQ = ((RSAPrivateCrtKey) K).getPrimeExponentQ();
285
        final BigInteger dQ = ((RSAPrivateCrtKey) K).getPrimeExponentQ();
313
        final BigInteger qInv = ((RSAPrivateCrtKey) K).getCrtCoefficient();
286
        final BigInteger qInv = ((RSAPrivateCrtKey) K).getCrtCoefficient();
314
287
        // i. Let m_1 = c^dP mod p and m_2 = c^dQ mod q.
315
        // i.    Let m_1 = c^dP mod p and m_2 = c^dQ mod q.
316
        final BigInteger m_1 = c.modPow(dP, p);
288
        final BigInteger m_1 = c.modPow(dP, p);
317
        final BigInteger m_2 = c.modPow(dQ, q);
289
        final BigInteger m_2 = c.modPow(dQ, q);
318
        // ii.   If u > 2, let m_i = c^(d_i) mod r_i, i = 3, ..., u.
290
        // ii. If u > 2, let m_i = c^(d_i) mod r_i, i = 3, ..., u.
319
        // iii.  Let h = (m_1 - m_2) * qInv mod p.
291
        // iii. Let h = (m_1 - m_2) * qInv mod p.
320
        final BigInteger h = m_1.subtract(m_2).multiply(qInv).mod(p);
292
        final BigInteger h = m_1.subtract(m_2).multiply(qInv).mod(p);
321
        // iv.   Let m = m_2 + q * h.
293
        // iv. Let m = m_2 + q * h.
322
        result = m_2.add(q.multiply(h));
294
        result = m_2.add(q.multiply(h));
323
295
        if (rsaBlinding) // post-decryption
324
        if (rsaBlinding)
296
          result = result.multiply(r.modInverse(n)).mod(n);
325
          { // post-decryption
326
            result = result.multiply(r.modInverse(n)).mod(n);
327
          }
328
      }
297
      }
329
330
    // 3. Output m
298
    // 3. Output m
331
    return result;
299
    return result;
332
  }
300
  }
333
301
334
  /**
302
  /**
335
   * <p>Returns a random MPI with a random bit-length of the form <code>8b</code>,
303
   * Returns a random MPI with a random bit-length of the form <code>8b</code>,
336
   * where <code>b</code> is in the range <code>[32..64]</code>.</p>
304
   * where <code>b</code> is in the range <code>[32..64]</code>.
337
   *
305
   * 
338
   * @return a random MPI whose length in bytes is between 32 and 64 inclusive.
306
   * @return a random MPI whose length in bytes is between 32 and 64 inclusive.
339
   */
307
   */
340
  private static final BigInteger newR(final BigInteger N)
308
  private static final BigInteger newR(final BigInteger N)
(-)sig/rsa/RSAPKCS1V1_5Signature.java (-83 / +62 lines)
Lines 51-85 Link Here
51
import java.util.Arrays;
51
import java.util.Arrays;
52
52
53
/**
53
/**
54
 * <p>The RSA-PKCS1-V1.5 signature scheme is a digital signature scheme with
54
 * The RSA-PKCS1-V1.5 signature scheme is a digital signature scheme with
55
 * appendix (SSA) combining the RSA algorithm with the EMSA-PKCS1-v1_5 encoding
55
 * appendix (SSA) combining the RSA algorithm with the EMSA-PKCS1-v1_5 encoding
56
 * method.</p>
56
 * method.
57
 *
57
 * <p>
58
 * <p>References:</p>
58
 * References:
59
 * <ol>
59
 * <ol>
60
 *    <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
60
 * <li><a
61
 *    RSA-PSS Signature Scheme with Appendix, part B.</a><br>
61
 * href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
62
 *    Primitive specification and supporting documentation.<br>
62
 * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
63
 *    Jakob Jonsson and Burt Kaliski.</li>
63
 * Primitive specification and supporting documentation.<br>
64
 *
64
 * Jakob Jonsson and Burt Kaliski.</li>
65
 *    <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
65
 * <li><a href="http://www.ietf.org/rfc/rfc3447.txt">Public-Key Cryptography
66
 *    Standards (PKCS) #1:</a><br>
66
 * Standards (PKCS) #1:</a><br>
67
 *    RSA Cryptography Specifications Version 2.1.<br>
67
 * RSA Cryptography Specifications Version 2.1.<br>
68
 *    Jakob Jonsson and Burt Kaliski.</li>
68
 * Jakob Jonsson and Burt Kaliski.</li>
69
 * </ol>
69
 * </ol>
70
 */
70
 */
71
public class RSAPKCS1V1_5Signature extends BaseSignature
71
public class RSAPKCS1V1_5Signature
72
    extends BaseSignature
72
{
73
{
73
74
  // Constants and variables
75
  // -------------------------------------------------------------------------
76
77
  /** The underlying EMSA-PKCS1-v1.5 instance for this object. */
74
  /** The underlying EMSA-PKCS1-v1.5 instance for this object. */
78
  private EMSA_PKCS1_V1_5 pkcs1;
75
  private EMSA_PKCS1_V1_5 pkcs1;
79
76
80
  // Constructor(s)
81
  // -------------------------------------------------------------------------
82
83
  /**
77
  /**
84
   * Default 0-arguments constructor. Uses SHA-1 as the default hash.
78
   * Default 0-arguments constructor. Uses SHA-1 as the default hash.
85
   */
79
   */
Lines 89-97 Link Here
89
  }
83
  }
90
84
91
  /**
85
  /**
92
   * <p>Constructs an instance of this object using the designated message
86
   * Constructs an instance of this object using the designated message digest
93
   * digest algorithm as its underlying hash function.</p>
87
   * algorithm as its underlying hash function.
94
   *
88
   * 
95
   * @param mdName the canonical name of the underlying hash function.
89
   * @param mdName the canonical name of the underlying hash function.
96
   */
90
   */
97
  public RSAPKCS1V1_5Signature(final String mdName)
91
  public RSAPKCS1V1_5Signature(final String mdName)
Lines 117-130 Link Here
117
    this.pkcs1 = (EMSA_PKCS1_V1_5) that.pkcs1.clone();
111
    this.pkcs1 = (EMSA_PKCS1_V1_5) that.pkcs1.clone();
118
  }
112
  }
119
113
120
  // Class methods
121
  // -------------------------------------------------------------------------
122
123
  // Instance methods
124
  // -------------------------------------------------------------------------
125
126
  // Implementation of abstract methods in superclass ------------------------
127
128
  public Object clone()
114
  public Object clone()
129
  {
115
  {
130
    return new RSAPKCS1V1_5Signature(this);
116
    return new RSAPKCS1V1_5Signature(this);
Lines 133-181 Link Here
133
  protected void setupForVerification(final PublicKey k)
119
  protected void setupForVerification(final PublicKey k)
134
      throws IllegalArgumentException
120
      throws IllegalArgumentException
135
  {
121
  {
136
    if (!(k instanceof RSAPublicKey))
122
    if (! (k instanceof RSAPublicKey))
137
      {
123
      throw new IllegalArgumentException();
138
        throw new IllegalArgumentException();
124
139
      }
140
    publicKey = k;
125
    publicKey = k;
141
  }
126
  }
142
127
143
  protected void setupForSigning(final PrivateKey k)
128
  protected void setupForSigning(final PrivateKey k)
144
      throws IllegalArgumentException
129
      throws IllegalArgumentException
145
  {
130
  {
146
    if (!(k instanceof RSAPrivateKey))
131
    if (! (k instanceof RSAPrivateKey))
147
      {
132
      throw new IllegalArgumentException();
148
        throw new IllegalArgumentException();
133
149
      }
150
    privateKey = k;
134
    privateKey = k;
151
  }
135
  }
152
136
153
  protected Object generateSignature() throws IllegalStateException
137
  protected Object generateSignature() throws IllegalStateException
154
  {
138
  {
155
    // 1. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
139
    // 1. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
156
    //    operation (Section 9.2) to the message M to produce an encoded
140
    // operation (Section 9.2) to the message M to produce an encoded
157
    //    message EM of length k octets:
141
    // message EM of length k octets:
158
    //
142
    //
159
    //    EM = EMSA-PKCS1-V1_5-ENCODE (M, k).
143
    // EM = EMSA-PKCS1-V1_5-ENCODE (M, k).
160
    //
144
    //
161
    //    If the encoding operation outputs "message too long," output
145
    // If the encoding operation outputs "message too long," output
162
    //    "message too long" and stop.  If the encoding operation outputs
146
    // "message too long" and stop. If the encoding operation outputs
163
    //    "intended encoded message length too short," output "RSA modulus
147
    // "intended encoded message length too short," output "RSA modulus
164
    //    too short" and stop.
148
    // too short" and stop.
165
    final int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
149
    final int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
166
    final int k = (modBits + 7) / 8;
150
    final int k = (modBits + 7) / 8;
167
    final byte[] EM = pkcs1.encode(md.digest(), k);
151
    final byte[] EM = pkcs1.encode(md.digest(), k);
168
169
    // 2. RSA signature:
152
    // 2. RSA signature:
170
    //    a. Convert the encoded message EM to an integer message epresentative
153
    // a. Convert the encoded message EM to an integer message epresentative
171
    //       m (see Section 4.2):  m = OS2IP (EM).
154
    // m (see Section 4.2): m = OS2IP (EM).
172
    final BigInteger m = new BigInteger(1, EM);
155
    final BigInteger m = new BigInteger(1, EM);
173
    //    b. Apply the RSASP1 signature primitive (Section 5.2.1) to the RSA
156
    // b. Apply the RSASP1 signature primitive (Section 5.2.1) to the RSA
174
    //       private key K and the message representative m to produce an
157
    // private key K and the message representative m to produce an
175
    //       integer signature representative s:  s = RSASP1 (K, m).
158
    // integer signature representative s: s = RSASP1 (K, m).
176
    final BigInteger s = RSA.sign(privateKey, m);
159
    final BigInteger s = RSA.sign(privateKey, m);
177
    //    c. Convert the signature representative s to a signature S of length
160
    // c. Convert the signature representative s to a signature S of length
178
    //       k octets (see Section 4.1):  S = I2OSP (s, k).
161
    // k octets (see Section 4.1): S = I2OSP (s, k).
179
    // 3. Output the signature S.
162
    // 3. Output the signature S.
180
    return RSA.I2OSP(s, k);
163
    return RSA.I2OSP(s, k);
181
  }
164
  }
Lines 184-211 Link Here
184
      throws IllegalStateException
167
      throws IllegalStateException
185
  {
168
  {
186
    if (publicKey == null)
169
    if (publicKey == null)
187
      {
170
      throw new IllegalStateException();
188
        throw new IllegalStateException();
189
      }
190
    final byte[] S = (byte[]) sig;
171
    final byte[] S = (byte[]) sig;
191
    // 1. Length checking: If the length of the signature S is not k octets,
172
    // 1. Length checking: If the length of the signature S is not k octets,
192
    //    output "invalid signature" and stop.
173
    // output "invalid signature" and stop.
193
    final int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
174
    final int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
194
    final int k = (modBits + 7) / 8;
175
    final int k = (modBits + 7) / 8;
195
    if (S.length != k)
176
    if (S.length != k)
196
      {
177
      return false;
197
        return false;
198
      }
199
    // 2. RSA verification:
178
    // 2. RSA verification:
200
    //    a. Convert the signature S to an integer signature representative
179
    // a. Convert the signature S to an integer signature representative
201
    //       s (see Section 4.2): s = OS2IP (S).
180
    // s (see Section 4.2): s = OS2IP (S).
202
    final BigInteger s = new BigInteger(1, S);
181
    final BigInteger s = new BigInteger(1, S);
203
    //    b. Apply the RSAVP1 verification primitive (Section 5.2.2) to the
182
    // b. Apply the RSAVP1 verification primitive (Section 5.2.2) to the
204
    //       RSA public key (n, e) and the signature representative s to
183
    // RSA public key (n, e) and the signature representative s to
205
    //       produce an integer message representative m:
184
    // produce an integer message representative m:
206
    //          m = RSAVP1 ((n, e), s).
185
    // m = RSAVP1 ((n, e), s).
207
    //       If RSAVP1 outputs "signature representative out of range,"
186
    // If RSAVP1 outputs "signature representative out of range,"
208
    //       output "invalid signature" and stop.
187
    // output "invalid signature" and stop.
209
    final BigInteger m;
188
    final BigInteger m;
210
    try
189
    try
211
      {
190
      {
Lines 215-224 Link Here
215
      {
194
      {
216
        return false;
195
        return false;
217
      }
196
      }
218
    //    c. Convert the message representative m to an encoded message EM
197
    // c. Convert the message representative m to an encoded message EM
219
    //       of length k octets (see Section 4.1): EM = I2OSP (m, k).
198
    // of length k octets (see Section 4.1): EM = I2OSP (m, k).
220
    //       If I2OSP outputs "integer too large," output "invalid signature"
199
    // If I2OSP outputs "integer too large," output "invalid signature"
221
    //       and stop.
200
    // and stop.
222
    final byte[] EM;
201
    final byte[] EM;
223
    try
202
    try
224
      {
203
      {
Lines 229-245 Link Here
229
        return false;
208
        return false;
230
      }
209
      }
231
    // 3. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
210
    // 3. EMSA-PKCS1-v1_5 encoding: Apply the EMSA-PKCS1-v1_5 encoding
232
    //    operation (Section 9.2) to the message M to produce a second
211
    // operation (Section 9.2) to the message M to produce a second
233
    //    encoded message EM' of length k octets:
212
    // encoded message EM' of length k octets:
234
    //       EM' = EMSA-PKCS1-V1_5-ENCODE (M, k).
213
    // EM' = EMSA-PKCS1-V1_5-ENCODE (M, k).
235
    //    If the encoding operation outputs "message too long," output
214
    // If the encoding operation outputs "message too long," output
236
    //    "message too long" and stop.  If the encoding operation outputs
215
    // "message too long" and stop. If the encoding operation outputs
237
    //    "intended encoded message length too short," output "RSA modulus
216
    // "intended encoded message length too short," output "RSA modulus
238
    //    too short" and stop.
217
    // too short" and stop.
239
    final byte[] EMp = pkcs1.encode(md.digest(), k);
218
    final byte[] EMp = pkcs1.encode(md.digest(), k);
240
    // 4. Compare the encoded message EM and the second encoded message EM'.
219
    // 4. Compare the encoded message EM and the second encoded message EM'.
241
    //    If they are the same, output "valid signature"; otherwise, output
220
    // If they are the same, output "valid signature"; otherwise, output
242
    //    "invalid signature."
221
    // "invalid signature."
243
    return Arrays.equals(EM, EMp);
222
    return Arrays.equals(EM, EMp);
244
  }
223
  }
245
}
224
}
(-)sig/rsa/RSAPSSSignature.java (-127 / +58 lines)
Lines 53-89 Link Here
53
import java.util.logging.Logger;
53
import java.util.logging.Logger;
54
54
55
/**
55
/**
56
 * <p>The RSA-PSS signature scheme is a public-key encryption scheme combining
56
 * The RSA-PSS signature scheme is a public-key encryption scheme combining the
57
 * the RSA algorithm with the Probabilistic Signature Scheme (PSS) encoding
57
 * RSA algorithm with the Probabilistic Signature Scheme (PSS) encoding method.
58
 * method.</p>
58
 * <p>
59
 *
59
 * The inventors of RSA are Ronald L. Rivest, Adi Shamir, and Leonard Adleman,
60
 * <p>The inventors of RSA are Ronald L. Rivest, Adi Shamir, and Leonard Adleman,
61
 * while the inventors of the PSS encoding method are Mihir Bellare and Phillip
60
 * while the inventors of the PSS encoding method are Mihir Bellare and Phillip
62
 * Rogaway. During efforts to adopt RSA-PSS into the P1363a standards effort,
61
 * Rogaway. During efforts to adopt RSA-PSS into the P1363a standards effort,
63
 * certain adaptations to the original version of RSA-PSS were made by Mihir
62
 * certain adaptations to the original version of RSA-PSS were made by Mihir
64
 * Bellare and Phillip Rogaway and also by Burt Kaliski (the editor of IEEE
63
 * Bellare and Phillip Rogaway and also by Burt Kaliski (the editor of IEEE
65
 * P1363a) to facilitate implementation and integration into existing protocols.</p>
64
 * P1363a) to facilitate implementation and integration into existing protocols.
66
 *
65
 * <p>
67
 * <p>References:</pr>
66
 * References:
68
 * <ol>
67
 * <ol>
69
 *    <li><a href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
68
 * <li><a
70
 *    RSA-PSS Signature Scheme with Appendix, part B.</a><br>
69
 * href="http://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/rsa-pss.zip">
71
 *    Primitive specification and supporting documentation.<br>
70
 * RSA-PSS Signature Scheme with Appendix, part B.</a><br>
72
 *    Jakob Jonsson and Burt Kaliski.</li>
71
 * Primitive specification and supporting documentation.<br>
72
 * Jakob Jonsson and Burt Kaliski.</li>
73
 * </ol>
73
 * </ol>
74
 */
74
 */
75
public class RSAPSSSignature extends BaseSignature
75
public class RSAPSSSignature
76
    extends BaseSignature
76
{
77
{
77
  private static final Logger log = Logger.getLogger(RSAPSSSignature.class.getName());
78
  private static final Logger log = Logger.getLogger(RSAPSSSignature.class.getName());
79
78
  /** The underlying EMSA-PSS instance for this object. */
80
  /** The underlying EMSA-PSS instance for this object. */
79
  private EMSA_PSS pss;
81
  private EMSA_PSS pss;
80
82
81
  /** The desired length in octets of the EMSA-PSS salt. */
83
  /** The desired length in octets of the EMSA-PSS salt. */
82
  private int sLen;
84
  private int sLen;
83
85
84
  // Constructor(s)
85
  // -------------------------------------------------------------------------
86
87
  /**
86
  /**
88
   * Default 0-arguments constructor. Uses SHA-1 as the default hash and a
87
   * Default 0-arguments constructor. Uses SHA-1 as the default hash and a
89
   * 0-octet <i>salt</i>.
88
   * 0-octet <i>salt</i>.
Lines 94-103 Link Here
94
  }
93
  }
95
94
96
  /**
95
  /**
97
   * <p>Constructs an instance of this object using the designated message
96
   * Constructs an instance of this object using the designated message digest
98
   * digest algorithm as its underlying hash function, and having 0-octet
97
   * algorithm as its underlying hash function, and having 0-octet <i>salt</i>.
99
   * <i>salt</i>.</p>
98
   * 
100
   *
101
   * @param mdName the canonical name of the underlying hash function.
99
   * @param mdName the canonical name of the underlying hash function.
102
   */
100
   */
103
  public RSAPSSSignature(String mdName)
101
  public RSAPSSSignature(String mdName)
Lines 106-117 Link Here
106
  }
104
  }
107
105
108
  /**
106
  /**
109
   * <p>Constructs an instance of this object using the designated message
107
   * Constructs an instance of this object using the designated message digest
110
   * digest algorithm as its underlying hash function.</p>
108
   * algorithm as its underlying hash function.
111
   *
109
   * 
112
   * @param mdName the canonical name of the underlying hash function.
110
   * @param mdName the canonical name of the underlying hash function.
113
   * @param sLen the desired length in octets of the salt to use for encoding /
111
   * @param sLen the desired length in octets of the salt to use for encoding /
114
   * decoding signatures.
112
   *          decoding signatures.
115
   */
113
   */
116
  public RSAPSSSignature(String mdName, int sLen)
114
  public RSAPSSSignature(String mdName, int sLen)
117
  {
115
  {
Lines 137-150 Link Here
137
    this.pss = (EMSA_PSS) that.pss.clone();
135
    this.pss = (EMSA_PSS) that.pss.clone();
138
  }
136
  }
139
137
140
  // Class methods
141
  // -------------------------------------------------------------------------
142
143
  // Instance methods
144
  // -------------------------------------------------------------------------
145
146
  // Implementation of abstract methods in superclass ------------------------
147
148
  public Object clone()
138
  public Object clone()
149
  {
139
  {
150
    return new RSAPSSSignature(this);
140
    return new RSAPSSSignature(this);
Lines 153-184 Link Here
153
  protected void setupForVerification(PublicKey k)
143
  protected void setupForVerification(PublicKey k)
154
      throws IllegalArgumentException
144
      throws IllegalArgumentException
155
  {
145
  {
156
    if (!(k instanceof RSAPublicKey))
146
    if (! (k instanceof RSAPublicKey))
157
      {
147
      throw new IllegalArgumentException();
158
        throw new IllegalArgumentException();
148
159
      }
160
    publicKey = (RSAPublicKey) k;
149
    publicKey = (RSAPublicKey) k;
161
  }
150
  }
162
151
163
  protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
152
  protected void setupForSigning(PrivateKey k) throws IllegalArgumentException
164
  {
153
  {
165
    if (!(k instanceof RSAPrivateKey))
154
    if (! (k instanceof RSAPrivateKey))
166
      {
155
      throw new IllegalArgumentException();
167
        throw new IllegalArgumentException();
156
168
      }
169
    privateKey = (RSAPrivateKey) k;
157
    privateKey = (RSAPrivateKey) k;
170
  }
158
  }
171
159
172
  protected Object generateSignature() throws IllegalStateException
160
  protected Object generateSignature() throws IllegalStateException
173
  {
161
  {
174
    // 1. Apply the EMSA-PSS encoding operation to the message M to produce an
162
    // 1. Apply the EMSA-PSS encoding operation to the message M to produce an
175
    //    encoded message EM of length CEILING((modBits ? 1)/8) octets such
163
    // encoded message EM of length CEILING((modBits ? 1)/8) octets such
176
    //    that the bit length of the integer OS2IP(EM) is at most modBits ? 1:
164
    // that the bit length of the integer OS2IP(EM) is at most modBits ? 1:
177
    //    EM = EMSA-PSS-Encode(M,modBits ? 1).
165
    // EM = EMSA-PSS-Encode(M,modBits ? 1).
178
    //    Note that the octet length of EM will be one less than k if
166
    // Note that the octet length of EM will be one less than k if
179
    //    modBits ? 1 is divisible by 8. If the encoding operation outputs
167
    // modBits ? 1 is divisible by 8. If the encoding operation outputs
180
    //    'message too long' or 'encoding error,' then output 'message too
168
    // 'message too long' or 'encoding error,' then output 'message too
181
    //    long' or 'encoding error' and stop.
169
    // long' or 'encoding error' and stop.
182
    int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
170
    int modBits = ((RSAPrivateKey) privateKey).getModulus().bitLength();
183
    byte[] salt = new byte[sLen];
171
    byte[] salt = new byte[sLen];
184
    this.nextRandomBytes(salt);
172
    this.nextRandomBytes(salt);
Lines 186-229 Link Here
186
    if (Configuration.DEBUG)
174
    if (Configuration.DEBUG)
187
      log.fine("EM (sign): " + Util.toString(EM));
175
      log.fine("EM (sign): " + Util.toString(EM));
188
    // 2. Convert the encoded message EM to an integer message representative
176
    // 2. Convert the encoded message EM to an integer message representative
189
    //    m (see Section 1.2.2): m = OS2IP(EM).
177
    // m (see Section 1.2.2): m = OS2IP(EM).
190
    BigInteger m = new BigInteger(1, EM);
178
    BigInteger m = new BigInteger(1, EM);
191
    // 3. Apply the RSASP signature primitive to the public key K and the
179
    // 3. Apply the RSASP signature primitive to the public key K and the
192
    //    message representative m to produce an integer signature
180
    // message representative m to produce an integer signature
193
    //    representative s: s = RSASP(K,m).
181
    // representative s: s = RSASP(K,m).
194
    BigInteger s = RSA.sign(privateKey, m);
182
    BigInteger s = RSA.sign(privateKey, m);
195
    // 4. Convert the signature representative s to a signature S of length k
183
    // 4. Convert the signature representative s to a signature S of length k
196
    //    octets (see Section 1.2.1): S = I2OSP(s, k).
184
    // octets (see Section 1.2.1): S = I2OSP(s, k).
197
    // 5. Output the signature S.
185
    // 5. Output the signature S.
198
    int k = (modBits + 7) / 8;
186
    int k = (modBits + 7) / 8;
199
    //      return encodeSignature(s, k);
187
    // return encodeSignature(s, k);
200
    return RSA.I2OSP(s, k);
188
    return RSA.I2OSP(s, k);
201
  }
189
  }
202
190
203
  protected boolean verifySignature(Object sig) throws IllegalStateException
191
  protected boolean verifySignature(Object sig) throws IllegalStateException
204
  {
192
  {
205
    if (publicKey == null)
193
    if (publicKey == null)
206
      {
194
      throw new IllegalStateException();
207
        throw new IllegalStateException();
195
    // byte[] S = decodeSignature(sig);
208
      }
209
    //      byte[] S = decodeSignature(sig);
210
    byte[] S = (byte[]) sig;
196
    byte[] S = (byte[]) sig;
211
    // 1. If the length of the signature S is not k octets, output 'signature
197
    // 1. If the length of the signature S is not k octets, output 'signature
212
    //    invalid' and stop.
198
    // invalid' and stop.
213
    int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
199
    int modBits = ((RSAPublicKey) publicKey).getModulus().bitLength();
214
    int k = (modBits + 7) / 8;
200
    int k = (modBits + 7) / 8;
215
    if (S.length != k)
201
    if (S.length != k)
216
      {
202
      return false;
217
        return false;
218
      }
219
    // 2. Convert the signature S to an integer signature representative s:
203
    // 2. Convert the signature S to an integer signature representative s:
220
    //    s = OS2IP(S).
204
    // s = OS2IP(S).
221
    BigInteger s = new BigInteger(1, S);
205
    BigInteger s = new BigInteger(1, S);
222
    // 3. Apply the RSAVP verification primitive to the public key (n, e) and
206
    // 3. Apply the RSAVP verification primitive to the public key (n, e) and
223
    //    the signature representative s to produce an integer message
207
    // the signature representative s to produce an integer message
224
    //    representative m: m = RSAVP((n, e), s).
208
    // representative m: m = RSAVP((n, e), s).
225
    //    If RSAVP outputs 'signature representative out of range,' then
209
    // If RSAVP outputs 'signature representative out of range,' then
226
    //    output 'signature invalid' and stop.
210
    // output 'signature invalid' and stop.
227
    BigInteger m = null;
211
    BigInteger m = null;
228
    try
212
    try
229
      {
213
      {
Lines 234-253 Link Here
234
        return false;
218
        return false;
235
      }
219
      }
236
    // 4. Convert the message representative m to an encoded message EM of
220
    // 4. Convert the message representative m to an encoded message EM of
237
    //    length emLen = CEILING((modBits - 1)/8) octets, where modBits is
221
    // length emLen = CEILING((modBits - 1)/8) octets, where modBits is
238
    //    equal to the bit length of the modulus: EM = I2OSP(m, emLen).
222
    // equal to the bit length of the modulus: EM = I2OSP(m, emLen).
239
    //    Note that emLen will be one less than k if modBits - 1 is divisible
223
    // Note that emLen will be one less than k if modBits - 1 is divisible
240
    //    by 8. If I2OSP outputs 'integer too large,' then output 'signature
224
    // by 8. If I2OSP outputs 'integer too large,' then output 'signature
241
    //    invalid' and stop.
225
    // invalid' and stop.
242
    int emBits = modBits - 1;
226
    int emBits = modBits - 1;
243
    int emLen = (emBits + 7) / 8;
227
    int emLen = (emBits + 7) / 8;
244
    byte[] EM = m.toByteArray();
228
    byte[] EM = m.toByteArray();
245
    if (Configuration.DEBUG)
229
    if (Configuration.DEBUG)
246
      log.fine("EM (verify): " + Util.toString(EM));
230
      log.fine("EM (verify): " + Util.toString(EM));
247
    if (EM.length > emLen)
231
    if (EM.length > emLen)
248
      {
232
      return false;
249
        return false;
250
      }
251
    else if (EM.length < emLen)
233
    else if (EM.length < emLen)
252
      {
234
      {
253
        byte[] newEM = new byte[emLen];
235
        byte[] newEM = new byte[emLen];
Lines 255-263 Link Here
255
        EM = newEM;
237
        EM = newEM;
256
      }
238
      }
257
    // 5. Apply the EMSA-PSS decoding operation to the message M and the
239
    // 5. Apply the EMSA-PSS decoding operation to the message M and the
258
    //    encoded message EM: Result = EMSA-PSS-Decode(M, EM, emBits). If
240
    // encoded message EM: Result = EMSA-PSS-Decode(M, EM, emBits). If
259
    //    Result = 'consistent,' output 'signature verified.' Otherwise,
241
    // Result = 'consistent,' output 'signature verified.' Otherwise,
260
    //    output 'signature invalid.'
242
    // output 'signature invalid.'
261
    byte[] mHash = md.digest();
243
    byte[] mHash = md.digest();
262
    boolean result = false;
244
    boolean result = false;
263
    try
245
    try
Lines 270-324 Link Here
270
      }
252
      }
271
    return result;
253
    return result;
272
  }
254
  }
273
274
  // Other instance methods --------------------------------------------------
275
276
  /**
277
   * Converts the <i>signature representative</i> <code>s</code> to a signature
278
   * <code>S</code> of length <code>k</code> octets; i.e.
279
   * <code>S = I2OSP(s, k)</code>, where <code>k = CEILING(modBits/8)</code>.
280
   *
281
   * @param s the <i>signature representative</i>.
282
   * @param k the length of the output.
283
   * @return the signature as an octet sequence.
284
   * @exception IllegalArgumentException if the length in octets of meaningful
285
   * bytes of <code>s</code> is greater than <code>k</code>, implying that
286
   * <code>s</code> is not less than the RSA <i>modulus</i>.
287
   */
288
  //   private Object encodeSignature(BigInteger s, int k) {
289
  //      if (DEBUG && debuglevel > 8) {
290
  //         debug("s.bitLength(): "+String.valueOf(s.bitLength()));
291
  //         debug("k: "+String.valueOf(k));
292
  //      }
293
  //      byte[] result = s.toByteArray();
294
  //      if (DEBUG && debuglevel > 8) {
295
  //         debug("s: "+Util.toString(result));
296
  //         debug("s (bytes): "+String.valueOf(result.length));
297
  //      }
298
  //      if (result.length < k) {
299
  //         byte[] newResult = new byte[k];
300
  //         System.arraycopy(result, 0, newResult, k-result.length, result.length);
301
  //         result = newResult;
302
  //      } else if (result.length > k) { // leftmost extra bytes should all be 0
303
  //         int limit = result.length - k;
304
  //         for (int i = 0; i < limit; i++) {
305
  //            if (result[i] != 0x00) {
306
  //               throw new IllegalArgumentException("integer too large");
307
  //            }
308
  //         }
309
  //         byte[] newResult = new byte[k];
310
  //         System.arraycopy(result, limit, newResult, 0, k);
311
  //         result = newResult;
312
  //      }
313
  //      return result;
314
  //   }
315
  /**
316
   * Returns the output of a previously generated signature object as an octet
317
   * sequence.<p>
318
   *
319
   * @return the octet sequence <code>S</code>.
320
   */
321
  //   private byte[] decodeSignature(Object signature) {
322
  //      return (byte[]) signature;
323
  //   }
324
}
255
}
(-)sig/rsa/RSAPSSSignatureRawCodec.java (-51 / +28 lines)
Lines 44-96 Link Here
44
import java.io.ByteArrayOutputStream;
44
import java.io.ByteArrayOutputStream;
45
45
46
/**
46
/**
47
 * <p>An object that implements the {@link ISignatureCodec}
47
 * An object that implements the {@link ISignatureCodec} operations for the
48
 * operations for the <i>Raw</i> format to use with RSA-PSS signatures.</p>
48
 * <i>Raw</i> format to use with RSA-PSS signatures.
49
 */
49
 */
50
public class RSAPSSSignatureRawCodec implements ISignatureCodec
50
public class RSAPSSSignatureRawCodec
51
    implements ISignatureCodec
51
{
52
{
52
53
  // Constants and variables
54
  // -------------------------------------------------------------------------
55
56
  // Constructor(s)
57
  // -------------------------------------------------------------------------
58
59
  // implicit 0-arguments constructor
53
  // implicit 0-arguments constructor
60
54
61
  // Class methods
62
  // -------------------------------------------------------------------------
63
64
  // gnu.crypto.keys.IKeyPairCodec interface implementation
65
  // -------------------------------------------------------------------------
66
67
  public int getFormatID()
55
  public int getFormatID()
68
  {
56
  {
69
    return RAW_FORMAT;
57
    return RAW_FORMAT;
70
  }
58
  }
71
59
72
  /**
60
  /**
73
   * <p>Returns the encoded form of the designated RSA-PSS signature object
61
   * Returns the encoded form of the designated RSA-PSS signature object
74
   * according to the <i>Raw</i> format supported by this library.</p>
62
   * according to the <i>Raw</i> format supported by this library.
75
   *
63
   * <p>
76
   * <p>The <i>Raw</i> format for an RSA-PSS signature, in this implementation,
64
   * The <i>Raw</i> format for an RSA-PSS signature, in this implementation, is
77
   * is a byte sequence consisting of the following:</p>
65
   * a byte sequence consisting of the following:
78
   *
79
   * <ol>
66
   * <ol>
80
   *		<li>4-byte magic consisting of the value of the literal
67
   * <li>4-byte magic consisting of the value of the literal
81
   *    {@link Registry#MAGIC_RAW_RSA_PSS_SIGNATURE},<li>
68
   * {@link Registry#MAGIC_RAW_RSA_PSS_SIGNATURE},
82
   *		<li>1-byte version consisting of the constant: 0x01,</li>
69
   * <li>
83
   *		<li>4-byte count of following bytes representing the RSA-PSS signature
70
   * <li>1-byte version consisting of the constant: 0x01,</li>
84
   *    bytes in internet order,</li>
71
   * <li>4-byte count of following bytes representing the RSA-PSS signature
85
   *		<li>the RSA-PSS signature bytes in internet order.</li>
72
   * bytes in internet order,</li>
73
   * <li>the RSA-PSS signature bytes in internet order.</li>
86
   * </ol>
74
   * </ol>
87
   *
75
   * 
88
   * @param signature the signature to encode, consisting of the output of the
76
   * @param signature the signature to encode, consisting of the output of the
89
   * <code>sign()</code> method of a {@link RSAPSSSignature} instance --a byte
77
   *          <code>sign()</code> method of a {@link RSAPSSSignature} instance
90
   * array.
78
   *          --a byte array.
91
   * @return the <i>Raw</i> format encoding of the designated signature.
79
   * @return the <i>Raw</i> format encoding of the designated signature.
92
   * @exception IllegalArgumentException if the designated signature is not an
80
   * @exception IllegalArgumentException if the designated signature is not an
93
   * RSA-PSS one.
81
   *              RSA-PSS one.
94
   */
82
   */
95
  public byte[] encodeSignature(Object signature)
83
  public byte[] encodeSignature(Object signature)
96
  {
84
  {
Lines 101-128 Link Here
101
      }
89
      }
102
    catch (Exception x)
90
    catch (Exception x)
103
      {
91
      {
104
        throw new IllegalArgumentException("key");
92
        throw new IllegalArgumentException("signature");
105
      }
93
      }
106
107
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
94
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
108
109
    // magic
95
    // magic
110
    baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[0]);
96
    baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[0]);
111
    baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]);
97
    baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]);
112
    baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]);
98
    baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]);
113
    baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3]);
99
    baos.write(Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3]);
114
115
    // version
100
    // version
116
    baos.write(0x01);
101
    baos.write(0x01);
117
118
    // signature bytes
102
    // signature bytes
119
    int length = buffer.length;
103
    int length = buffer.length;
120
    baos.write(length >>> 24);
104
    baos.write( length >>> 24);
121
    baos.write((length >>> 16) & 0xFF);
105
    baos.write((length >>> 16) & 0xFF);
122
    baos.write((length >>> 8) & 0xFF);
106
    baos.write((length >>> 8) & 0xFF);
123
    baos.write(length & 0xFF);
107
    baos.write(length & 0xFF);
124
    baos.write(buffer, 0, length);
108
    baos.write(buffer, 0, length);
125
126
    return baos.toByteArray();
109
    return baos.toByteArray();
127
  }
110
  }
128
111
Lines 133-157 Link Here
133
        || k[1] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]
116
        || k[1] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[1]
134
        || k[2] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]
117
        || k[2] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[2]
135
        || k[3] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3])
118
        || k[3] != Registry.MAGIC_RAW_RSA_PSS_SIGNATURE[3])
136
      {
119
      throw new IllegalArgumentException("magic");
137
        throw new IllegalArgumentException("magic");
138
      }
139
140
    // version
120
    // version
141
    if (k[4] != 0x01)
121
    if (k[4] != 0x01)
142
      {
122
      throw new IllegalArgumentException("version");
143
        throw new IllegalArgumentException("version");
144
      }
145
146
    int i = 5;
123
    int i = 5;
147
    int l;
124
    int l;
148
149
    // signature bytes
125
    // signature bytes
150
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
126
    l =  k[i++]         << 24
151
        | (k[i++] & 0xFF);
127
      | (k[i++] & 0xFF) << 16
128
      | (k[i++] & 0xFF) << 8
129
      | (k[i++] & 0xFF);
152
    byte[] result = new byte[l];
130
    byte[] result = new byte[l];
153
    System.arraycopy(k, i, result, 0, l);
131
    System.arraycopy(k, i, result, 0, l);
154
155
    return result;
132
    return result;
156
  }
133
  }
157
}
134
}
(-)util/Base64.java (-117 / +87 lines)
Lines 50-55 Link Here
50
public class Base64
50
public class Base64
51
{
51
{
52
  private static final Logger log = Logger.getLogger(Base64.class.getName());
52
  private static final Logger log = Logger.getLogger(Base64.class.getName());
53
53
  /** Maximum line length (76) of Base64 output. */
54
  /** Maximum line length (76) of Base64 output. */
54
  private static final int MAX_LINE_LENGTH = 76;
55
  private static final int MAX_LINE_LENGTH = 76;
55
56
Lines 64-142 Link Here
64
  private static final byte EQUALS_SIGN_ENC = -1; // equals sign in encoding
65
  private static final byte EQUALS_SIGN_ENC = -1; // equals sign in encoding
65
66
66
  /** The 64 valid Base64 values. */
67
  /** The 64 valid Base64 values. */
67
  private static final byte[] ALPHABET = { (byte) 'A', (byte) 'B', (byte) 'C',
68
  private static final byte[] ALPHABET = {
68
                                          (byte) 'D', (byte) 'E', (byte) 'F',
69
      (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
69
                                          (byte) 'G', (byte) 'H', (byte) 'I',
70
      (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L',
70
                                          (byte) 'J', (byte) 'K', (byte) 'L',
71
      (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R',
71
                                          (byte) 'M', (byte) 'N', (byte) 'O',
72
      (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X',
72
                                          (byte) 'P', (byte) 'Q', (byte) 'R',
73
      (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd',
73
                                          (byte) 'S', (byte) 'T', (byte) 'U',
74
      (byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
74
                                          (byte) 'V', (byte) 'W', (byte) 'X',
75
      (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p',
75
                                          (byte) 'Y', (byte) 'Z', (byte) 'a',
76
      (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v',
76
                                          (byte) 'b', (byte) 'c', (byte) 'd',
77
      (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', (byte) '0', (byte) '1',
77
                                          (byte) 'e', (byte) 'f', (byte) 'g',
78
      (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
78
                                          (byte) 'h', (byte) 'i', (byte) 'j',
79
      (byte) '8', (byte) '9', (byte) '+', (byte) '/'
79
                                          (byte) 'k', (byte) 'l', (byte) 'm',
80
  };
80
                                          (byte) 'n', (byte) 'o', (byte) 'p',
81
                                          (byte) 'q', (byte) 'r', (byte) 's',
82
                                          (byte) 't', (byte) 'u', (byte) 'v',
83
                                          (byte) 'w', (byte) 'x', (byte) 'y',
84
                                          (byte) 'z', (byte) '0', (byte) '1',
85
                                          (byte) '2', (byte) '3', (byte) '4',
86
                                          (byte) '5', (byte) '6', (byte) '7',
87
                                          (byte) '8', (byte) '9', (byte) '+',
88
                                          (byte) '/' };
89
81
90
  /**
82
  /**
91
   * Translates a Base64 value to either its 6-bit reconstruction value or a
83
   * Translates a Base64 value to either its 6-bit reconstruction value or a
92
   * negative number indicating some other meaning.
84
   * negative number indicating some other meaning.
93
   */
85
   */
94
  private static final byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal  0 -  8
86
  private static final byte[] DECODABET = {
95
                                           -5, -5, // Whitespace: Tab and Linefeed
87
      -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 0 - 8
96
                                           -9, -9, // Decimal 11 - 12
88
      -5, -5, // Whitespace: Tab and Linefeed
97
                                           -5, // Whitespace: Carriage Return
89
      -9, -9, // Decimal 11 - 12
98
                                           -9, -9, -9, -9, -9, -9, -9, -9, -9,
90
      -5, // Whitespace: Carriage Return
99
                                           -9, -9, -9, -9, // Decimal 14 - 26
91
      -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 14 - 26
100
                                           -9, -9, -9, -9, -9, // Decimal 27 - 31
92
      -9, -9, -9, -9, -9, // Decimal 27 - 31
101
                                           -5, // Whitespace: Space
93
      -5, // Whitespace: Space
102
                                           -9, -9, -9, -9, -9, -9, -9, -9, -9,
94
      -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, // Decimal 33 - 42
103
                                           -9, // Decimal 33 - 42
95
      62, // Plus sign at decimal 43
104
                                           62, // Plus sign at decimal 43
96
      -9, -9, -9, // Decimal 44 - 46
105
                                           -9, -9, -9, // Decimal 44 - 46
97
      63, // Slash at decimal 47
106
                                           63, // Slash at decimal 47
98
      52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // Numbers zero through nine
107
                                           52, 53, 54, 55, 56, 57, 58, 59, 60,
99
      -9, -9, -9, // Decimal 58 - 60
108
                                           61, // Numbers zero through nine
100
      -1, // Equals sign at decimal 61
109
                                           -9, -9, -9, // Decimal 58 - 60
101
      -9, -9, -9, // Decimal 62 - 64
110
                                           -1, // Equals sign at decimal 61
102
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, // Letters 'A' through 'N'
111
                                           -9, -9, -9, // Decimal 62 - 64
103
      14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // Letters 'O' through 'Z'
112
                                           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
104
      -9, -9, -9, -9, -9, -9, // Decimal 91 - 96
113
                                           11, 12, 13, // Letters 'A' through 'N'
105
      26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // Letters 'a' through 'm'
114
                                           14, 15, 16, 17, 18, 19, 20, 21, 22,
106
      39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // Letters 'n' through 'z'
115
                                           23, 24, 25, // Letters 'O' through 'Z'
107
      -9, -9, -9, -9 // Decimal 123 - 126
116
                                           -9, -9, -9, -9, -9, -9, // Decimal 91 - 96
117
                                           26, 27, 28, 29, 30, 31, 32, 33, 34,
118
                                           35, 36, 37, 38, // Letters 'a' through 'm'
119
                                           39, 40, 41, 42, 43, 44, 45, 46, 47,
120
                                           48, 49, 50, 51, // Letters 'n' through 'z'
121
                                           -9, -9, -9, -9 // Decimal 123 - 126
122
  };
108
  };
123
109
124
  // Constructor(s)
125
  // -------------------------------------------------------------------------
126
127
  /** Trivial private ctor to enfore Singleton pattern. */
110
  /** Trivial private ctor to enfore Singleton pattern. */
128
  private Base64()
111
  private Base64()
129
  {
112
  {
130
    super();
113
    super();
131
  }
114
  }
132
115
133
  // Class methods
134
  // -------------------------------------------------------------------------
135
136
  /**
116
  /**
137
   * Encodes a byte array into Base64 notation. Equivalent to calling
117
   * Encodes a byte array into Base64 notation. Equivalent to calling
138
   * <code>encode(source, 0, source.length)</code>.
118
   * <code>encode(source, 0, source.length)</code>.
139
   *
119
   * 
140
   * @param src the data to convert.
120
   * @param src the data to convert.
141
   */
121
   */
142
  public static final String encode(final byte[] src)
122
  public static final String encode(final byte[] src)
Lines 146-152 Link Here
146
126
147
  /**
127
  /**
148
   * Encodes a byte array into Base64 notation.
128
   * Encodes a byte array into Base64 notation.
149
   *
129
   * 
150
   * @param src the data to convert.
130
   * @param src the data to convert.
151
   * @param off offset in array where conversion should begin.
131
   * @param off offset in array where conversion should begin.
152
   * @param len length of data to convert.
132
   * @param len length of data to convert.
Lines 159-165 Link Here
159
    final byte[] outBuff = new byte[len43 // Main 4:3
139
    final byte[] outBuff = new byte[len43 // Main 4:3
160
                                    + ((len % 3) > 0 ? 4 : 0) // Account for padding
140
                                    + ((len % 3) > 0 ? 4 : 0) // Account for padding
161
                                    + (breakLines ? (len43 / MAX_LINE_LENGTH)
141
                                    + (breakLines ? (len43 / MAX_LINE_LENGTH)
162
                                                 : 0)]; // New lines
142
                                                  : 0)]; // New lines
163
    int d = 0;
143
    int d = 0;
164
    int e = 0;
144
    int e = 0;
165
    final int len2 = len - 2;
145
    final int len2 = len - 2;
Lines 175-187 Link Here
175
            lineLength = 0;
155
            lineLength = 0;
176
          }
156
          }
177
      }
157
      }
178
158
    if (d < len) // padding needed
179
    if (d < len)
159
      {
180
      { // padding needed
181
        encode3to4(src, d + off, len - d, outBuff, e);
160
        encode3to4(src, d + off, len - d, outBuff, e);
182
        e += 4;
161
        e += 4;
183
      }
162
      }
184
185
    return new String(outBuff, 0, e);
163
    return new String(outBuff, 0, e);
186
  }
164
  }
187
165
Lines 238-268 Link Here
238
                  } // end if: quartet built
216
                  } // end if: quartet built
239
              } // end if: equals sign or better
217
              } // end if: equals sign or better
240
          }
218
          }
241
        else
219
        throw new IllegalArgumentException("Illegal BASE-64 character at #"
242
          {
220
                                           + i + ": " + src[i] + "(decimal)");
243
            throw new IllegalArgumentException("Illegal BASE-64 character at #"
244
                                               + i + ": " + src[i]
245
                                               + "(decimal)");
246
          }
247
      }
221
      }
248
249
    final byte[] result = new byte[outBuffPosn];
222
    final byte[] result = new byte[outBuffPosn];
250
    System.arraycopy(outBuff, 0, result, 0, outBuffPosn);
223
    System.arraycopy(outBuff, 0, result, 0, outBuffPosn);
251
    return result;
224
    return result;
252
  }
225
  }
253
226
254
  /**
227
  /**
255
   * <p>Encodes up to three bytes of the array <code>src</code> and writes
228
   * Encodes up to three bytes of the array <code>src</code> and writes the
256
   * the resulting four Base64 bytes to <code>dest</code>. The source and
229
   * resulting four Base64 bytes to <code>dest</code>. The source and
257
   * destination arrays can be manipulated anywhere along their length by
230
   * destination arrays can be manipulated anywhere along their length by
258
   * specifying <code>sOffset</code> and <code>dOffset</code>.</p>
231
   * specifying <code>sOffset</code> and <code>dOffset</code>.
259
   *
232
   * <p>
260
   * <p>This method does not check to make sure the arrays are large enough to
233
   * This method does not check to make sure the arrays are large enough to
261
   * accomodate <code>sOffset + 3</code> for the <code>src</code> array or
234
   * accomodate <code>sOffset + 3</code> for the <code>src</code> array or
262
   * <code>dOffset + 4</code> for the <code>dest</code> array. The actual
235
   * <code>dOffset + 4</code> for the <code>dest</code> array. The actual
263
   * number of significant bytes in the input array is given by
236
   * number of significant bytes in the input array is given by
264
   * <code>numBytes</code>.</p>
237
   * <code>numBytes</code>.
265
   *
238
   * 
266
   * @param src the array to convert.
239
   * @param src the array to convert.
267
   * @param sOffset the index where conversion begins.
240
   * @param sOffset the index where conversion begins.
268
   * @param numBytes the number of significant bytes in your array.
241
   * @param numBytes the number of significant bytes in your array.
Lines 285-309 Link Here
285
    // significant bytes passed in the array.
258
    // significant bytes passed in the array.
286
    // We have to shift left 24 in order to flush out the 1's that appear
259
    // We have to shift left 24 in order to flush out the 1's that appear
287
    // when Java treats a value as negative that is cast from a byte to an int.
260
    // when Java treats a value as negative that is cast from a byte to an int.
288
    final int inBuff = (numBytes > 0 ? ((src[sOffset] << 24) >>> 8) : 0)
261
    final int inBuff =   (numBytes > 0 ? ((src[sOffset]     << 24) >>>  8) : 0)
289
                       | (numBytes > 1 ? ((src[sOffset + 1] << 24) >>> 16) : 0)
262
                       | (numBytes > 1 ? ((src[sOffset + 1] << 24) >>> 16) : 0)
290
                       | (numBytes > 2 ? ((src[sOffset + 2] << 24) >>> 24) : 0);
263
                       | (numBytes > 2 ? ((src[sOffset + 2] << 24) >>> 24) : 0);
291
    switch (numBytes)
264
    switch (numBytes)
292
      {
265
      {
293
      case 3:
266
      case 3:
294
        dest[dOffset] = ALPHABET[(inBuff >>> 18)];
267
        dest[dOffset    ] = ALPHABET[(inBuff >>> 18)];
295
        dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
268
        dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
296
        dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F];
269
        dest[dOffset + 2] = ALPHABET[(inBuff >>>  6) & 0x3F];
297
        dest[dOffset + 3] = ALPHABET[(inBuff) & 0x3F];
270
        dest[dOffset + 3] = ALPHABET[(inBuff)        & 0x3F];
298
        break;
271
        break;
299
      case 2:
272
      case 2:
300
        dest[dOffset] = ALPHABET[(inBuff >>> 18)];
273
        dest[dOffset    ] = ALPHABET[(inBuff >>> 18)];
301
        dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
274
        dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
302
        dest[dOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3F];
275
        dest[dOffset + 2] = ALPHABET[(inBuff >>>  6) & 0x3F];
303
        dest[dOffset + 3] = EQUALS_SIGN;
276
        dest[dOffset + 3] = EQUALS_SIGN;
304
        break;
277
        break;
305
      case 1:
278
      case 1:
306
        dest[dOffset] = ALPHABET[(inBuff >>> 18)];
279
        dest[dOffset    ] = ALPHABET[(inBuff >>> 18)];
307
        dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
280
        dest[dOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3F];
308
        dest[dOffset + 2] = EQUALS_SIGN;
281
        dest[dOffset + 2] = EQUALS_SIGN;
309
        dest[dOffset + 3] = EQUALS_SIGN;
282
        dest[dOffset + 3] = EQUALS_SIGN;
Lines 313-331 Link Here
313
  }
286
  }
314
287
315
  /**
288
  /**
316
   * <p>Decodes four bytes from array <code>src</code> and writes the
289
   * Decodes four bytes from array <code>src</code> and writes the resulting
317
   * resulting bytes (up to three of them) to <code>dest</code>.</p>
290
   * bytes (up to three of them) to <code>dest</code>.
318
   *
291
   * <p>
319
   * <p>The source and destination arrays can be manipulated anywhere along
292
   * The source and destination arrays can be manipulated anywhere along their
320
   * their length by specifying <code>sOffset</code> and <code>dOffset</code>.
293
   * length by specifying <code>sOffset</code> and <code>dOffset</code>.
321
   * </p>
294
   * <p>
322
   *
295
   * This method does not check to make sure your arrays are large enough to
323
   * <p>This method does not check to make sure your arrays are large enough
296
   * accomodate <code>sOffset + 4</code> for the <code>src</code> array or
324
   * to accomodate <code>sOffset + 4</code> for the <code>src</code> array or
325
   * <code>dOffset + 3</code> for the <code>dest</code> array. This method
297
   * <code>dOffset + 3</code> for the <code>dest</code> array. This method
326
   * returns the actual number of bytes that were converted from the Base64
298
   * returns the actual number of bytes that were converted from the Base64
327
   * encoding.</p>
299
   * encoding.
328
   *
300
   * 
329
   * @param src the array to convert.
301
   * @param src the array to convert.
330
   * @param sOffset the index where conversion begins.
302
   * @param sOffset the index where conversion begins.
331
   * @param dest the array to hold the conversion.
303
   * @param dest the array to hold the conversion.
Lines 335-366 Link Here
335
  private static final int decode4to3(final byte[] src, final int sOffset,
307
  private static final int decode4to3(final byte[] src, final int sOffset,
336
                                      final byte[] dest, final int dOffset)
308
                                      final byte[] dest, final int dOffset)
337
  {
309
  {
338
    if (src[sOffset + 2] == EQUALS_SIGN)
310
    if (src[sOffset + 2] == EQUALS_SIGN) // Example: Dk==
339
      { // Example: Dk==
311
      {
340
        final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18)
312
        final int outBuff = ((DECODABET[src[sOffset    ]] & 0xFF) << 18)
341
                            | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12);
313
                          | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12);
342
        dest[dOffset] = (byte) (outBuff >>> 16);
314
        dest[dOffset] = (byte)(outBuff >>> 16);
343
        return 1;
315
        return 1;
344
      }
316
      }
345
317
    if (src[sOffset + 3] == EQUALS_SIGN) // Example: DkL=
346
    if (src[sOffset + 3] == EQUALS_SIGN)
318
      {
347
      { // Example: DkL=
319
        final int outBuff = ((DECODABET[src[sOffset    ]] & 0xFF) << 18)
348
        final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18)
320
                          | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
349
                            | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
321
                          | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6);
350
                            | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6);
322
        dest[dOffset    ] = (byte)(outBuff >>> 16);
351
        dest[dOffset] = (byte) (outBuff >>> 16);
323
        dest[dOffset + 1] = (byte)(outBuff >>> 8);
352
        dest[dOffset + 1] = (byte) (outBuff >>> 8);
353
        return 2;
324
        return 2;
354
      }
325
      }
355
326
    try // Example: DkLE
356
    try
327
      {
357
      { // Example: DkLE
328
        final int outBuff = ((DECODABET[src[sOffset    ]] & 0xFF) << 18)
358
        final int outBuff = ((DECODABET[src[sOffset]] & 0xFF) << 18)
329
                          | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
359
                            | ((DECODABET[src[sOffset + 1]] & 0xFF) << 12)
330
                          | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6)
360
                            | ((DECODABET[src[sOffset + 2]] & 0xFF) << 6)
331
                          | ((DECODABET[src[sOffset + 3]] & 0xFF));
361
                            | ((DECODABET[src[sOffset + 3]] & 0xFF));
332
        dest[dOffset    ] = (byte)(outBuff >> 16);
362
        dest[dOffset] = (byte) (outBuff >> 16);
333
        dest[dOffset + 1] = (byte)(outBuff >> 8);
363
        dest[dOffset + 1] = (byte) (outBuff >> 8);
364
        dest[dOffset + 2] = (byte) outBuff;
334
        dest[dOffset + 2] = (byte) outBuff;
365
        return 3;
335
        return 3;
366
      }
336
      }
(-)util/ExpirableObject.java (-46 / +24 lines)
Lines 46-71 Link Here
46
46
47
/**
47
/**
48
 * The base class for objects with sensitive data that are automatically
48
 * The base class for objects with sensitive data that are automatically
49
 * destroyed after a timeout elapses. On creation, an object that extends
49
 * destroyed after a timeout elapses. On creation, an object that extends this
50
 * this class will automatically be added to a {@link Timer} object that,
50
 * class will automatically be added to a {@link Timer} object that, once a
51
 * once a timeout elapses, will automatically call the {@link
51
 * timeout elapses, will automatically call the {@link Destroyable#destroy()}
52
 * Destroyable#destroy()} method.
52
 * method.
53
 *
53
 * <p>
54
 * <p>Concrete subclasses must implement the {@link #doDestroy()} method
54
 * Concrete subclasses must implement the {@link #doDestroy()} method instead of
55
 * instead of {@link Destroyable#destroy()}; the behavior of that method
55
 * {@link Destroyable#destroy()}; the behavior of that method should match
56
 * should match exactly the behavior desired of <code>destroy()</code>.
56
 * exactly the behavior desired of <code>destroy()</code>.
57
 *
57
 * <p>
58
 * <p>Note that if a {@link DestroyFailedException} occurs when the timeout
58
 * Note that if a {@link DestroyFailedException} occurs when the timeout
59
 * expires, it will not be reported.
59
 * expires, it will not be reported.
60
 *
60
 * 
61
 * @see Destroyable
61
 * @see Destroyable
62
 */
62
 */
63
public abstract class ExpirableObject implements Destroyable
63
public abstract class ExpirableObject
64
    implements Destroyable
64
{
65
{
65
66
  // Constants and fields.
67
  // -------------------------------------------------------------------------
68
69
  /**
66
  /**
70
   * The default timeout, used in the default constructor.
67
   * The default timeout, used in the default constructor.
71
   */
68
   */
Lines 82-90 Link Here
82
   */
79
   */
83
  private final Destroyer destroyer;
80
  private final Destroyer destroyer;
84
81
85
  // Constructors.
86
  // -------------------------------------------------------------------------
87
88
  /**
82
  /**
89
   * Create a new expirable object that will expire after one hour.
83
   * Create a new expirable object that will expire after one hour.
90
   */
84
   */
Lines 94-105 Link Here
94
  }
88
  }
95
89
96
  /**
90
  /**
97
   * Create a new expirable object that will expire after the specified
91
   * Create a new expirable object that will expire after the specified timeout.
98
   * timeout.
92
   * 
99
   *
100
   * @param delay The delay before expiration.
93
   * @param delay The delay before expiration.
101
   * @throws IllegalArgumentException If <i>delay</i> is negative, or if
94
   * @throws IllegalArgumentException If <i>delay</i> is negative, or if
102
   *  <code>delay + System.currentTimeMillis()</code> is negative.
95
   *           <code>delay + System.currentTimeMillis()</code> is negative.
103
   */
96
   */
104
  protected ExpirableObject(final long delay)
97
  protected ExpirableObject(final long delay)
105
  {
98
  {
Lines 107-120 Link Here
107
    EXPIRER.schedule(destroyer, delay);
100
    EXPIRER.schedule(destroyer, delay);
108
  }
101
  }
109
102
110
  // Instance methods.
111
  // -------------------------------------------------------------------------
112
113
  /**
103
  /**
114
   * Destroys this object. This method calls {@link #doDestroy}, then, if
104
   * Destroys this object. This method calls {@link #doDestroy}, then, if no
115
   * no exception is thrown, cancels the task that would destroy this object
105
   * exception is thrown, cancels the task that would destroy this object when
116
   * when the timeout is reached.
106
   * the timeout is reached.
117
   *
107
   * 
118
   * @throws DestroyFailedException If this operation fails.
108
   * @throws DestroyFailedException If this operation fails.
119
   */
109
   */
120
  public final void destroy() throws DestroyFailedException
110
  public final void destroy() throws DestroyFailedException
Lines 126-167 Link Here
126
  /**
116
  /**
127
   * Subclasses must implement this method instead of the {@link
117
   * Subclasses must implement this method instead of the {@link
128
   * Destroyable#destroy()} method.
118
   * Destroyable#destroy()} method.
129
   *
119
   * 
130
   * @throws DestroyFailedException If this operation fails.
120
   * @throws DestroyFailedException If this operation fails.
131
   */
121
   */
132
  protected abstract void doDestroy() throws DestroyFailedException;
122
  protected abstract void doDestroy() throws DestroyFailedException;
133
123
134
  // Inner classes.
135
  // -------------------------------------------------------------------------
136
137
  /**
124
  /**
138
   * The task that destroys the target when the timeout elapses.
125
   * The task that destroys the target when the timeout elapses.
139
   */
126
   */
140
  private final class Destroyer extends TimerTask
127
  private final class Destroyer
128
      extends TimerTask
141
  {
129
  {
142
143
    // Fields.
144
    // -----------------------------------------------------------------------
145
146
    private final ExpirableObject target;
130
    private final ExpirableObject target;
147
131
148
    // Constructor.
149
    // -----------------------------------------------------------------------
150
151
    Destroyer(final ExpirableObject target)
132
    Destroyer(final ExpirableObject target)
152
    {
133
    {
153
      super();
134
      super();
154
      this.target = target;
135
      this.target = target;
155
    }
136
    }
156
137
157
    // Instance methods.
158
    // -----------------------------------------------------------------------
159
160
    public void run()
138
    public void run()
161
    {
139
    {
162
      try
140
      try
163
        {
141
        {
164
          if (!target.isDestroyed())
142
          if (! target.isDestroyed())
165
            target.doDestroy();
143
            target.doDestroy();
166
        }
144
        }
167
      catch (DestroyFailedException dfe)
145
      catch (DestroyFailedException dfe)
(-)util/PRNG.java (-23 / +8 lines)
Lines 45-71 Link Here
45
import gnu.java.security.prng.MDGenerator;
45
import gnu.java.security.prng.MDGenerator;
46
46
47
/**
47
/**
48
 * A useful hash-based (SHA) pseudo-random number generator used
48
 * A useful hash-based (SHA) pseudo-random number generator used throughout this
49
 * throughout this library.
49
 * library.
50
 * 
50
 * 
51
 * @see MDGenerator
51
 * @see MDGenerator
52
 */
52
 */
53
public class PRNG
53
public class PRNG
54
{
54
{
55
  // Constans and fields
56
  // --------------------------------------------------------------------------
57
58
  /** The underlying {@link IRandom}. */
55
  /** The underlying {@link IRandom}. */
59
  private IRandom delegate;
56
  private IRandom delegate;
60
57
61
  // Constructor(s)
62
  // --------------------------------------------------------------------------
63
64
  /**
58
  /**
65
   * Private constructor to enforce using the Factory method.
59
   * Private constructor to enforce using the Factory method.
66
   * 
60
   * 
67
   * @param delegate
61
   * @param delegate the undelying {@link IRandom} object used.
68
   *          the undelying {@link IRandom} object used.
69
   */
62
   */
70
  private PRNG(IRandom delegate)
63
  private PRNG(IRandom delegate)
71
  {
64
  {
Lines 74-82 Link Here
74
    this.delegate = delegate;
67
    this.delegate = delegate;
75
  }
68
  }
76
69
77
  // Class methods
78
  // --------------------------------------------------------------------------
79
80
  public static final PRNG getInstance()
70
  public static final PRNG getInstance()
81
  {
71
  {
82
    IRandom delegate = new MDGenerator();
72
    IRandom delegate = new MDGenerator();
Lines 86-95 Link Here
86
        // initialise it with a seed
76
        // initialise it with a seed
87
        long t = System.currentTimeMillis();
77
        long t = System.currentTimeMillis();
88
        byte[] seed = new byte[] {
78
        byte[] seed = new byte[] {
89
            (byte) (t >>> 56), (byte) (t >>> 48),
79
            (byte)(t >>> 56), (byte)(t >>> 48),
90
            (byte) (t >>> 40), (byte) (t >>> 32),
80
            (byte)(t >>> 40), (byte)(t >>> 32),
91
            (byte) (t >>> 24), (byte) (t >>> 16),
81
            (byte)(t >>> 24), (byte)(t >>> 16),
92
            (byte) (t >>>  8), (byte)  t};
82
            (byte)(t >>>  8), (byte) t };
93
        map.put(MDGenerator.SEEED, seed);
83
        map.put(MDGenerator.SEEED, seed);
94
        delegate.init(map); // default is to use SHA-1 hash
84
        delegate.init(map); // default is to use SHA-1 hash
95
      }
85
      }
Lines 97-115 Link Here
97
      {
87
      {
98
        throw new ExceptionInInitializerError(x);
88
        throw new ExceptionInInitializerError(x);
99
      }
89
      }
100
101
    return new PRNG(delegate);
90
    return new PRNG(delegate);
102
  }
91
  }
103
92
104
  // Instance methods
105
  // --------------------------------------------------------------------------
106
107
  /**
93
  /**
108
   * Completely fills the designated <code>buffer</code> with random data
94
   * Completely fills the designated <code>buffer</code> with random data
109
   * generated by the underlying delegate.
95
   * generated by the underlying delegate.
110
   * 
96
   * 
111
   * @param buffer
97
   * @param buffer the place holder of random bytes generated by the underlying
112
   *          the place holder of random bytes generated by the underlying
113
   *          delegate. On output, the contents of <code>buffer</code> are
98
   *          delegate. On output, the contents of <code>buffer</code> are
114
   *          replaced with pseudo-random data, iff the <code>buffer</code>
99
   *          replaced with pseudo-random data, iff the <code>buffer</code>
115
   *          size is not zero.
100
   *          size is not zero.
(-)util/Sequence.java (-39 / +23 lines)
Lines 44-67 Link Here
44
/**
44
/**
45
 * A monotonic sequence of integers in the finite field 2<sup>32</sup>.
45
 * A monotonic sequence of integers in the finite field 2<sup>32</sup>.
46
 */
46
 */
47
public final class Sequence extends AbstractList
47
public final class Sequence
48
    extends AbstractList
48
{
49
{
49
50
  // Field.
51
  // ------------------------------------------------------------------------
52
53
  private final Integer[] sequence;
50
  private final Integer[] sequence;
54
51
55
  // Constructor.
56
  // ------------------------------------------------------------------------
57
58
  /**
52
  /**
59
   * Create a sequence of integers from 0 to <i>end</i>, with an increment
53
   * Create a sequence of integers from 0 to <i>end</i>, with an increment of
60
   * of 1. If <i>end</i> is less than 0, then the sequence will wrap around
54
   * 1. If <i>end</i> is less than 0, then the sequence will wrap around
61
   * through all positive integers then negative integers until the end
55
   * through all positive integers then negative integers until the end value is
62
   * value is reached. Naturally, this will result in an enormous object,
56
   * reached. Naturally, this will result in an enormous object, so don't do
63
   * so don't do this.
57
   * this.
64
   *
58
   * 
65
   * @param end The ending value.
59
   * @param end The ending value.
66
   */
60
   */
67
  public Sequence(int end)
61
  public Sequence(int end)
Lines 71-80 Link Here
71
65
72
  /**
66
  /**
73
   * Create a sequence of integers from <i>start</i> to <i>end</i>, with an
67
   * Create a sequence of integers from <i>start</i> to <i>end</i>, with an
74
   * increment of 1. If <i>end</i> is less than <i>start</i>, then the sequence
68
   * increment of 1. If <i>end</i> is less than <i>start</i>, then the
75
   * will wrap around until the end value is reached. Naturally, this will
69
   * sequence will wrap around until the end value is reached. Naturally, this
76
   * result in an enormous object, so don't do this.
70
   * will result in an enormous object, so don't do this.
77
   *
71
   * 
78
   * @param start The starting value.
72
   * @param start The starting value.
79
   * @param end The ending value.
73
   * @param end The ending value.
80
   */
74
   */
Lines 88-100 Link Here
88
   * increment of <i>span</i>. If <i>end</i> is less than <i>start</i>, then
82
   * increment of <i>span</i>. If <i>end</i> is less than <i>start</i>, then
89
   * the sequence will wrap around until the end value is reached. Naturally,
83
   * the sequence will wrap around until the end value is reached. Naturally,
90
   * this will result in an enormous object, so don't do this.
84
   * this will result in an enormous object, so don't do this.
91
   *
85
   * <p>
92
   * <p><i>span</i> can be negative, resulting in a decresing sequence.
86
   * <i>span</i> can be negative, resulting in a decresing sequence.
93
   *
87
   * <p>
94
   * <p>If <i>span</i> is 0, then the sequence will contain {<i>start</i>,
88
   * If <i>span</i> is 0, then the sequence will contain {<i>start</i>,
95
   * <i>end</i>} if <i>start</i> != <i>end</i>, or just the singleton
89
   * <i>end</i>} if <i>start</i> != <i>end</i>, or just the singleton
96
   * <i>start</i> if <i>start</i> == <i>end</i>.
90
   * <i>start</i> if <i>start</i> == <i>end</i>.
97
   *
91
   * 
98
   * @param start The starting value.
92
   * @param start The starting value.
99
   * @param end The ending value.
93
   * @param end The ending value.
100
   * @param span The increment value.
94
   * @param span The increment value.
Lines 104-139 Link Here
104
    if (span == 0)
98
    if (span == 0)
105
      {
99
      {
106
        if (start != end)
100
        if (start != end)
107
          {
101
          sequence = new Integer[] { Integer.valueOf(start),
108
            sequence = new Integer[] { Integer.valueOf(start), Integer.valueOf(end) };
102
                                     Integer.valueOf(end) };
109
          }
110
        else
103
        else
111
          {
104
          sequence = new Integer[] { Integer.valueOf(start) };
112
            sequence = new Integer[] { Integer.valueOf(start) };
113
          }
114
      }
105
      }
115
    else
106
    else
116
      {
107
      {
117
        LinkedList l = new LinkedList();
108
        LinkedList l = new LinkedList();
118
        for (int i = start; i != end; i += span)
109
        for (int i = start; i != end; i += span)
119
          {
110
          l.add(Integer.valueOf(i));
120
            l.add(Integer.valueOf(i));
111
121
          }
122
        l.add(Integer.valueOf(end));
112
        l.add(Integer.valueOf(end));
123
        sequence = (Integer[]) l.toArray(new Integer[l.size()]);
113
        sequence = (Integer[]) l.toArray(new Integer[l.size()]);
124
      }
114
      }
125
  }
115
  }
126
116
127
  // Instance methods.
128
  // ------------------------------------------------------------------------
129
130
  public Object get(int index)
117
  public Object get(int index)
131
  {
118
  {
132
    if (index < 0 || index >= size())
119
    if (index < 0 || index >= size())
133
      {
120
      throw new IndexOutOfBoundsException("index=" + index + ", size=" + size());
134
        throw new IndexOutOfBoundsException("index=" + index + ", size="
135
                                            + size());
136
      }
137
    return sequence[index];
121
    return sequence[index];
138
  }
122
  }
139
123
(-)util/SimpleList.java (-32 / +16 lines)
Lines 43-66 Link Here
43
import java.util.Iterator;
43
import java.util.Iterator;
44
44