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

Collapse All | Expand All

(-)BaseKeyAgreementParty.java (-64 / +24 lines)
Lines 47-87 Link Here
47
import java.util.Map;
47
import java.util.Map;
48
48
49
/**
49
/**
50
 * <p>A base abstract class to facilitate implementations of concrete key
50
 * A base abstract class to facilitate implementations of concrete key agreement
51
 * agreement protocol handlers.</p>
51
 * protocol handlers.
52
 */
52
 */
53
public abstract class BaseKeyAgreementParty implements IKeyAgreementParty
53
public abstract class BaseKeyAgreementParty
54
    implements IKeyAgreementParty
54
{
55
{
55
56
  // Constants and variables
57
  // -------------------------------------------------------------------------
58
59
  protected static final BigInteger TWO = BigInteger.valueOf(2L);
56
  protected static final BigInteger TWO = BigInteger.valueOf(2L);
60
61
  /** The canonical name of the protocol. */
57
  /** The canonical name of the protocol. */
62
  protected String name;
58
  protected String name;
63
64
  /** Whether the instance is initialised or not. */
59
  /** Whether the instance is initialised or not. */
65
  protected boolean initialised = false;
60
  protected boolean initialised = false;
66
67
  /** The current step index of the protocol exchange. */
61
  /** The current step index of the protocol exchange. */
68
  protected int step = -1;
62
  protected int step = -1;
69
70
  /** Whether the exchange has concluded or not. */
63
  /** Whether the exchange has concluded or not. */
71
  protected boolean complete = false;
64
  protected boolean complete = false;
72
73
  /** The optional {@link SecureRandom} instance to use. */
65
  /** The optional {@link SecureRandom} instance to use. */
74
  protected SecureRandom rnd = null;
66
  protected SecureRandom rnd = null;
75
76
  /** The optional {@link IRandom} instance to use. */
67
  /** The optional {@link IRandom} instance to use. */
77
  protected IRandom irnd = null;
68
  protected IRandom irnd = null;
78
79
  /** Our default source of randomness. */
69
  /** Our default source of randomness. */
80
  private PRNG prng = null;
70
  private PRNG prng = null;
81
71
82
  // Constructor(s)
83
  // -------------------------------------------------------------------------
84
85
  protected BaseKeyAgreementParty(String name)
72
  protected BaseKeyAgreementParty(String name)
86
  {
73
  {
87
    super();
74
    super();
Lines 89-100 Link Here
89
    this.name = name;
76
    this.name = name;
90
  }
77
  }
91
78
92
  // Class methods
93
  // -------------------------------------------------------------------------
94
95
  // Instance methods
96
  // -------------------------------------------------------------------------
97
98
  public String name()
79
  public String name()
99
  {
80
  {
100
    return name;
81
    return name;
Lines 103-114 Link Here
103
  public void init(Map attributes) throws KeyAgreementException
84
  public void init(Map attributes) throws KeyAgreementException
104
  {
85
  {
105
    if (initialised)
86
    if (initialised)
106
      {
87
      throw new IllegalStateException("already initialised");
107
        throw new IllegalStateException("already initialised");
108
      }
109
110
    this.engineInit(attributes);
88
    this.engineInit(attributes);
111
112
    initialised = true;
89
    initialised = true;
113
    this.step = -1;
90
    this.step = -1;
114
    this.complete = false;
91
    this.complete = false;
Lines 117-131 Link Here
117
  public OutgoingMessage processMessage(IncomingMessage in)
94
  public OutgoingMessage processMessage(IncomingMessage in)
118
      throws KeyAgreementException
95
      throws KeyAgreementException
119
  {
96
  {
120
    if (!initialised)
97
    if (! initialised)
121
      {
98
      throw new IllegalStateException("not initialised");
122
        throw new IllegalStateException("not initialised");
123
      }
124
    if (complete)
99
    if (complete)
125
      {
100
      throw new IllegalStateException("exchange has already concluded");
126
        throw new IllegalStateException("exchange has already concluded");
127
      }
128
129
    step++;
101
    step++;
130
    return this.engineProcessMessage(in);
102
    return this.engineProcessMessage(in);
131
  }
103
  }
Lines 137-150 Link Here
137
109
138
  public byte[] getSharedSecret() throws KeyAgreementException
110
  public byte[] getSharedSecret() throws KeyAgreementException
139
  {
111
  {
140
    if (!initialised)
112
    if (! initialised)
141
      {
113
      throw new KeyAgreementException("not yet initialised");
142
        throw new KeyAgreementException("not yet initialised");
114
    if (! isComplete())
143
      }
115
      throw new KeyAgreementException("not yet computed");
144
    if (!isComplete())
145
      {
146
        throw new KeyAgreementException("not yet computed");
147
      }
148
    return engineSharedSecret();
116
    return engineSharedSecret();
149
  }
117
  }
150
118
Lines 157-164 Link Here
157
      }
125
      }
158
  }
126
  }
159
127
160
  // abstract methods to be implemented by concrete subclasses ---------------
161
162
  protected abstract void engineInit(Map attributes)
128
  protected abstract void engineInit(Map attributes)
163
      throws KeyAgreementException;
129
      throws KeyAgreementException;
164
130
Lines 169-199 Link Here
169
135
170
  protected abstract void engineReset();
136
  protected abstract void engineReset();
171
137
172
  // helper methods ----------------------------------------------------------
173
174
  /**
138
  /**
175
   * Fills the designated byte array with random data.
139
   * Fills the designated byte array with random data.
176
   *
140
   * 
177
   * @param buffer the byte array to fill with random data.
141
   * @param buffer the byte array to fill with random data.
178
   */
142
   */
179
  protected void nextRandomBytes(byte[] buffer)
143
  protected void nextRandomBytes(byte[] buffer)
180
  {
144
  {
181
    if (rnd != null)
145
    if (rnd != null)
182
      {
146
      rnd.nextBytes(buffer);
183
        rnd.nextBytes(buffer);
184
      }
185
    else if (irnd != null)
147
    else if (irnd != null)
186
      {
148
      try
187
        try
149
        {
188
          {
150
          irnd.nextBytes(buffer, 0, buffer.length);
189
            irnd.nextBytes(buffer, 0, buffer.length);
151
        }
190
          }
152
      catch (LimitReachedException lre)
191
        catch (LimitReachedException lre)
153
        {
192
          {
154
          irnd = null;
193
            irnd = null;
155
          getDefaultPRNG().nextBytes(buffer);
194
            getDefaultPRNG().nextBytes(buffer);
156
        }
195
          }
196
      }
197
    else
157
    else
198
      getDefaultPRNG().nextBytes(buffer);
158
      getDefaultPRNG().nextBytes(buffer);
199
  }
159
  }
Lines 205-208 Link Here
205
165
206
    return prng;
166
    return prng;
207
  }
167
  }
208
}
168
}
(-)GnuSecretKey.java (-33 / +15 lines)
Lines 42-68 Link Here
42
import java.security.Key;
42
import java.security.Key;
43
43
44
/**
44
/**
45
 * A secret key composed of a sequence of raw, unformatted octets. This class
45
 * A secret key composed of a sequence of raw, unformatted octets. This class is
46
 * is analogous to the {@link javax.crypto.spec.SecretKeySpec} class, but is
46
 * analogous to the {@link javax.crypto.spec.SecretKeySpec} class, but is
47
 * provided for platforms that do not or cannot contain that class.
47
 * provided for platforms that do not or cannot contain that class.
48
 */
48
 */
49
public class GnuSecretKey implements Key
49
public class GnuSecretKey
50
    implements Key
50
{
51
{
51
52
  // Field.
53
  // ------------------------------------------------------------------------
54
55
  private final byte[] key;
52
  private final byte[] key;
56
57
  private final String algorithm;
53
  private final String algorithm;
58
54
59
  // Constructors.
60
  // ------------------------------------------------------------------------
61
62
  /**
55
  /**
63
   * Creates a new secret key. The supplied byte array is copied by this
56
   * Creates a new secret key. The supplied byte array is copied by this
64
   * constructor.
57
   * constructor.
65
   *
58
   * 
66
   * @param key The raw, secret key.
59
   * @param key The raw, secret key.
67
   * @param algorithm The algorithm name, which can be null or empty.
60
   * @param algorithm The algorithm name, which can be null or empty.
68
   */
61
   */
Lines 73-79 Link Here
73
66
74
  /**
67
  /**
75
   * Creates a new secret key from a portion of a byte array.
68
   * Creates a new secret key from a portion of a byte array.
76
   *
69
   * 
77
   * @param key The raw, secret key.
70
   * @param key The raw, secret key.
78
   * @param offset The offset at which the key begins.
71
   * @param offset The offset at which the key begins.
79
   * @param length The number of bytes that comprise the key.
72
   * @param length The number of bytes that comprise the key.
Lines 86-97 Link Here
86
    this.algorithm = algorithm;
79
    this.algorithm = algorithm;
87
  }
80
  }
88
81
89
  // Instance methods.
90
  // ------------------------------------------------------------------------
91
92
  /**
82
  /**
93
   * Returns the algorithm name, if any.
83
   * Returns the algorithm name, if any.
94
   *
84
   * 
95
   * @return The algorithm name.
85
   * @return The algorithm name.
96
   */
86
   */
97
  public String getAlgorithm()
87
  public String getAlgorithm()
Lines 103-109 Link Here
103
   * Returns the encoded key, which is merely the byte array this class was
93
   * Returns the encoded key, which is merely the byte array this class was
104
   * created with. A reference to the internal byte array is returned, so the
94
   * created with. A reference to the internal byte array is returned, so the
105
   * caller can delete this key from memory by modifying the returned array.
95
   * caller can delete this key from memory by modifying the returned array.
106
   *
96
   * 
107
   * @return The raw key.
97
   * @return The raw key.
108
   */
98
   */
109
  public byte[] getEncoded()
99
  public byte[] getEncoded()
Lines 113-119 Link Here
113
103
114
  /**
104
  /**
115
   * Returns the string "RAW".
105
   * Returns the string "RAW".
116
   *
106
   * 
117
   * @return The string "RAW".
107
   * @return The string "RAW".
118
   */
108
   */
119
  public String getFormat()
109
  public String getFormat()
Lines 123-144 Link Here
123
113
124
  public boolean equals(Object o)
114
  public boolean equals(Object o)
125
  {
115
  {
126
    if (!(o instanceof GnuSecretKey))
116
    if (! (o instanceof GnuSecretKey))
127
      {
117
      return false;
128
        return false;
129
      }
130
    if (key.length != ((GnuSecretKey) o).key.length)
118
    if (key.length != ((GnuSecretKey) o).key.length)
131
      {
119
      return false;
132
        return false;
133
      }
134
    byte[] key2 = ((GnuSecretKey) o).key;
120
    byte[] key2 = ((GnuSecretKey) o).key;
135
    for (int i = 0; i < key.length; i++)
121
    for (int i = 0; i < key.length; i++)
136
      {
122
      if (key[i] != key2[i])
137
        if (key[i] != key2[i])
123
        return false;
138
          {
139
            return false;
140
          }
141
      }
142
    return true;
124
    return true;
143
  }
125
  }
144
126
Lines 146-149 Link Here
146
  {
128
  {
147
    return "GnuSecretKey [ " + algorithm + " " + Util.toString(key) + " ]";
129
    return "GnuSecretKey [ " + algorithm + " " + Util.toString(key) + " ]";
148
  }
130
  }
149
}
131
}
(-)IKeyAgreementParty.java (-24 / +19 lines)
Lines 41-105 Link Here
41
import java.util.Map;
41
import java.util.Map;
42
42
43
/**
43
/**
44
 * <p>The visible methods of an key agreement protocol participating party.</p>
44
 * The visible methods of an key agreement protocol participating party.
45
 */
45
 */
46
public interface IKeyAgreementParty
46
public interface IKeyAgreementParty
47
{
47
{
48
49
  // Constants
50
  // -------------------------------------------------------------------------
51
52
  // Methods
53
  // -------------------------------------------------------------------------
54
55
  /**
48
  /**
56
   * <p>Returns the canonical name of the key agreement protocol.</p>
49
   * Returns the canonical name of the key agreement protocol.
57
   *
50
   * 
58
   * @return the canonical name of the key agreement protocol.
51
   * @return the canonical name of the key agreement protocol.
59
   */
52
   */
60
  String name();
53
  String name();
61
54
62
  /**
55
  /**
63
   * <p>Sets up the instance to operate with specific attributes.</p>
56
   * Sets up the instance to operate with specific attributes.
64
   *
57
   * 
65
   * @param attributes a map of name-values used by concrete implementations.
58
   * @param attributes a map of name-values used by concrete implementations.
66
   * @throws KeyAgreementException if an exception occurs during the setup.
59
   * @throws KeyAgreementException if an exception occurs during the setup.
67
   */
60
   */
68
  void init(Map attributes) throws KeyAgreementException;
61
  void init(Map attributes) throws KeyAgreementException;
69
62
70
  /**
63
  /**
71
   * <p>Processes an incoming message at one end, generating a message that
64
   * Processes an incoming message at one end, generating a message that will be
72
   * will be processed by the other party(ies).</p>
65
   * processed by the other party(ies).
73
   *
66
   * 
74
   * @param in the incoming message.
67
   * @param in the incoming message.
75
   * @return an outgoing message, or <code>null</code> if this is an
68
   * @return an outgoing message, or <code>null</code> if this is an
76
   * intermediary step that does not cause any output.
69
   *         intermediary step that does not cause any output.
77
   * @throws KeyAgreementException if an exception occurs during the processing
70
   * @throws KeyAgreementException if an exception occurs during the processing
78
   * of the incoming message, or during the generation of the outgoing message.
71
   *           of the incoming message, or during the generation of the outgoing
72
   *           message.
79
   */
73
   */
80
  OutgoingMessage processMessage(IncomingMessage in)
74
  OutgoingMessage processMessage(IncomingMessage in)
81
      throws KeyAgreementException;
75
      throws KeyAgreementException;
82
76
83
  /**
77
  /**
84
   * <p>Returns <code>true</code> if the party in the key agreement protocol
78
   * Returns <code>true</code> if the party in the key agreement protocol
85
   * exchange has completed its part of the exchange. If this is the case an
79
   * exchange has completed its part of the exchange. If this is the case an
86
   * {@link IllegalStateException} is thrown for any method invocation except
80
   * {@link IllegalStateException} is thrown for any method invocation except
87
   * <code>init()</code> or <code>reset()</code>.
81
   * <code>init()</code> or <code>reset()</code>.
82
   * 
88
   * @return <code>true</code> if this party has completed its part of the key
83
   * @return <code>true</code> if this party has completed its part of the key
89
   * agreement protocol exchange; <code>false</code> otherwise.
84
   *         agreement protocol exchange; <code>false</code> otherwise.
90
   */
85
   */
91
  boolean isComplete();
86
  boolean isComplete();
92
87
93
  /**
88
  /**
94
   * <p>Returns the byte array containing the shared secret as generated by
89
   * Returns the byte array containing the shared secret as generated by this
95
   * this party.</p>
90
   * party.
96
   *
91
   * 
97
   * @return the generated shared secret.
92
   * @return the generated shared secret.
98
   * @throws KeyAgreementException if the key agreement is not yet initialised,
93
   * @throws KeyAgreementException if the key agreement is not yet initialised,
99
   * or is initialised but the exchange is still in progress.
94
   *           or is initialised but the exchange is still in progress.
100
   */
95
   */
101
  byte[] getSharedSecret() throws KeyAgreementException;
96
  byte[] getSharedSecret() throws KeyAgreementException;
102
97
103
  /** Resets this instance for re-use with another set of attributes. */
98
  /** Resets this instance for re-use with another set of attributes. */
104
  void reset();
99
  void reset();
105
}
100
}
(-)IncomingMessage.java (-76 / +38 lines)
Lines 58-87 Link Here
58
import java.security.PublicKey;
58
import java.security.PublicKey;
59
59
60
/**
60
/**
61
 * <p>An implementation of an incoming message for use with key agreement
61
 * An implementation of an incoming message for use with key agreement
62
 * protocols.</p>
62
 * protocols.
63
 */
63
 */
64
public class IncomingMessage
64
public class IncomingMessage
65
{
65
{
66
67
  // Constants and variables
68
  // -------------------------------------------------------------------------
69
70
  /** The internal buffer stream containing the message's contents. */
66
  /** The internal buffer stream containing the message's contents. */
71
  protected ByteArrayInputStream in;
67
  protected ByteArrayInputStream in;
72
73
  /** The length of the message contents, according to its 4-byte header. */
68
  /** The length of the message contents, according to its 4-byte header. */
74
  protected int length;
69
  protected int length;
75
70
76
  // Constructor(s)
77
  // -------------------------------------------------------------------------
78
79
  /**
71
  /**
80
   * <p>Constructs an incoming message given the message's encoded form,
72
   * Constructs an incoming message given the message's encoded form, including
81
   * including its header bytes.</p>
73
   * its header bytes.
82
   *
74
   * 
83
   * @param b the encoded form, including the header bytes, of an incoming
75
   * @param b the encoded form, including the header bytes, of an incoming
84
   * message.
76
   *          message.
85
   * @throws KeyAgreementException if the buffer is malformed.
77
   * @throws KeyAgreementException if the buffer is malformed.
86
   */
78
   */
87
  public IncomingMessage(byte[] b) throws KeyAgreementException
79
  public IncomingMessage(byte[] b) throws KeyAgreementException
Lines 89-103 Link Here
89
    this();
81
    this();
90
82
91
    if (b.length < 4)
83
    if (b.length < 4)
92
      {
84
      throw new KeyAgreementException("message header too short");
93
        throw new KeyAgreementException("message header too short");
85
    length =  b[0]         << 24
94
      }
86
           | (b[1] & 0xFF) << 16
95
    length = b[0] << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8
87
           | (b[2] & 0xFF) << 8
96
             | (b[3] & 0xFF);
88
           | (b[3] & 0xFF);
97
    if (length > Registry.SASL_BUFFER_MAX_LIMIT || length < 0)
89
    if (length > Registry.SASL_BUFFER_MAX_LIMIT || length < 0)
98
      {
90
      throw new KeyAgreementException("message size limit exceeded");
99
        throw new KeyAgreementException("message size limit exceeded");
100
      }
101
    in = new ByteArrayInputStream(b, 4, length);
91
    in = new ByteArrayInputStream(b, 4, length);
102
  }
92
  }
103
93
Lines 107-122 Link Here
107
    super();
97
    super();
108
  }
98
  }
109
99
110
  // Class methods
111
  // -------------------------------------------------------------------------
112
113
  /**
100
  /**
114
   * <p>Returns an instance of a message given its encoded contents, excluding
101
   * Returns an instance of a message given its encoded contents, excluding the
115
   * the message's header bytes.</p>
102
   * message's header bytes.
116
   *
103
   * <p>
117
   * <p>Calls the method with the same name and three arguments as:
104
   * Calls the method with the same name and three arguments as:
118
   * <code>getInstance(raw, 0, raw.length)</code>.
105
   * <code>getInstance(raw, 0, raw.length)</code>.
119
   *
106
   * 
120
   * @param raw the encoded form, excluding the header bytes.
107
   * @param raw the encoded form, excluding the header bytes.
121
   * @return a new instance of <code>IncomingMessage</code>.
108
   * @return a new instance of <code>IncomingMessage</code>.
122
   */
109
   */
Lines 126-134 Link Here
126
  }
113
  }
127
114
128
  /**
115
  /**
129
   * <p>Returns an instance of a message given its encoded contents, excluding
116
   * Returns an instance of a message given its encoded contents, excluding the
130
   * the message's header bytes.</p>
117
   * message's header bytes.
131
   *
118
   * 
132
   * @param raw the encoded form, excluding the header bytes.
119
   * @param raw the encoded form, excluding the header bytes.
133
   * @param offset offset where to start using raw bytes from.
120
   * @param offset offset where to start using raw bytes from.
134
   * @param len number of bytes to use.
121
   * @param len number of bytes to use.
Lines 142-149 Link Here
142
  }
129
  }
143
130
144
  /**
131
  /**
145
   * <p>Converts two octets into the number that they represent.</p>
132
   * Converts two octets into the number that they represent.
146
   *
133
   * 
147
   * @param b the two octets.
134
   * @param b the two octets.
148
   * @return the length.
135
   * @return the length.
149
   */
136
   */
Lines 151-182 Link Here
151
  {
138
  {
152
    int result = (b[0] & 0xFF) << 8 | (b[1] & 0xFF);
139
    int result = (b[0] & 0xFF) << 8 | (b[1] & 0xFF);
153
    if (result > Registry.SASL_TWO_BYTE_MAX_LIMIT)
140
    if (result > Registry.SASL_TWO_BYTE_MAX_LIMIT)
154
      {
141
      throw new KeyAgreementException("encoded MPI size limit exceeded");
155
        throw new KeyAgreementException("encoded MPI size limit exceeded");
156
      }
157
    return result;
142
    return result;
158
  }
143
  }
159
144
160
  /**
145
  /**
161
   * <p>Converts four octets into the number that they represent.</p>
146
   * Converts four octets into the number that they represent.
162
   *
147
   * 
163
   * @param b the four octets.
148
   * @param b the four octets.
164
   * @return the length.
149
   * @return the length.
165
   */
150
   */
166
  public static int fourBytesToLength(byte[] b) throws KeyAgreementException
151
  public static int fourBytesToLength(byte[] b) throws KeyAgreementException
167
  {
152
  {
168
    int result = b[0] << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8
153
    int result =  b[0]         << 24
169
                 | (b[3] & 0xFF);
154
               | (b[1] & 0xFF) << 16
155
               | (b[2] & 0xFF) << 8
156
               | (b[3] & 0xFF);
170
    if (result > Registry.SASL_FOUR_BYTE_MAX_LIMIT || result < 0)
157
    if (result > Registry.SASL_FOUR_BYTE_MAX_LIMIT || result < 0)
171
      {
158
      throw new KeyAgreementException("encoded entity size limit exceeded");
172
        throw new KeyAgreementException("encoded entity size limit exceeded");
173
      }
174
    return result;
159
    return result;
175
  }
160
  }
176
161
177
  // Instance methods
178
  // -------------------------------------------------------------------------
179
180
  public boolean hasMoreElements()
162
  public boolean hasMoreElements()
181
  {
163
  {
182
    return (in.available() > 0);
164
    return (in.available() > 0);
Lines 195-212 Link Here
195
  {
177
  {
196
    if (in.available() < 5)
178
    if (in.available() < 5)
197
      throw new KeyAgreementException("not enough bytes for a public key in message");
179
      throw new KeyAgreementException("not enough bytes for a public key in message");
198
199
    byte[] elementLengthBytes = new byte[4];
180
    byte[] elementLengthBytes = new byte[4];
200
    in.read(elementLengthBytes, 0, 4);
181
    in.read(elementLengthBytes, 0, 4);
201
    int elementLength = fourBytesToLength(elementLengthBytes);
182
    int elementLength = fourBytesToLength(elementLengthBytes);
202
    if (in.available() < elementLength)
183
    if (in.available() < elementLength)
203
      throw new KeyAgreementException("illegal public key encoding");
184
      throw new KeyAgreementException("illegal public key encoding");
204
205
    int keyTypeAndFormatID = in.read() & 0xFF;
185
    int keyTypeAndFormatID = in.read() & 0xFF;
206
    elementLength--;
186
    elementLength--;
207
    byte[] kb = new byte[elementLength];
187
    byte[] kb = new byte[elementLength];
208
    in.read(kb, 0, elementLength);
188
    in.read(kb, 0, elementLength);
209
210
    // instantiate the right codec and decode
189
    // instantiate the right codec and decode
211
    IKeyPairCodec kpc = getKeyPairCodec(keyTypeAndFormatID);
190
    IKeyPairCodec kpc = getKeyPairCodec(keyTypeAndFormatID);
212
    return kpc.decodePublicKey(kb);
191
    return kpc.decodePublicKey(kb);
Lines 225-290 Link Here
225
  {
204
  {
226
    if (in.available() < 5)
205
    if (in.available() < 5)
227
      throw new KeyAgreementException("not enough bytes for a private key in message");
206
      throw new KeyAgreementException("not enough bytes for a private key in message");
228
229
    byte[] elementLengthBytes = new byte[4];
207
    byte[] elementLengthBytes = new byte[4];
230
    in.read(elementLengthBytes, 0, 4);
208
    in.read(elementLengthBytes, 0, 4);
231
    int elementLength = fourBytesToLength(elementLengthBytes);
209
    int elementLength = fourBytesToLength(elementLengthBytes);
232
    if (in.available() < elementLength)
210
    if (in.available() < elementLength)
233
      throw new KeyAgreementException("illegal private key encoding");
211
      throw new KeyAgreementException("illegal private key encoding");
234
235
    int keyTypeAndFormatID = in.read() & 0xFF;
212
    int keyTypeAndFormatID = in.read() & 0xFF;
236
    elementLength--;
213
    elementLength--;
237
    byte[] kb = new byte[elementLength];
214
    byte[] kb = new byte[elementLength];
238
    in.read(kb, 0, elementLength);
215
    in.read(kb, 0, elementLength);
239
240
    // instantiate the right codec and decode
216
    // instantiate the right codec and decode
241
    IKeyPairCodec kpc = getKeyPairCodec(keyTypeAndFormatID);
217
    IKeyPairCodec kpc = getKeyPairCodec(keyTypeAndFormatID);
242
    return kpc.decodePrivateKey(kb);
218
    return kpc.decodePrivateKey(kb);
243
  }
219
  }
244
220
245
  /**
221
  /**
246
   * <p>Decodes an MPI from the current message's contents.</p>
222
   * Decodes an MPI from the current message's contents.
247
   *
223
   * 
248
   * @return a native representation of an MPI.
224
   * @return a native representation of an MPI.
249
   * @throws KeyAgreementException if an encoding exception occurs during the
225
   * @throws KeyAgreementException if an encoding exception occurs during the
250
   * operation.
226
   *           operation.
251
   */
227
   */
252
  public BigInteger readMPI() throws KeyAgreementException
228
  public BigInteger readMPI() throws KeyAgreementException
253
  {
229
  {
254
    if (in.available() < 2)
230
    if (in.available() < 2)
255
      {
231
      throw new KeyAgreementException("not enough bytes for an MPI in message");
256
        throw new KeyAgreementException(
257
                                        "not enough bytes for an MPI in message");
258
      }
259
    byte[] elementLengthBytes = new byte[2];
232
    byte[] elementLengthBytes = new byte[2];
260
    in.read(elementLengthBytes, 0, 2);
233
    in.read(elementLengthBytes, 0, 2);
261
    int elementLength = twoBytesToLength(elementLengthBytes);
234
    int elementLength = twoBytesToLength(elementLengthBytes);
262
    if (in.available() < elementLength)
235
    if (in.available() < elementLength)
263
      {
236
      throw new KeyAgreementException("illegal MPI encoding");
264
        throw new KeyAgreementException("illegal MPI encoding");
265
      }
266
267
    byte[] element = new byte[elementLength];
237
    byte[] element = new byte[elementLength];
268
    in.read(element, 0, element.length);
238
    in.read(element, 0, element.length);
269
270
    return new BigInteger(1, element);
239
    return new BigInteger(1, element);
271
  }
240
  }
272
241
273
  public String readString() throws KeyAgreementException
242
  public String readString() throws KeyAgreementException
274
  {
243
  {
275
    if (in.available() < 2)
244
    if (in.available() < 2)
276
      {
245
      throw new KeyAgreementException("not enough bytes for a text in message");
277
        throw new KeyAgreementException(
278
                                        "not enough bytes for a text in message");
279
      }
280
    byte[] elementLengthBytes = new byte[2];
246
    byte[] elementLengthBytes = new byte[2];
281
    in.read(elementLengthBytes, 0, 2);
247
    in.read(elementLengthBytes, 0, 2);
282
    int elementLength = twoBytesToLength(elementLengthBytes);
248
    int elementLength = twoBytesToLength(elementLengthBytes);
283
    if (in.available() < elementLength)
249
    if (in.available() < elementLength)
284
      {
250
      throw new KeyAgreementException("illegal text encoding");
285
        throw new KeyAgreementException("illegal text encoding");
286
      }
287
288
    byte[] element = new byte[elementLength];
251
    byte[] element = new byte[elementLength];
289
    in.read(element, 0, element.length);
252
    in.read(element, 0, element.length);
290
    String result = null;
253
    String result = null;
Lines 296-302 Link Here
296
      {
259
      {
297
        throw new KeyAgreementException("unxupported UTF8 encoding", x);
260
        throw new KeyAgreementException("unxupported UTF8 encoding", x);
298
      }
261
      }
299
300
    return result;
262
    return result;
301
  }
263
  }
302
264
Lines 353-356 Link Here
353
                                        + formatID);
315
                                        + formatID);
354
      }
316
      }
355
  }
317
  }
356
}
318
}
(-)KeyAgreementException.java (-64 / +43 lines)
Lines 44-69 Link Here
44
import java.security.KeyManagementException;
44
import java.security.KeyManagementException;
45
45
46
/**
46
/**
47
 * A generic exception indicating that an unexpected condition has
47
 * A generic exception indicating that an unexpected condition has been detected
48
 * been detected during the setup and/or processing of a key agreement
48
 * during the setup and/or processing of a key agreement protocol exchange.
49
 * protocol exchange.
50
 */
49
 */
51
public class KeyAgreementException extends KeyManagementException implements
50
public class KeyAgreementException
52
    Serializable
51
    extends KeyManagementException
52
    implements Serializable
53
{
53
{
54
55
  // Constants and variables
56
  // -------------------------------------------------------------------------
57
58
  /** @serial The possibly <code>null</code> <i>root</i> cause exception. */
54
  /** @serial The possibly <code>null</code> <i>root</i> cause exception. */
59
  private Throwable cause = null;
55
  private Throwable cause = null;
60
56
61
  // Constructor(s)
62
  // -------------------------------------------------------------------------
63
64
  /**
57
  /**
65
   * <p>Constructs a new instance of <code>KeyAgreementException</code>. The
58
   * Constructs a new instance of <code>KeyAgreementException</code>. The
66
   * root exception and the detailed message are <code>null</code>.</p>
59
   * root exception and the detailed message are <code>null</code>.
67
   */
60
   */
68
  public KeyAgreementException()
61
  public KeyAgreementException()
69
  {
62
  {
Lines 71-81 Link Here
71
  }
64
  }
72
65
73
  /**
66
  /**
74
   * <p>Constructs a new instance of <code>KeyAgreementException</code> with a
67
   * Constructs a new instance of <code>KeyAgreementException</code> with a
75
   * detailed message. The <i>root</i> exception is <code>null</code>.</p>
68
   * detailed message. The <i>root</i> exception is <code>null</code>.
76
   *
69
   * 
77
   * @param detail a possibly <code>null</code> string containing details of
70
   * @param detail a possibly <code>null</code> string containing details of
78
   * the exception.
71
   *          the exception.
79
   * @see Throwable#getMessage()
72
   * @see Throwable#getMessage()
80
   */
73
   */
81
  public KeyAgreementException(String detail)
74
  public KeyAgreementException(String detail)
Lines 84-96 Link Here
84
  }
77
  }
85
78
86
  /**
79
  /**
87
   * <p>Constructs a new instance of <code>KeyAgreementException</code> with a
80
   * Constructs a new instance of <code>KeyAgreementException</code> with a
88
   * detailed message and a <i>root</i> exception.</p>
81
   * detailed message and a <i>root</i> exception.
89
   *
82
   * 
90
   * @param detail a possibly <code>null</code> string containing details of
83
   * @param detail a possibly <code>null</code> string containing details of
91
   * the exception.
84
   *          the exception.
92
   * @param cause a possibly <code>null</code> root exception that caused this
85
   * @param cause a possibly <code>null</code> root exception that caused this
93
   * exception.
86
   *          exception.
94
   * @see Throwable#getMessage()
87
   * @see Throwable#getMessage()
95
   * @see #getCause()
88
   * @see #getCause()
96
   */
89
   */
Lines 100-116 Link Here
100
    this.cause = cause;
93
    this.cause = cause;
101
  }
94
  }
102
95
103
  // Class methods
104
  // -------------------------------------------------------------------------
105
106
  // Instance methods
107
  // -------------------------------------------------------------------------
108
109
  /**
96
  /**
110
   * <p>Returns the cause of this throwable or <code>null</code> if the cause
97
   * Returns the cause of this throwable or <code>null</code> if the cause is
111
   * is nonexistent or unknown. The <i>cause</i> is the throwable that caused
98
   * nonexistent or unknown. The <i>cause</i> is the throwable that caused this
112
   * this exception to be thrown.</p>
99
   * exception to be thrown.
113
   *
100
   * 
114
   * @return the possibly <code>null</code> exception that caused this one.
101
   * @return the possibly <code>null</code> exception that caused this one.
115
   */
102
   */
116
  public Throwable getCause()
103
  public Throwable getCause()
Lines 119-187 Link Here
119
  }
106
  }
120
107
121
  /**
108
  /**
122
   * <p>Prints this exception's stack trace to <code>System.err</code>. If this
109
   * Prints this exception's stack trace to <code>System.err</code>. If this
123
   * exception has a <i>root</i> exception; the stack trace of the <i>root</i>
110
   * exception has a <i>root</i> exception; the stack trace of the <i>root</i>
124
   * exception is also printed to <code>System.err</code>.</p>
111
   * exception is also printed to <code>System.err</code>.
125
   */
112
   */
126
  public void printStackTrace()
113
  public void printStackTrace()
127
  {
114
  {
128
    super.printStackTrace();
115
    super.printStackTrace();
129
    if (cause != null)
116
    if (cause != null)
130
      {
117
      cause.printStackTrace();
131
        cause.printStackTrace();
132
      }
133
  }
118
  }
134
119
135
  /**
120
  /**
136
   * <p>Prints this exception's stack trace to a print stream. If this
121
   * Prints this exception's stack trace to a print stream. If this exception
137
   * exception has a <i>root</i> exception; the stack trace of the <i>root</i>
122
   * has a <i>root</i> exception; the stack trace of the <i>root</i> exception
138
   * exception is also printed to the print stream.</p>
123
   * is also printed to the print stream.
139
   *
124
   * 
140
   * @param ps the non-null print stream to which to print.
125
   * @param ps the non-null print stream to which to print.
141
   */
126
   */
142
  public void printStackTrace(PrintStream ps)
127
  public void printStackTrace(PrintStream ps)
143
  {
128
  {
144
    super.printStackTrace(ps);
129
    super.printStackTrace(ps);
145
    if (cause != null)
130
    if (cause != null)
146
      {
131
      cause.printStackTrace(ps);
147
        cause.printStackTrace(ps);
148
      }
149
  }
132
  }
150
133
151
  /**
134
  /**
152
   * <p>Prints this exception's stack trace to a print writer. If this
135
   * Prints this exception's stack trace to a print writer. If this exception
153
   * exception has a <i>root</i> exception; the stack trace of the <i>root</i>
136
   * has a <i>root</i> exception; the stack trace of the <i>root</i> exception
154
   * exception is also printed to the print writer.</p>
137
   * is also printed to the print writer.
155
   *
138
   * 
156
   * @param pw the non-null print writer to use for output.
139
   * @param pw the non-null print writer to use for output.
157
   */
140
   */
158
  public void printStackTrace(PrintWriter pw)
141
  public void printStackTrace(PrintWriter pw)
159
  {
142
  {
160
    super.printStackTrace(pw);
143
    super.printStackTrace(pw);
161
    if (cause != null)
144
    if (cause != null)
162
      {
145
      cause.printStackTrace(pw);
163
        cause.printStackTrace(pw);
164
      }
165
  }
146
  }
166
147
167
  /**
148
  /**
168
   * <p>Returns the string representation of this exception. The string
149
   * Returns the string representation of this exception. The string
169
   * representation contains this exception's class name, its detailed
150
   * representation contains this exception's class name, its detailed messsage,
170
   * messsage, and if it has a <i>root</i> exception, the string representation
151
   * and if it has a <i>root</i> exception, the string representation of the
171
   * of the root exception. This string representation is meant for debugging
152
   * root exception. This string representation is meant for debugging and is
172
   * and is not meant to be interpreted programmatically.</p>
153
   * not meant to be interpreted programmatically.
173
   *
154
   * 
174
   * @return the non-null string representation of this exception.
155
   * @return the non-null string representation of this exception.
175
   * @see Throwable#getMessage()
156
   * @see Throwable#getMessage()
176
   */
157
   */
177
  public String toString()
158
  public String toString()
178
  {
159
  {
179
    StringBuffer sb = new StringBuffer(this.getClass().getName()).append(": ").append(
160
    StringBuffer sb = new StringBuffer(this.getClass().getName()).append(": ")
180
                                                                                      super.toString());
161
        .append(super.toString());
181
    if (cause != null)
162
    if (cause != null)
182
      {
163
      sb.append("; caused by: ").append(cause.toString());
183
        sb.append("; caused by: ").append(cause.toString());
184
      }
185
    return sb.toString();
164
    return sb.toString();
186
  }
165
  }
187
}
166
}
(-)KeyAgreementFactory.java (-63 / +25 lines)
Lines 56-170 Link Here
56
import java.util.Set;
56
import java.util.Set;
57
57
58
/**
58
/**
59
 * <p>A <i>Factory</i> class to generate key agreement protocol handlers.</p>
59
 * A <i>Factory</i> class to generate key agreement protocol handlers.
60
 */
60
 */
61
public class KeyAgreementFactory
61
public class KeyAgreementFactory
62
{
62
{
63
64
  // Constants and variables
65
  // -------------------------------------------------------------------------
66
67
  // Constructor(s)
68
  // -------------------------------------------------------------------------
69
70
  /** Trivial constructor to enforce <i>Singleton</i> pattern. */
63
  /** Trivial constructor to enforce <i>Singleton</i> pattern. */
71
  private KeyAgreementFactory()
64
  private KeyAgreementFactory()
72
  {
65
  {
73
    super();
66
    super();
74
  }
67
  }
75
68
76
  // Class methods
77
  // -------------------------------------------------------------------------
78
79
  /**
69
  /**
80
   * <p>Returns an instance of a key agreeent protocol handler, for party
70
   * Returns an instance of a key agreeent protocol handler, for party
81
   * <code>A</code> in a two-party <code>A..B</code> exchange, given the
71
   * <code>A</code> in a two-party <code>A..B</code> exchange, given the
82
   * canonical name of this protocol. Party <code>A</code> is usually the
72
   * canonical name of this protocol. Party <code>A</code> is usually the
83
   * initiator of the exchange.</p>
73
   * initiator of the exchange.
84
   *
74
   * 
85
   * @param name the case-insensitive key agreement protocol name.
75
   * @param name the case-insensitive key agreement protocol name.
86
   * @return an instance of the key agreement protocol handler for party
76
   * @return an instance of the key agreement protocol handler for party
87
   * <code>A</code>, or <code>null</code> if none found.
77
   *         <code>A</code>, or <code>null</code> if none found.
88
   */
78
   */
89
  public static IKeyAgreementParty getPartyAInstance(String name)
79
  public static IKeyAgreementParty getPartyAInstance(String name)
90
  {
80
  {
91
    if (name == null)
81
    if (name == null)
92
      {
82
      return null;
93
        return null;
94
      }
95
96
    name = name.trim();
83
    name = name.trim();
97
    IKeyAgreementParty result = null;
84
    IKeyAgreementParty result = null;
98
    if (name.equalsIgnoreCase(Registry.DH_KA))
85
    if (name.equalsIgnoreCase(Registry.DH_KA))
99
      {
86
      result = new DiffieHellmanSender();
100
        result = new DiffieHellmanSender();
101
      }
102
    else if (name.equalsIgnoreCase(Registry.ELGAMAL_KA))
87
    else if (name.equalsIgnoreCase(Registry.ELGAMAL_KA))
103
      {
88
      result = new ElGamalSender();
104
        result = new ElGamalSender();
105
      }
106
    else if (name.equalsIgnoreCase(Registry.SRP6_KA))
89
    else if (name.equalsIgnoreCase(Registry.SRP6_KA))
107
      {
90
      result = new SRP6User();
108
        result = new SRP6User();
109
      }
110
    else if (name.equalsIgnoreCase(Registry.SRP_SASL_KA))
91
    else if (name.equalsIgnoreCase(Registry.SRP_SASL_KA))
111
      {
92
      result = new SRP6SaslClient();
112
        result = new SRP6SaslClient();
113
      }
114
    else if (name.equalsIgnoreCase(Registry.SRP_TLS_KA))
93
    else if (name.equalsIgnoreCase(Registry.SRP_TLS_KA))
115
      {
94
      result = new SRP6TLSClient();
116
        result = new SRP6TLSClient();
117
      }
118
119
    return result;
95
    return result;
120
  }
96
  }
121
97
122
  /**
98
  /**
123
   * <p>Returns an instance of a key agreeent protocol handler, for party
99
   * Returns an instance of a key agreeent protocol handler, for party
124
   * <code>B</code> in a two-party <code>A..B</code> exchange, given the
100
   * <code>B</code> in a two-party <code>A..B</code> exchange, given the
125
   * canonical name of this protocol.</p>
101
   * canonical name of this protocol.
126
   *
102
   * 
127
   * @param name the case-insensitive key agreement protocol name.
103
   * @param name the case-insensitive key agreement protocol name.
128
   * @return an instance of the key agreement protocol handler for party
104
   * @return an instance of the key agreement protocol handler for party
129
   * <code>B</code>, or <code>null</code> if none found.
105
   *         <code>B</code>, or <code>null</code> if none found.
130
   */
106
   */
131
  public static IKeyAgreementParty getPartyBInstance(String name)
107
  public static IKeyAgreementParty getPartyBInstance(String name)
132
  {
108
  {
133
    if (name == null)
109
    if (name == null)
134
      {
110
      return null;
135
        return null;
136
      }
137
138
    name = name.trim();
111
    name = name.trim();
139
    IKeyAgreementParty result = null;
112
    IKeyAgreementParty result = null;
140
    if (name.equalsIgnoreCase(Registry.DH_KA))
113
    if (name.equalsIgnoreCase(Registry.DH_KA))
141
      {
114
      result = new DiffieHellmanReceiver();
142
        result = new DiffieHellmanReceiver();
143
      }
144
    else if (name.equalsIgnoreCase(Registry.ELGAMAL_KA))
115
    else if (name.equalsIgnoreCase(Registry.ELGAMAL_KA))
145
      {
116
      result = new ElGamalReceiver();
146
        result = new ElGamalReceiver();
147
      }
148
    else if (name.equalsIgnoreCase(Registry.SRP6_KA))
117
    else if (name.equalsIgnoreCase(Registry.SRP6_KA))
149
      {
118
      result = new SRP6Host();
150
        result = new SRP6Host();
151
      }
152
    else if (name.equalsIgnoreCase(Registry.SRP_SASL_KA))
119
    else if (name.equalsIgnoreCase(Registry.SRP_SASL_KA))
153
      {
120
      result = new SRP6SaslServer();
154
        result = new SRP6SaslServer();
155
      }
156
    else if (name.equalsIgnoreCase(Registry.SRP_TLS_KA))
121
    else if (name.equalsIgnoreCase(Registry.SRP_TLS_KA))
157
      {
122
      result = new SRP6TLSServer();
158
        result = new SRP6TLSServer();
159
      }
160
161
    return result;
123
    return result;
162
  }
124
  }
163
125
164
  /**
126
  /**
165
   * <p>Returns a {@link Set} of key agreement protocol names supported by this
127
   * Returns a {@link Set} of key agreement protocol names supported by this
166
   * <i>Factory</i>.</p>
128
   * <i>Factory</i>.
167
   *
129
   * 
168
   * @return a {@link Set} of key agreement protocol names (Strings).
130
   * @return a {@link Set} of key agreement protocol names (Strings).
169
   */
131
   */
170
  public static final Set getNames()
132
  public static final Set getNames()
Lines 178-181 Link Here
178
140
179
    return Collections.unmodifiableSet(hs);
141
    return Collections.unmodifiableSet(hs);
180
  }
142
  }
181
}
143
}
(-)OutgoingMessage.java (-50 / +29 lines)
Lines 53-73 Link Here
53
import java.math.BigInteger;
53
import java.math.BigInteger;
54
54
55
/**
55
/**
56
 * <p>An implementation of outgoing messages for use with key agreement
56
 * An implementation of outgoing messages for use with key agreement protocols.
57
 * protocols.</p>
58
 */
57
 */
59
public class OutgoingMessage
58
public class OutgoingMessage
60
{
59
{
61
62
  // Constants and variables
63
  // -------------------------------------------------------------------------
64
65
  /** The internal output stream. */
60
  /** The internal output stream. */
66
  private ByteArrayOutputStream out;
61
  private ByteArrayOutputStream out;
67
62
68
  // Constructor(s)
69
  // -------------------------------------------------------------------------
70
71
  public OutgoingMessage()
63
  public OutgoingMessage()
72
  {
64
  {
73
    super();
65
    super();
Lines 75-90 Link Here
75
    out = new ByteArrayOutputStream();
67
    out = new ByteArrayOutputStream();
76
  }
68
  }
77
69
78
  // Class methods
79
  // -------------------------------------------------------------------------
80
81
  // Instance methods
82
  // -------------------------------------------------------------------------
83
84
  /**
70
  /**
85
   * <p>Returns the encoded form of the current message including the 4-byte
71
   * Returns the encoded form of the current message including the 4-byte length
86
   * length header.</p>
72
   * header.
87
   *
73
   * 
88
   * @throws KeyAgreementException if an encoding size constraint is violated.
74
   * @throws KeyAgreementException if an encoding size constraint is violated.
89
   */
75
   */
90
  public byte[] toByteArray() throws KeyAgreementException
76
  public byte[] toByteArray() throws KeyAgreementException
Lines 92-119 Link Here
92
    byte[] buffer = wrap();
78
    byte[] buffer = wrap();
93
    int length = buffer.length;
79
    int length = buffer.length;
94
    byte[] result = new byte[length + 4];
80
    byte[] result = new byte[length + 4];
95
    result[0] = (byte) (length >>> 24);
81
    result[0] = (byte)(length >>> 24);
96
    result[1] = (byte) (length >>> 16);
82
    result[1] = (byte)(length >>> 16);
97
    result[2] = (byte) (length >>> 8);
83
    result[2] = (byte)(length >>> 8);
98
    result[3] = (byte) length;
84
    result[3] = (byte) length;
99
    System.arraycopy(buffer, 0, result, 4, length);
85
    System.arraycopy(buffer, 0, result, 4, length);
100
101
    return result;
86
    return result;
102
  }
87
  }
103
88
104
  /**
89
  /**
105
   * <p>Returns the encoded form of the current message excluding the 4-byte
90
   * Returns the encoded form of the current message excluding the 4-byte length
106
   * length header.</p>
91
   * header.
107
   *
92
   * 
108
   * @throws KeyAgreementException if an encoding size constraint is violated.
93
   * @throws KeyAgreementException if an encoding size constraint is violated.
109
   */
94
   */
110
  public byte[] wrap() throws KeyAgreementException
95
  public byte[] wrap() throws KeyAgreementException
111
  {
96
  {
112
    int length = out.size();
97
    int length = out.size();
113
    if (length > Registry.SASL_BUFFER_MAX_LIMIT || length < 0)
98
    if (length > Registry.SASL_BUFFER_MAX_LIMIT || length < 0)
114
      {
99
      throw new KeyAgreementException("message content is too long");
115
        throw new KeyAgreementException("message content is too long");
116
      }
117
    return out.toByteArray();
100
    return out.toByteArray();
118
  }
101
  }
119
102
Lines 128-136 Link Here
128
   * representing the total length, excluding these 4 bytes, of the bytes
111
   * representing the total length, excluding these 4 bytes, of the bytes
129
   * representing the encoded key and the one-byte representing the key-type and
112
   * representing the encoded key and the one-byte representing the key-type and
130
   * format; i.e.
113
   * format; i.e.
131
   * 
132
   * <pre>
114
   * <pre>
133
   *    key --&gt; 4-byte-length || 1-byte-type-and-format || encoded-key-bytes
115
   * key --&gt; 4-byte-length || 1-byte-type-and-format || encoded-key-bytes
134
   * </pre>
116
   * </pre>
135
   * 
117
   * 
136
   * @param k the public key to encode.
118
   * @param k the public key to encode.
Lines 152-160 Link Here
152
   * representing the total length, excluding these 4 bytes, of the bytes
134
   * representing the total length, excluding these 4 bytes, of the bytes
153
   * representing the encoded key and the one-byte representing the key-type and
135
   * representing the encoded key and the one-byte representing the key-type and
154
   * format; i.e.
136
   * format; i.e.
155
   * 
156
   * <pre>
137
   * <pre>
157
   *    key --&gt; 4-byte-length || 1-byte-type-and-format || encoded-key-bytes
138
   * key --&gt; 4-byte-length || 1-byte-type-and-format || encoded-key-bytes
158
   * </pre>
139
   * </pre>
159
   * 
140
   * 
160
   * @param k the private key to encode.
141
   * @param k the private key to encode.
Lines 166-173 Link Here
166
  }
147
  }
167
148
168
  /**
149
  /**
169
   * <p>Encodes an MPI into the message.</p>
150
   * Encodes an MPI into the message.
170
   *
151
   * 
171
   * @param val the MPI to encode.
152
   * @param val the MPI to encode.
172
   * @throws KeyAgreementException if an encoding size constraint is violated.
153
   * @throws KeyAgreementException if an encoding size constraint is violated.
173
   */
154
   */
Lines 176-195 Link Here
176
    byte[] b = val.toByteArray();
157
    byte[] b = val.toByteArray();
177
    int length = b.length;
158
    int length = b.length;
178
    if (length > Registry.SASL_TWO_BYTE_MAX_LIMIT)
159
    if (length > Registry.SASL_TWO_BYTE_MAX_LIMIT)
179
      {
160
      throw new KeyAgreementException("MPI is too long");
180
        throw new KeyAgreementException("MPI is too long");
161
    byte[] lengthBytes = { (byte)(length >>> 8), (byte) length };
181
      }
182
    byte[] lengthBytes = { (byte) (length >>> 8), (byte) length };
183
    out.write(lengthBytes, 0, 2);
162
    out.write(lengthBytes, 0, 2);
184
    out.write(b, 0, b.length);
163
    out.write(b, 0, b.length);
185
  }
164
  }
186
165
187
  /**
166
  /**
188
   * <p>Encodes a string into the message.</p>
167
   * Encodes a string into the message.
189
   *
168
   * 
190
   * @param s the string to encode.
169
   * @param s the string to encode.
191
   * @throws KeyAgreementException if the UTF8 encoding is not supported on
170
   * @throws KeyAgreementException if the UTF8 encoding is not supported on this
192
   * this platform, or if an encoding size constraint is violated.
171
   *           platform, or if an encoding size constraint is violated.
193
   */
172
   */
194
  public void writeString(String s) throws KeyAgreementException
173
  public void writeString(String s) throws KeyAgreementException
195
  {
174
  {
Lines 204-213 Link Here
204
      }
183
      }
205
    int length = b.length;
184
    int length = b.length;
206
    if (length > Registry.SASL_TWO_BYTE_MAX_LIMIT)
185
    if (length > Registry.SASL_TWO_BYTE_MAX_LIMIT)
207
      {
186
      throw new KeyAgreementException("text too long");
208
        throw new KeyAgreementException("text too long");
187
    byte[] lengthBytes = { (byte)(length >>> 8), (byte) length };
209
      }
210
    byte[] lengthBytes = { (byte) (length >>> 8), (byte) length };
211
    out.write(lengthBytes, 0, 2);
188
    out.write(lengthBytes, 0, 2);
212
    out.write(b, 0, b.length);
189
    out.write(b, 0, b.length);
213
  }
190
  }
Lines 224-232 Link Here
224
    int length = b.length + 1;
201
    int length = b.length + 1;
225
    if (length > Registry.SASL_FOUR_BYTE_MAX_LIMIT)
202
    if (length > Registry.SASL_FOUR_BYTE_MAX_LIMIT)
226
      throw new KeyAgreementException("Encoded key is too long");
203
      throw new KeyAgreementException("Encoded key is too long");
227
204
    byte[] lengthBytes = {
228
    byte[] lengthBytes = { (byte) (length >>> 24), (byte) (length >>> 16),
205
        (byte)(length >>> 24),
229
                          (byte) (length >>> 8), (byte) length };
206
        (byte)(length >>> 16),
207
        (byte)(length >>> 8),
208
        (byte) length };
230
    out.write(lengthBytes, 0, 4);
209
    out.write(lengthBytes, 0, 4);
231
    out.write(((keyType & 0x0F) << 4) | (formatID & 0x0F));
210
    out.write(((keyType & 0x0F) << 4) | (formatID & 0x0F));
232
    out.write(b, 0, b.length);
211
    out.write(b, 0, b.length);
Lines 252-255 Link Here
252
    throw new KeyAgreementException("Unknown or unsupported key type: "
231
    throw new KeyAgreementException("Unknown or unsupported key type: "
253
                                    + k.getClass().getName());
232
                                    + k.getClass().getName());
254
  }
233
  }
255
}
234
}
(-)dh/DHKeyPairRawCodec.java (-160 / +126 lines)
Lines 47-108 Link Here
47
import java.security.PublicKey;
47
import java.security.PublicKey;
48
48
49
/**
49
/**
50
 * <p>An object that implements the {@link IKeyPairCodec} operations for the
50
 * An object that implements the {@link IKeyPairCodec} operations for the
51
 * <i>Raw</i> format to use with Diffie-Hellman keypairs.</p>
51
 * <i>Raw</i> format to use with Diffie-Hellman keypairs.
52
 */
52
 */
53
public class DHKeyPairRawCodec implements IKeyPairCodec
53
public class DHKeyPairRawCodec
54
    implements IKeyPairCodec
54
{
55
{
55
56
  // Constants and variables
57
  // -------------------------------------------------------------------------
58
59
  // Constructor(s)
60
  // -------------------------------------------------------------------------
61
62
  // implicit 0-arguments ctor
63
64
  // Class methods
65
  // -------------------------------------------------------------------------
66
67
  // Instance methods
68
  // -------------------------------------------------------------------------
69
70
  // gnu.crypto.keys.IKeyPairCodec interface implementation -------------------
71
72
  public int getFormatID()
56
  public int getFormatID()
73
  {
57
  {
74
    return RAW_FORMAT;
58
    return RAW_FORMAT;
75
  }
59
  }
76
60
77
  /**
61
  /**
78
   * <p>Returns the encoded form of the designated Diffie-Hellman public key
62
   * Returns the encoded form of the designated Diffie-Hellman public key
79
   * according to the <i>Raw</i> format supported by this library.</p>
63
   * according to the <i>Raw</i> format supported by this library.
80
   *
64
   * <p>
81
   * <p>The <i>Raw</i> format for a DH public key, in this implementation, is
65
   * The <i>Raw</i> format for a DH public key, in this implementation, is a
82
   * a byte sequence consisting of the following:</p>
66
   * byte sequence consisting of the following:
83
   *
84
   * <ol>
67
   * <ol>
85
   *    <li>4-byte magic consisting of the value of the literal
68
   * <li>4-byte magic consisting of the value of the literal
86
   *    {@link Registry#MAGIC_RAW_DH_PUBLIC_KEY},<li>
69
   * {@link Registry#MAGIC_RAW_DH_PUBLIC_KEY},</li>
87
   *    <li>1-byte version consisting of the constant: 0x01,</li>
70
   * <li>1-byte version consisting of the constant: 0x01,</li>
88
   *    <li>4-byte count of following bytes representing the DH parameter
71
   * <li>4-byte count of following bytes representing the DH parameter
89
   *    <code>q</code> in internet order,</li>
72
   * <code>q</code> in internet order,</li>
90
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
73
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
91
   *    the <code>toByteArray()</code> method on the DH parameter <code>q</code>,</li>
74
   * the <code>toByteArray()</code> method on the DH parameter <code>q</code>,
92
   *    <li>4-byte count of following bytes representing the DH parameter
75
   * </li>
93
   *    <code>p</code> in internet order,</li>
76
   * <li>4-byte count of following bytes representing the DH parameter
94
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
77
   * <code>p</code> in internet order,</li>
95
   *    the <code>toByteArray()</code> method on the DH parameter <code>p</code>,</li>
78
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
96
   *    <li>4-byte count of following bytes representing the DH parameter
79
   * the <code>toByteArray()</code> method on the DH parameter <code>p</code>,
97
   *    <code>g</code>,</li>
80
   * </li>
98
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
81
   * <li>4-byte count of following bytes representing the DH parameter
99
   *    the <code>toByteArray()</code> method on the DH parameter <code>g</code>,</li>
82
   * <code>g</code>,</li>
100
   *    <li>4-byte count of following bytes representing the DH parameter
83
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
101
   *    <code>y</code>,</li>
84
   * the <code>toByteArray()</code> method on the DH parameter <code>g</code>,
102
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
85
   * </li>
103
   *    the <code>toByteArray()</code> method on the DH parameter <code>y</code>,</li>
86
   * <li>4-byte count of following bytes representing the DH parameter
87
   * <code>y</code>,</li>
88
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
89
   * the <code>toByteArray()</code> method on the DH parameter <code>y</code>,
90
   * </li>
104
   * </ol>
91
   * </ol>
105
   *
92
   * 
106
   * @param key the key to encode.
93
   * @param key the key to encode.
107
   * @return the <i>Raw</i> format encoding of the designated key.
94
   * @return the <i>Raw</i> format encoding of the designated key.
108
   * @throws IllegalArgumentException if the designated key is not a DH one.
95
   * @throws IllegalArgumentException if the designated key is not a DH one.
Lines 110-168 Link Here
110
   */
97
   */
111
  public byte[] encodePublicKey(PublicKey key)
98
  public byte[] encodePublicKey(PublicKey key)
112
  {
99
  {
113
    if (!(key instanceof GnuDHPublicKey))
100
    if (! (key instanceof GnuDHPublicKey))
114
      {
101
      throw new IllegalArgumentException("key");
115
        throw new IllegalArgumentException("key");
116
      }
117
118
    GnuDHPublicKey dhKey = (GnuDHPublicKey) key;
102
    GnuDHPublicKey dhKey = (GnuDHPublicKey) key;
119
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
103
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
120
121
    // magic
104
    // magic
122
    baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[0]);
105
    baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[0]);
123
    baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[1]);
106
    baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[1]);
124
    baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[2]);
107
    baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[2]);
125
    baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[3]);
108
    baos.write(Registry.MAGIC_RAW_DH_PUBLIC_KEY[3]);
126
127
    // version
109
    // version
128
    baos.write(0x01);
110
    baos.write(0x01);
129
130
    // q
111
    // q
131
    byte[] buffer = dhKey.getQ().toByteArray();
112
    byte[] buffer = dhKey.getQ().toByteArray();
132
    int length = buffer.length;
113
    int length = buffer.length;
133
    baos.write(length >>> 24);
114
    baos.write( length >>> 24);
134
    baos.write((length >>> 16) & 0xFF);
115
    baos.write((length >>> 16) & 0xFF);
135
    baos.write((length >>> 8) & 0xFF);
116
    baos.write((length >>>  8) & 0xFF);
136
    baos.write(length & 0xFF);
117
    baos.write( length         & 0xFF);
137
    baos.write(buffer, 0, length);
118
    baos.write(buffer, 0, length);
138
139
    // p
119
    // p
140
    buffer = dhKey.getParams().getP().toByteArray();
120
    buffer = dhKey.getParams().getP().toByteArray();
141
    length = buffer.length;
121
    length = buffer.length;
142
    baos.write(length >>> 24);
122
    baos.write( length >>> 24);
143
    baos.write((length >>> 16) & 0xFF);
123
    baos.write((length >>> 16) & 0xFF);
144
    baos.write((length >>> 8) & 0xFF);
124
    baos.write((length >>>  8) & 0xFF);
145
    baos.write(length & 0xFF);
125
    baos.write( length         & 0xFF);
146
    baos.write(buffer, 0, length);
126
    baos.write(buffer, 0, length);
147
148
    // g
127
    // g
149
    buffer = dhKey.getParams().getG().toByteArray();
128
    buffer = dhKey.getParams().getG().toByteArray();
150
    length = buffer.length;
129
    length = buffer.length;
151
    baos.write(length >>> 24);
130
    baos.write( length >>> 24);
152
    baos.write((length >>> 16) & 0xFF);
131
    baos.write((length >>> 16) & 0xFF);
153
    baos.write((length >>> 8) & 0xFF);
132
    baos.write((length >>>  8) & 0xFF);
154
    baos.write(length & 0xFF);
133
    baos.write( length         & 0xFF);
155
    baos.write(buffer, 0, length);
134
    baos.write(buffer, 0, length);
156
157
    // y
135
    // y
158
    buffer = dhKey.getY().toByteArray();
136
    buffer = dhKey.getY().toByteArray();
159
    length = buffer.length;
137
    length = buffer.length;
160
    baos.write(length >>> 24);
138
    baos.write( length >>> 24);
161
    baos.write((length >>> 16) & 0xFF);
139
    baos.write((length >>> 16) & 0xFF);
162
    baos.write((length >>> 8) & 0xFF);
140
    baos.write((length >>>  8) & 0xFF);
163
    baos.write(length & 0xFF);
141
    baos.write( length         & 0xFF);
164
    baos.write(buffer, 0, length);
142
    baos.write(buffer, 0, length);
165
166
    return baos.toByteArray();
143
    return baos.toByteArray();
167
  }
144
  }
168
145
Lines 173-255 Link Here
173
        || k[1] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[1]
150
        || k[1] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[1]
174
        || k[2] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[2]
151
        || k[2] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[2]
175
        || k[3] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[3])
152
        || k[3] != Registry.MAGIC_RAW_DH_PUBLIC_KEY[3])
176
      {
153
      throw new IllegalArgumentException("magic");
177
        throw new IllegalArgumentException("magic");
178
      }
179
180
    // version
154
    // version
181
    if (k[4] != 0x01)
155
    if (k[4] != 0x01)
182
      {
156
      throw new IllegalArgumentException("version");
183
        throw new IllegalArgumentException("version");
184
      }
185
    int i = 5;
157
    int i = 5;
186
    int l;
158
    int l;
187
    byte[] buffer;
159
    byte[] buffer;
188
189
    // q
160
    // q
190
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
161
    l =  k[i++]         << 24
191
        | (k[i++] & 0xFF);
162
      | (k[i++] & 0xFF) << 16
163
      | (k[i++] & 0xFF) << 8
164
      | (k[i++] & 0xFF);
192
    buffer = new byte[l];
165
    buffer = new byte[l];
193
    System.arraycopy(k, i, buffer, 0, l);
166
    System.arraycopy(k, i, buffer, 0, l);
194
    i += l;
167
    i += l;
195
    BigInteger q = new BigInteger(1, buffer);
168
    BigInteger q = new BigInteger(1, buffer);
196
197
    // p
169
    // p
198
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
170
    l =  k[i++]         << 24
199
        | (k[i++] & 0xFF);
171
      | (k[i++] & 0xFF) << 16
172
      | (k[i++] & 0xFF) << 8
173
      | (k[i++] & 0xFF);
200
    buffer = new byte[l];
174
    buffer = new byte[l];
201
    System.arraycopy(k, i, buffer, 0, l);
175
    System.arraycopy(k, i, buffer, 0, l);
202
    i += l;
176
    i += l;
203
    BigInteger p = new BigInteger(1, buffer);
177
    BigInteger p = new BigInteger(1, buffer);
204
205
    // g
178
    // g
206
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
179
    l =  k[i++]         << 24
207
        | (k[i++] & 0xFF);
180
      | (k[i++] & 0xFF) << 16
181
      | (k[i++] & 0xFF) << 8
182
      | (k[i++] & 0xFF);
208
    buffer = new byte[l];
183
    buffer = new byte[l];
209
    System.arraycopy(k, i, buffer, 0, l);
184
    System.arraycopy(k, i, buffer, 0, l);
210
    i += l;
185
    i += l;
211
    BigInteger g = new BigInteger(1, buffer);
186
    BigInteger g = new BigInteger(1, buffer);
212
213
    // y
187
    // y
214
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
188
    l =  k[i++]         << 24
215
        | (k[i++] & 0xFF);
189
      | (k[i++] & 0xFF) << 16
190
      | (k[i++] & 0xFF) << 8
191
      | (k[i++] & 0xFF);
216
    buffer = new byte[l];
192
    buffer = new byte[l];
217
    System.arraycopy(k, i, buffer, 0, l);
193
    System.arraycopy(k, i, buffer, 0, l);
218
    i += l;
194
    i += l;
219
    BigInteger y = new BigInteger(1, buffer);
195
    BigInteger y = new BigInteger(1, buffer);
220
221
    return new GnuDHPublicKey(q, p, g, y);
196
    return new GnuDHPublicKey(q, p, g, y);
222
  }
197
  }
223
198
224
  /**
199
  /**
225
   * <p>Returns the encoded form of the designated Diffie-Hellman private key
200
   * Returns the encoded form of the designated Diffie-Hellman private key
226
   * according to the <i>Raw</i> format supported by this library.</p>
201
   * according to the <i>Raw</i> format supported by this library.
227
   *
202
   * <p>
228
   * <p>The <i>Raw</i> format for a DH private key, in this implementation, is
203
   * The <i>Raw</i> format for a DH private key, in this implementation, is a
229
   * a byte sequence consisting of the following:</p>
204
   * byte sequence consisting of the following:
230
   *
231
   * <ol>
205
   * <ol>
232
   *    <li>4-byte magic consisting of the value of the literal
206
   * <li>4-byte magic consisting of the value of the literal
233
   *    {@link Registry#MAGIC_RAW_DH_PRIVATE_KEY},<li>
207
   * {@link Registry#MAGIC_RAW_DH_PRIVATE_KEY},</li>
234
   *    <li>1-byte version consisting of the constant: 0x01,</li>
208
   * <li>1-byte version consisting of the constant: 0x01,</li>
235
   *    <li>4-byte count of following bytes representing the DH parameter
209
   * <li>4-byte count of following bytes representing the DH parameter
236
   *    <code>q</code>,</li>
210
   * <code>q</code>,</li>
237
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
211
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
238
   *    the <code>toByteArray()</code> method on the DH parameter <code>q</code>,</li>
212
   * the <code>toByteArray()</code> method on the DH parameter <code>q</code>,
239
   *    <li>4-byte count of following bytes representing the DH parameter
213
   * </li>
240
   *    <code>p</code> in internet order,</li>
214
   * <li>4-byte count of following bytes representing the DH parameter
241
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
215
   * <code>p</code> in internet order,</li>
242
   *    the <code>toByteArray()</code> method on the DH parameter <code>p</code>,</li>
216
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
243
   *    <li>4-byte count of following bytes representing the DH parameter
217
   * the <code>toByteArray()</code> method on the DH parameter <code>p</code>,
244
   *    <code>g</code>,</li>
218
   * </li>
245
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
219
   * <li>4-byte count of following bytes representing the DH parameter
246
   *    the <code>toByteArray()</code> method on the DH parameter <code>g</code>,</li>
220
   * <code>g</code>,</li>
247
   *    <li>4-byte count of following bytes representing the DH parameter
221
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
248
   *    <code>x</code>,</li>
222
   * the <code>toByteArray()</code> method on the DH parameter <code>g</code>,
249
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
223
   * </li>
250
   *    the <code>toByteArray()</code> method on the DH parameter <code>x</code>,</li>
224
   * <li>4-byte count of following bytes representing the DH parameter
225
   * <code>x</code>,</li>
226
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
227
   * the <code>toByteArray()</code> method on the DH parameter <code>x</code>,
228
   * </li>
251
   * </ol>
229
   * </ol>
252
   *
230
   * 
253
   * @param key the key to encode.
231
   * @param key the key to encode.
254
   * @return the <i>Raw</i> format encoding of the designated key.
232
   * @return the <i>Raw</i> format encoding of the designated key.
255
   * @throws IllegalArgumentException if the designated key is not a DH one.
233
   * @throws IllegalArgumentException if the designated key is not a DH one.
Lines 257-315 Link Here
257
   */
235
   */
258
  public byte[] encodePrivateKey(PrivateKey key)
236
  public byte[] encodePrivateKey(PrivateKey key)
259
  {
237
  {
260
    if (!(key instanceof GnuDHPrivateKey))
238
    if (! (key instanceof GnuDHPrivateKey))
261
      {
239
      throw new IllegalArgumentException("key");
262
        throw new IllegalArgumentException("key");
263
      }
264
265
    GnuDHPrivateKey dhKey = (GnuDHPrivateKey) key;
240
    GnuDHPrivateKey dhKey = (GnuDHPrivateKey) key;
266
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
241
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
267
268
    // magic
242
    // magic
269
    baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[0]);
243
    baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[0]);
270
    baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[1]);
244
    baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[1]);
271
    baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[2]);
245
    baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[2]);
272
    baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[3]);
246
    baos.write(Registry.MAGIC_RAW_DH_PRIVATE_KEY[3]);
273
274
    // version
247
    // version
275
    baos.write(0x01);
248
    baos.write(0x01);
276
277
    // q
249
    // q
278
    byte[] buffer = dhKey.getQ().toByteArray();
250
    byte[] buffer = dhKey.getQ().toByteArray();
279
    int length = buffer.length;
251
    int length = buffer.length;
280
    baos.write(length >>> 24);
252
    baos.write( length >>> 24);
281
    baos.write((length >>> 16) & 0xFF);
253
    baos.write((length >>> 16) & 0xFF);
282
    baos.write((length >>> 8) & 0xFF);
254
    baos.write((length >>>  8) & 0xFF);
283
    baos.write(length & 0xFF);
255
    baos.write( length         & 0xFF);
284
    baos.write(buffer, 0, length);
256
    baos.write(buffer, 0, length);
285
286
    // p
257
    // p
287
    buffer = dhKey.getParams().getP().toByteArray();
258
    buffer = dhKey.getParams().getP().toByteArray();
288
    length = buffer.length;
259
    length = buffer.length;
289
    baos.write(length >>> 24);
260
    baos.write( length >>> 24);
290
    baos.write((length >>> 16) & 0xFF);
261
    baos.write((length >>> 16) & 0xFF);
291
    baos.write((length >>> 8) & 0xFF);
262
    baos.write((length >>>  8) & 0xFF);
292
    baos.write(length & 0xFF);
263
    baos.write( length         & 0xFF);
293
    baos.write(buffer, 0, length);
264
    baos.write(buffer, 0, length);
294
295
    // g
265
    // g
296
    buffer = dhKey.getParams().getG().toByteArray();
266
    buffer = dhKey.getParams().getG().toByteArray();
297
    length = buffer.length;
267
    length = buffer.length;
298
    baos.write(length >>> 24);
268
    baos.write( length >>> 24);
299
    baos.write((length >>> 16) & 0xFF);
269
    baos.write((length >>> 16) & 0xFF);
300
    baos.write((length >>> 8) & 0xFF);
270
    baos.write((length >>>  8) & 0xFF);
301
    baos.write(length & 0xFF);
271
    baos.write( length         & 0xFF);
302
    baos.write(buffer, 0, length);
272
    baos.write(buffer, 0, length);
303
304
    // x
273
    // x
305
    buffer = dhKey.getX().toByteArray();
274
    buffer = dhKey.getX().toByteArray();
306
    length = buffer.length;
275
    length = buffer.length;
307
    baos.write(length >>> 24);
276
    baos.write( length >>> 24);
308
    baos.write((length >>> 16) & 0xFF);
277
    baos.write((length >>> 16) & 0xFF);
309
    baos.write((length >>> 8) & 0xFF);
278
    baos.write((length >>>  8) & 0xFF);
310
    baos.write(length & 0xFF);
279
    baos.write( length         & 0xFF);
311
    baos.write(buffer, 0, length);
280
    baos.write(buffer, 0, length);
312
313
    return baos.toByteArray();
281
    return baos.toByteArray();
314
  }
282
  }
315
283
Lines 320-370 Link Here
320
        || k[1] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[1]
288
        || k[1] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[1]
321
        || k[2] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[2]
289
        || k[2] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[2]
322
        || k[3] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[3])
290
        || k[3] != Registry.MAGIC_RAW_DH_PRIVATE_KEY[3])
323
      {
291
      throw new IllegalArgumentException("magic");
324
        throw new IllegalArgumentException("magic");
325
      }
326
327
    // version
292
    // version
328
    if (k[4] != 0x01)
293
    if (k[4] != 0x01)
329
      {
294
      throw new IllegalArgumentException("version");
330
        throw new IllegalArgumentException("version");
331
      }
332
    int i = 5;
295
    int i = 5;
333
    int l;
296
    int l;
334
    byte[] buffer;
297
    byte[] buffer;
335
336
    // q
298
    // q
337
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
299
    l =  k[i++]         << 24
338
        | (k[i++] & 0xFF);
300
      | (k[i++] & 0xFF) << 16
301
      | (k[i++] & 0xFF) << 8
302
      | (k[i++] & 0xFF);
339
    buffer = new byte[l];
303
    buffer = new byte[l];
340
    System.arraycopy(k, i, buffer, 0, l);
304
    System.arraycopy(k, i, buffer, 0, l);
341
    i += l;
305
    i += l;
342
    BigInteger q = new BigInteger(1, buffer);
306
    BigInteger q = new BigInteger(1, buffer);
343
344
    // p
307
    // p
345
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
308
    l =  k[i++]         << 24
346
        | (k[i++] & 0xFF);
309
      | (k[i++] & 0xFF) << 16
310
      | (k[i++] & 0xFF) << 8
311
      | (k[i++] & 0xFF);
347
    buffer = new byte[l];
312
    buffer = new byte[l];
348
    System.arraycopy(k, i, buffer, 0, l);
313
    System.arraycopy(k, i, buffer, 0, l);
349
    i += l;
314
    i += l;
350
    BigInteger p = new BigInteger(1, buffer);
315
    BigInteger p = new BigInteger(1, buffer);
351
352
    // g
316
    // g
353
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
317
    l =  k[i++]         << 24
354
        | (k[i++] & 0xFF);
318
      | (k[i++] & 0xFF) << 16
319
      | (k[i++] & 0xFF) << 8
320
      | (k[i++] & 0xFF);
355
    buffer = new byte[l];
321
    buffer = new byte[l];
356
    System.arraycopy(k, i, buffer, 0, l);
322
    System.arraycopy(k, i, buffer, 0, l);
357
    i += l;
323
    i += l;
358
    BigInteger g = new BigInteger(1, buffer);
324
    BigInteger g = new BigInteger(1, buffer);
359
360
    // x
325
    // x
361
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
326
    l =  k[i++]         << 24
362
        | (k[i++] & 0xFF);
327
      | (k[i++] & 0xFF) << 16
328
      | (k[i++] & 0xFF) << 8
329
      | (k[i++] & 0xFF);
363
    buffer = new byte[l];
330
    buffer = new byte[l];
364
    System.arraycopy(k, i, buffer, 0, l);
331
    System.arraycopy(k, i, buffer, 0, l);
365
    i += l;
332
    i += l;
366
    BigInteger x = new BigInteger(1, buffer);
333
    BigInteger x = new BigInteger(1, buffer);
367
368
    return new GnuDHPrivateKey(q, p, g, x);
334
    return new GnuDHPrivateKey(q, p, g, x);
369
  }
335
  }
370
}
336
}
(-)dh/DiffieHellmanKeyAgreement.java (-53 / +38 lines)
Lines 49-126 Link Here
49
import javax.crypto.interfaces.DHPrivateKey;
49
import javax.crypto.interfaces.DHPrivateKey;
50
50
51
/**
51
/**
52
 * <p>The basic version of the Diffie-Hellman key agreement is described in the
52
 * The basic version of the Diffie-Hellman key agreement is described in the
53
 * Handbook of Applied Cryptography [HAC] as follows:</p>
53
 * Handbook of Applied Cryptography [HAC] as follows:
54
 * <ul>
54
 * <ul>
55
 *    <li>An appropriate prime p and generator g of Z<sub>p</sub><sup>*</sup>
55
 * <li>An appropriate prime p and generator g of Z<sub>p</sub><sup>*</sup>
56
 *    (2 &lt;= g &lt;= p-2) are selected and published.</li>
56
 * (2 &lt;= g &lt;= p-2) are selected and published.</li>
57
 *    <li>A and B each send the other one message over an open channel; as a
57
 * <li>A and B each send the other one message over an open channel; as a
58
 *    result, they both can then compute a shared secret key K which they can
58
 * result, they both can then compute a shared secret key K which they can use
59
 *    use to protect their future communication.</li>
59
 * to protect their future communication.</li>
60
 *    <li>A chooses a random secret x, 1 &lt;= x &lt;= p-2, and sends B message
60
 * <li>A chooses a random secret x, 1 &lt;= x &lt;= p-2, and sends B message
61
 *    (1) which is g^x mod p.</li>
61
 * (1) which is g^x mod p.</li>
62
 *    <li>B chooses a random secret y, 1 &lt;= y &lt;= p-2, and sends A message
62
 * <li>B chooses a random secret y, 1 &lt;= y &lt;= p-2, and sends A message
63
 *    (2) which is g^y mod p.</li>
63
 * (2) which is g^y mod p.</li>
64
 *    <li>B receives message (1) and computes the shared key as K = (g^x)^y mod
64
 * <li>B receives message (1) and computes the shared key as K = (g^x)^y mod p.
65
 *    p.</li>
65
 * </li>
66
 *    <li>A receives message (2) and computes the shared key as K = (g^y)^x mod
66
 * <li>A receives message (2) and computes the shared key as K = (g^y)^x mod p.
67
 *    p.</li>
67
 * </li>
68
 * </ul>
68
 * </ul>
69
 *
69
 * <p>
70
 * <p>RFC-2631 describes a <i>Static-Static Mode</i> of operations with
70
 * RFC-2631 describes a <i>Static-Static Mode</i> of operations with
71
 * Diffie-Hellman keypairs as follows:</p>
71
 * Diffie-Hellman keypairs as follows:
72
 * <pre>
72
 * <pre>
73
 * "In Static-Static mode, both the sender and the recipient have a
73
 *  &quot;In Static-Static mode, both the sender and the recipient have a
74
 static (and certified) key pair. Since the sender's and recipient's
74
 *  static (and certified) key pair. Since the sender's and recipient's
75
 keys are therefore the same for each message, ZZ will be the same for
75
 *  keys are therefore the same for each message, ZZ will be the same for
76
 each message. Thus, partyAInfo MUST be used (and different for each
76
 *  each message. Thus, partyAInfo MUST be used (and different for each
77
 message) in order to ensure that different messages use different
77
 *  message) in order to ensure that different messages use different
78
 KEKs. Implementations MAY implement Static-Static mode."
78
 *  KEKs. Implementations MAY implement Static-Static mode.&quot;
79
 * </pre>
79
 * </pre>
80
 *
80
 * 
81
 * <p>Reference:</p>
81
 * <p>
82
 * Reference:
82
 * <ol>
83
 * <ol>
83
 *    <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
84
 * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
84
 *    Agreement Method</a><br>
85
 * Agreement Method</a><br>
85
 *    Eric Rescorla.</li>
86
 * Eric Rescorla.</li>
86
 *    <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
87
 * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
87
 *    Applied Cryptography.<br>
88
 * Applied Cryptography.<br>
88
 *    CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
89
 * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
89
 *    Menezes, A., van Oorschot, P. and S. Vanstone.</li>
90
 * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
90
 * </ol>
91
 * </ol>
91
 */
92
 */
92
public abstract class DiffieHellmanKeyAgreement extends BaseKeyAgreementParty
93
public abstract class DiffieHellmanKeyAgreement
94
    extends BaseKeyAgreementParty
93
{
95
{
94
95
  // Constants and variables
96
  // -------------------------------------------------------------------------
97
98
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dh.ka.prng";
96
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dh.ka.prng";
99
97
  public static final String KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY =
100
  public static final String KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY = "gnu.crypto.dh.ka.owner.private.key";
98
      "gnu.crypto.dh.ka.owner.private.key";
101
102
  /** The key agreement party's private key. */
99
  /** The key agreement party's private key. */
103
  protected DHPrivateKey ownerKey;
100
  protected DHPrivateKey ownerKey;
104
105
  /** The shared secret key. */
101
  /** The shared secret key. */
106
  protected BigInteger ZZ;
102
  protected BigInteger ZZ;
107
103
108
  // Constructor(s)
109
  // -------------------------------------------------------------------------
110
111
  protected DiffieHellmanKeyAgreement()
104
  protected DiffieHellmanKeyAgreement()
112
  {
105
  {
113
    super(Registry.DH_KA);
106
    super(Registry.DH_KA);
114
  }
107
  }
115
108
116
  // Class methods
117
  // -------------------------------------------------------------------------
118
119
  // Instance methods
120
  // -------------------------------------------------------------------------
121
122
  // implementation of common abstract methods in BaseKeyAGreementParty ------
123
124
  protected byte[] engineSharedSecret() throws KeyAgreementException
109
  protected byte[] engineSharedSecret() throws KeyAgreementException
125
  {
110
  {
126
    return Util.trim(ZZ);
111
    return Util.trim(ZZ);
(-)dh/DiffieHellmanReceiver.java (-40 / +10 lines)
Lines 51-100 Link Here
51
import javax.crypto.interfaces.DHPrivateKey;
51
import javax.crypto.interfaces.DHPrivateKey;
52
52
53
/**
53
/**
54
 * <p>This implementation is the receiver's part of the basic version of the
54
 * This implementation is the receiver's part of the basic version of the
55
 * Diffie-Hellman key agreement exchange (B in [HAC]).</p>
55
 * Diffie-Hellman key agreement exchange (B in [HAC]).
56
 *
56
 * 
57
 * @see DiffieHellmanKeyAgreement
57
 * @see DiffieHellmanKeyAgreement
58
 */
58
 */
59
public class DiffieHellmanReceiver extends DiffieHellmanKeyAgreement
59
public class DiffieHellmanReceiver
60
    extends DiffieHellmanKeyAgreement
60
{
61
{
61
62
  // Constants and variables
63
  // -------------------------------------------------------------------------
64
65
  private BigInteger y; // the receiver's random secret
62
  private BigInteger y; // the receiver's random secret
66
63
67
  // Constructor(s)
68
  // -------------------------------------------------------------------------
69
70
  // default 0-arguments constructor
64
  // default 0-arguments constructor
71
65
72
  // Class methods
73
  // -------------------------------------------------------------------------
74
75
  // Instance methods
76
  // -------------------------------------------------------------------------
77
78
  // implementation of abstract methods in base class ------------------------
79
80
  protected void engineInit(Map attributes) throws KeyAgreementException
66
  protected void engineInit(Map attributes) throws KeyAgreementException
81
  {
67
  {
82
    Object random = attributes.get(SOURCE_OF_RANDOMNESS);
68
    Object random = attributes.get(SOURCE_OF_RANDOMNESS);
83
    rnd = null;
69
    rnd = null;
84
    irnd = null;
70
    irnd = null;
85
    if (random instanceof SecureRandom)
71
    if (random instanceof SecureRandom)
86
      {
72
      rnd = (SecureRandom) random;
87
        rnd = (SecureRandom) random;
88
      }
89
    else if (random instanceof IRandom)
73
    else if (random instanceof IRandom)
90
      {
74
      irnd = (IRandom) random;
91
        irnd = (IRandom) random;
92
      }
93
    ownerKey = (DHPrivateKey) attributes.get(KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY);
75
    ownerKey = (DHPrivateKey) attributes.get(KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY);
94
    if (ownerKey == null)
76
    if (ownerKey == null)
95
      {
77
      throw new KeyAgreementException("missing owner's private key");
96
        throw new KeyAgreementException("missing owner's private key");
97
      }
98
  }
78
  }
99
79
100
  protected OutgoingMessage engineProcessMessage(IncomingMessage in)
80
  protected OutgoingMessage engineProcessMessage(IncomingMessage in)
Lines 109-128 Link Here
109
      }
89
      }
110
  }
90
  }
111
91
112
  // own methods -------------------------------------------------------------
113
114
  private OutgoingMessage computeSharedSecret(IncomingMessage in)
92
  private OutgoingMessage computeSharedSecret(IncomingMessage in)
115
      throws KeyAgreementException
93
      throws KeyAgreementException
116
  {
94
  {
117
    BigInteger m1 = in.readMPI();
95
    BigInteger m1 = in.readMPI();
118
    if (m1 == null)
96
    if (m1 == null)
119
      {
97
      throw new KeyAgreementException("missing message (1)");
120
        throw new KeyAgreementException("missing message (1)");
121
      }
122
123
    BigInteger p = ownerKey.getParams().getP();
98
    BigInteger p = ownerKey.getParams().getP();
124
    BigInteger g = ownerKey.getParams().getG();
99
    BigInteger g = ownerKey.getParams().getG();
125
126
    // B chooses a random integer y, 1 <= y <= p-2
100
    // B chooses a random integer y, 1 <= y <= p-2
127
    // rfc-2631 restricts y to only be in [2, p-1]
101
    // rfc-2631 restricts y to only be in [2, p-1]
128
    BigInteger p_minus_2 = p.subtract(TWO);
102
    BigInteger p_minus_2 = p.subtract(TWO);
Lines 132-147 Link Here
132
        nextRandomBytes(xBytes);
106
        nextRandomBytes(xBytes);
133
        y = new BigInteger(1, xBytes);
107
        y = new BigInteger(1, xBytes);
134
      }
108
      }
135
    while (!(y.compareTo(TWO) >= 0 && y.compareTo(p_minus_2) <= 0));
109
    while (! (y.compareTo(TWO) >= 0 && y.compareTo(p_minus_2) <= 0));
136
137
    ZZ = m1.modPow(y, p); // ZZ = (yb ^ xa) mod p
110
    ZZ = m1.modPow(y, p); // ZZ = (yb ^ xa) mod p
138
139
    complete = true;
111
    complete = true;
140
141
    // B sends A the message: g^y mod p
112
    // B sends A the message: g^y mod p
142
    OutgoingMessage result = new OutgoingMessage();
113
    OutgoingMessage result = new OutgoingMessage();
143
    result.writeMPI(g.modPow(y, p)); // message (2)
114
    result.writeMPI(g.modPow(y, p)); // message (2)
144
145
    return result;
115
    return result;
146
  }
116
  }
147
}
117
}
(-)dh/DiffieHellmanSender.java (-40 / +11 lines)
Lines 51-100 Link Here
51
import javax.crypto.interfaces.DHPrivateKey;
51
import javax.crypto.interfaces.DHPrivateKey;
52
52
53
/**
53
/**
54
 * <p>This implementation is the sender's part of the basic version of the
54
 * This implementation is the sender's part of the basic version of the
55
 * Diffie-Hellman key agreement exchange (A in [HAC]).</p>
55
 * Diffie-Hellman key agreement exchange (A in [HAC]).
56
 *
56
 * 
57
 * @see DiffieHellmanKeyAgreement
57
 * @see DiffieHellmanKeyAgreement
58
 */
58
 */
59
public class DiffieHellmanSender extends DiffieHellmanKeyAgreement
59
public class DiffieHellmanSender
60
    extends DiffieHellmanKeyAgreement
60
{
61
{
61
62
  // Constants and variables
63
  // -------------------------------------------------------------------------
64
65
  private BigInteger x; // the sender's random secret
62
  private BigInteger x; // the sender's random secret
66
63
67
  // Constructor(s)
68
  // -------------------------------------------------------------------------
69
70
  // default 0-arguments constructor
64
  // default 0-arguments constructor
71
65
72
  // Class methods
73
  // -------------------------------------------------------------------------
74
75
  // Instance methods
76
  // -------------------------------------------------------------------------
77
78
  // implementation of abstract methods in base class ------------------------
79
80
  protected void engineInit(Map attributes) throws KeyAgreementException
66
  protected void engineInit(Map attributes) throws KeyAgreementException
81
  {
67
  {
82
    Object random = attributes.get(SOURCE_OF_RANDOMNESS);
68
    Object random = attributes.get(SOURCE_OF_RANDOMNESS);
83
    rnd = null;
69
    rnd = null;
84
    irnd = null;
70
    irnd = null;
85
    if (random instanceof SecureRandom)
71
    if (random instanceof SecureRandom)
86
      {
72
      rnd = (SecureRandom) random;
87
        rnd = (SecureRandom) random;
88
      }
89
    else if (random instanceof IRandom)
73
    else if (random instanceof IRandom)
90
      {
74
      irnd = (IRandom) random;
91
        irnd = (IRandom) random;
92
      }
93
    ownerKey = (DHPrivateKey) attributes.get(KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY);
75
    ownerKey = (DHPrivateKey) attributes.get(KA_DIFFIE_HELLMAN_OWNER_PRIVATE_KEY);
94
    if (ownerKey == null)
76
    if (ownerKey == null)
95
      {
77
      throw new KeyAgreementException("missing owner's private key");
96
        throw new KeyAgreementException("missing owner's private key");
97
      }
98
  }
78
  }
99
79
100
  protected OutgoingMessage engineProcessMessage(IncomingMessage in)
80
  protected OutgoingMessage engineProcessMessage(IncomingMessage in)
Lines 111-124 Link Here
111
      }
91
      }
112
  }
92
  }
113
93
114
  // own methods -------------------------------------------------------------
115
116
  private OutgoingMessage sendRandomSecret(IncomingMessage in)
94
  private OutgoingMessage sendRandomSecret(IncomingMessage in)
117
      throws KeyAgreementException
95
      throws KeyAgreementException
118
  {
96
  {
119
    BigInteger p = ownerKey.getParams().getP();
97
    BigInteger p = ownerKey.getParams().getP();
120
    BigInteger g = ownerKey.getParams().getG();
98
    BigInteger g = ownerKey.getParams().getG();
121
122
    // A chooses a random integer x, 1 <= x <= p-2
99
    // A chooses a random integer x, 1 <= x <= p-2
123
    // rfc-2631 restricts x to only be in [2, p-1]
100
    // rfc-2631 restricts x to only be in [2, p-1]
124
    BigInteger p_minus_2 = p.subtract(TWO);
101
    BigInteger p_minus_2 = p.subtract(TWO);
Lines 128-139 Link Here
128
        nextRandomBytes(xBytes);
105
        nextRandomBytes(xBytes);
129
        x = new BigInteger(1, xBytes);
106
        x = new BigInteger(1, xBytes);
130
      }
107
      }
131
    while (!(x.compareTo(TWO) >= 0 && x.compareTo(p_minus_2) <= 0));
108
    while (! (x.compareTo(TWO) >= 0 && x.compareTo(p_minus_2) <= 0));
132
133
    // A sends B the message: g^x mod p
109
    // A sends B the message: g^x mod p
134
    OutgoingMessage result = new OutgoingMessage();
110
    OutgoingMessage result = new OutgoingMessage();
135
    result.writeMPI(g.modPow(x, p));
111
    result.writeMPI(g.modPow(x, p));
136
137
    return result;
112
    return result;
138
  }
113
  }
139
114
Lines 142-154 Link Here
142
  {
117
  {
143
    BigInteger m1 = in.readMPI();
118
    BigInteger m1 = in.readMPI();
144
    if (m1 == null)
119
    if (m1 == null)
145
      {
120
      throw new KeyAgreementException("missing message (2)");
146
        throw new KeyAgreementException("missing message (2)");
147
      }
148
149
    BigInteger p = ownerKey.getParams().getP();
121
    BigInteger p = ownerKey.getParams().getP();
150
    ZZ = m1.modPow(x, p); // ZZ = (yb ^ xa)  mod p
122
    ZZ = m1.modPow(x, p); // ZZ = (yb ^ xa) mod p
151
152
    complete = true;
123
    complete = true;
153
    return null;
124
    return null;
154
  }
125
  }
(-)dh/ElGamalKeyAgreement.java (-53 / +38 lines)
Lines 47-123 Link Here
47
import java.math.BigInteger;
47
import java.math.BigInteger;
48
48
49
/**
49
/**
50
 * <p>The ElGamal key agreement, also known as the half-certified Diffie-Hellman
50
 * The ElGamal key agreement, also known as the half-certified Diffie-Hellman
51
 * key agreement, is described in the Handbook of Applied Cryptography [HAC] as
51
 * key agreement, is described in the Handbook of Applied Cryptography [HAC] as
52
 * follows:</p>
52
 * follows:
53
 * <ul>
53
 * <ul>
54
 *    <li>A sends to B a single message allowing one-pass key agreement.</li>
54
 * <li>A sends to B a single message allowing one-pass key agreement.</li>
55
 *    <li>A obtains an authentic copy of B's public key (p, g, yb), where
55
 * <li>A obtains an authentic copy of B's public key (p, g, yb), where yb =
56
 *    yb = g**xb.</li>
56
 * g**xb.</li>
57
 *    <li>A chooses a random integer x, 1 &lt;= x &lt;= p-2, and sends B the
57
 * <li>A chooses a random integer x, 1 &lt;= x &lt;= p-2, and sends B the
58
 *    message g**x.  A computes the shared secret key K as yb**x.</li>
58
 * message g**x. A computes the shared secret key K as yb**x.</li>
59
 *    <li>B computes the same key K on receipt of the previous message as
59
 * <li>B computes the same key K on receipt of the previous message as
60
 *    (g**x)**xb.</li>
60
 * (g**x)**xb.</li>
61
 * </ul>
61
 * </ul>
62
 *
62
 * <p>
63
 * <p>RFC-2631 describes an <i>Ephemeral-Static Mode</i> of operations with
63
 * RFC-2631 describes an <i>Ephemeral-Static Mode</i> of operations with
64
 * Diffie-Hellman keypairs as follows:</p>
64
 * Diffie-Hellman keypairs as follows:
65
 * <pre>
65
 * <pre>
66
 * "In Ephemeral-Static mode, the recipient has a static (and certified)
66
 *  &quot;In Ephemeral-Static mode, the recipient has a static (and certified)
67
 * key pair, but the sender generates a new key pair for each message
67
 *  key pair, but the sender generates a new key pair for each message
68
 * and sends it using the originatorKey production. If the sender's key
68
 *  and sends it using the originatorKey production. If the sender's key
69
 * is freshly generated for each message, the shared secret ZZ will be
69
 *  is freshly generated for each message, the shared secret ZZ will be
70
 * similarly different for each message and partyAInfo MAY be omitted,
70
 *  similarly different for each message and partyAInfo MAY be omitted,
71
 * since it serves merely to decouple multiple KEKs generated by the
71
 *  since it serves merely to decouple multiple KEKs generated by the
72
 * same set of pairwise keys. If, however, the same ephemeral sender key
72
 *  same set of pairwise keys. If, however, the same ephemeral sender key
73
 * is used for multiple messages (e.g. it is cached as a performance
73
 *  is used for multiple messages (e.g. it is cached as a performance
74
 * optimization) then a separate partyAInfo MUST be used for each
74
 *  optimization) then a separate partyAInfo MUST be used for each
75
 * message. All implementations of this standard MUST implement
75
 *  message. All implementations of this standard MUST implement
76
 * Ephemeral-Static mode."
76
 *  Ephemeral-Static mode.&quot;
77
 * </pre>
77
 * </pre>
78
 *
78
 * <p>
79
 * <p>Reference:</p>
79
 * Reference:
80
 * <ol>
80
 * <ol>
81
 *    <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
81
 * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
82
 *    Agreement Method</a><br>
82
 * Agreement Method</a><br>
83
 *    Eric Rescorla.</li>
83
 * Eric Rescorla.</li>
84
 *    <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
84
 * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
85
 *    Applied Cryptography.<br>
85
 * Applied Cryptography.<br>
86
 *    CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
86
 * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
87
 *    Menezes, A., van Oorschot, P. and S. Vanstone.</li>
87
 * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
88
 * </ol>
88
 * </ol>
89
 */
89
 */
90
public abstract class ElGamalKeyAgreement extends BaseKeyAgreementParty
90
public abstract class ElGamalKeyAgreement
91
    extends BaseKeyAgreementParty
91
{
92
{
92
93
  // Constants and variables
94
  // -------------------------------------------------------------------------
95
96
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.elgamal.ka.prng";
93
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.elgamal.ka.prng";
97
94
  public static final String KA_ELGAMAL_RECIPIENT_PRIVATE_KEY =
98
  public static final String KA_ELGAMAL_RECIPIENT_PRIVATE_KEY = "gnu.crypto.elgamal.ka.recipient.private.key";
95
      "gnu.crypto.elgamal.ka.recipient.private.key";
99
96
  public static final String KA_ELGAMAL_RECIPIENT_PUBLIC_KEY =
100
  public static final String KA_ELGAMAL_RECIPIENT_PUBLIC_KEY = "gnu.crypto.elgamal.ka.recipient.public.key";
97
      "gnu.crypto.elgamal.ka.recipient.public.key";
101
102
  /** The shared secret key. */
98
  /** The shared secret key. */
103
  protected BigInteger ZZ;
99
  protected BigInteger ZZ;
104
100
105
  // Constructor(s)
106
  // -------------------------------------------------------------------------
107
108
  protected ElGamalKeyAgreement()
101
  protected ElGamalKeyAgreement()
109
  {
102
  {
110
    super(Registry.ELGAMAL_KA);
103
    super(Registry.ELGAMAL_KA);
111
  }
104
  }
112
105
113
  // Class methods
114
  // -------------------------------------------------------------------------
115
116
  // Instance methods
117
  // -------------------------------------------------------------------------
118
119
  // implementation of common abstract methods in BaseKeyAGreementParty ------
120
121
  protected byte[] engineSharedSecret() throws KeyAgreementException
106
  protected byte[] engineSharedSecret() throws KeyAgreementException
122
  {
107
  {
123
    return Util.trim(ZZ);
108
    return Util.trim(ZZ);
(-)dh/ElGamalReceiver.java (-29 / +7 lines)
Lines 49-81 Link Here
49
import javax.crypto.interfaces.DHPrivateKey;
49
import javax.crypto.interfaces.DHPrivateKey;
50
50
51
/**
51
/**
52
 * <p>This implementation is the receiver's part of the ElGamal key agreement
52
 * This implementation is the receiver's part of the ElGamal key agreement
53
 * exchange (B in [HAC]).</p>
53
 * exchange (B in [HAC]).
54
 *
54
 * 
55
 * @see ElGamalKeyAgreement
55
 * @see ElGamalKeyAgreement
56
 */
56
 */
57
public class ElGamalReceiver extends ElGamalKeyAgreement
57
public class ElGamalReceiver
58
    extends ElGamalKeyAgreement
58
{
59
{
59
60
  // Constants and variables
61
  // -------------------------------------------------------------------------
62
63
  /** The recipient's private key. */
60
  /** The recipient's private key. */
64
  private DHPrivateKey B;
61
  private DHPrivateKey B;
65
62
66
  // Constructor(s)
67
  // -------------------------------------------------------------------------
68
69
  // default 0-arguments constructor
63
  // default 0-arguments constructor
70
64
71
  // Class methods
72
  // -------------------------------------------------------------------------
73
74
  // Instance methods
75
  // -------------------------------------------------------------------------
76
77
  // implementation of abstract methods in base class ------------------------
78
79
  protected void engineInit(Map attributes) throws KeyAgreementException
65
  protected void engineInit(Map attributes) throws KeyAgreementException
80
  {
66
  {
81
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
67
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
Lines 83-91 Link Here
83
    // a keypair and publishes its public key
69
    // a keypair and publishes its public key
84
    B = (DHPrivateKey) attributes.get(KA_ELGAMAL_RECIPIENT_PRIVATE_KEY);
70
    B = (DHPrivateKey) attributes.get(KA_ELGAMAL_RECIPIENT_PRIVATE_KEY);
85
    if (B == null)
71
    if (B == null)
86
      {
72
      throw new KeyAgreementException("missing recipient private key");
87
        throw new KeyAgreementException("missing recipient private key");
88
      }
89
  }
73
  }
90
74
91
  protected OutgoingMessage engineProcessMessage(IncomingMessage in)
75
  protected OutgoingMessage engineProcessMessage(IncomingMessage in)
Lines 100-107 Link Here
100
      }
84
      }
101
  }
85
  }
102
86
103
  // own methods -------------------------------------------------------------
104
105
  private OutgoingMessage computeSharedSecret(IncomingMessage in)
87
  private OutgoingMessage computeSharedSecret(IncomingMessage in)
106
      throws KeyAgreementException
88
      throws KeyAgreementException
107
  {
89
  {
Lines 109-120 Link Here
109
    // K = (g^x)^xb mod p
91
    // K = (g^x)^xb mod p
110
    BigInteger m1 = in.readMPI();
92
    BigInteger m1 = in.readMPI();
111
    if (m1 == null)
93
    if (m1 == null)
112
      {
94
      throw new KeyAgreementException("missing message (1)");
113
        throw new KeyAgreementException("missing message (1)");
114
      }
115
116
    ZZ = m1.modPow(B.getX(), B.getParams().getP()); // ZZ = (ya ^ xb) mod p
95
    ZZ = m1.modPow(B.getX(), B.getParams().getP()); // ZZ = (ya ^ xb) mod p
117
118
    complete = true;
96
    complete = true;
119
    return null;
97
    return null;
120
  }
98
  }
(-)dh/ElGamalSender.java (-28 / +6 lines)
Lines 49-81 Link Here
49
import javax.crypto.interfaces.DHPublicKey;
49
import javax.crypto.interfaces.DHPublicKey;
50
50
51
/**
51
/**
52
 * <p>This implementation is the sender's part of the ElGamal key agreement
52
 * This implementation is the sender's part of the ElGamal key agreement
53
 * exchange (A in [HAC]).</p>
53
 * exchange (A in [HAC]).
54
 *
54
 * 
55
 * @see ElGamalKeyAgreement
55
 * @see ElGamalKeyAgreement
56
 */
56
 */
57
public class ElGamalSender extends ElGamalKeyAgreement
57
public class ElGamalSender
58
    extends ElGamalKeyAgreement
58
{
59
{
59
60
  // Constants and variables
61
  // -------------------------------------------------------------------------
62
63
  /** The recipient's public key. */
60
  /** The recipient's public key. */
64
  private DHPublicKey B;
61
  private DHPublicKey B;
65
62
66
  // Constructor(s)
67
  // -------------------------------------------------------------------------
68
69
  // default 0-arguments constructor
63
  // default 0-arguments constructor
70
64
71
  // Class methods
72
  // -------------------------------------------------------------------------
73
74
  // Instance methods
75
  // -------------------------------------------------------------------------
76
77
  // implementation of abstract methods in base class ------------------------
78
79
  protected void engineInit(Map attributes) throws KeyAgreementException
65
  protected void engineInit(Map attributes) throws KeyAgreementException
80
  {
66
  {
81
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
67
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
Lines 83-91 Link Here
83
    // a keypair and publishes its public key
69
    // a keypair and publishes its public key
84
    B = (DHPublicKey) attributes.get(KA_ELGAMAL_RECIPIENT_PUBLIC_KEY);
70
    B = (DHPublicKey) attributes.get(KA_ELGAMAL_RECIPIENT_PUBLIC_KEY);
85
    if (B == null)
71
    if (B == null)
86
      {
72
      throw new KeyAgreementException("missing recipient public key");
87
        throw new KeyAgreementException("missing recipient public key");
88
      }
89
  }
73
  }
90
74
91
  protected OutgoingMessage engineProcessMessage(IncomingMessage in)
75
  protected OutgoingMessage engineProcessMessage(IncomingMessage in)
Lines 100-114 Link Here
100
      }
84
      }
101
  }
85
  }
102
86
103
  // own methods -------------------------------------------------------------
104
105
  private OutgoingMessage computeSharedSecret(IncomingMessage in)
87
  private OutgoingMessage computeSharedSecret(IncomingMessage in)
106
      throws KeyAgreementException
88
      throws KeyAgreementException
107
  {
89
  {
108
    BigInteger p = B.getParams().getP();
90
    BigInteger p = B.getParams().getP();
109
    BigInteger g = B.getParams().getG();
91
    BigInteger g = B.getParams().getG();
110
    BigInteger yb = B.getY();
92
    BigInteger yb = B.getY();
111
112
    // A chooses a random integer x, 1 <= x <= p-2
93
    // A chooses a random integer x, 1 <= x <= p-2
113
    // rfc-2631 restricts x to only be in [2, p-1]
94
    // rfc-2631 restricts x to only be in [2, p-1]
114
    BigInteger p_minus_2 = p.subtract(TWO);
95
    BigInteger p_minus_2 = p.subtract(TWO);
Lines 120-133 Link Here
120
        x = new BigInteger(1, xBytes);
101
        x = new BigInteger(1, xBytes);
121
      }
102
      }
122
    while (x.compareTo(TWO) >= 0 && x.compareTo(p_minus_2) <= 0);
103
    while (x.compareTo(TWO) >= 0 && x.compareTo(p_minus_2) <= 0);
123
124
    // A sends B the message: g^x mod p
104
    // A sends B the message: g^x mod p
125
    OutgoingMessage result = new OutgoingMessage();
105
    OutgoingMessage result = new OutgoingMessage();
126
    result.writeMPI(g.modPow(x, p));
106
    result.writeMPI(g.modPow(x, p));
127
128
    // A computes the key as K = (yb)^x mod p
107
    // A computes the key as K = (yb)^x mod p
129
    ZZ = yb.modPow(x, p); // ZZ = (yb ^ xa) mod p
108
    ZZ = yb.modPow(x, p); // ZZ = (yb ^ xa) mod p
130
131
    complete = true;
109
    complete = true;
132
    return result;
110
    return result;
133
  }
111
  }
(-)dh/GnuDHKey.java (-61 / +27 lines)
Lines 49-97 Link Here
49
import javax.crypto.spec.DHParameterSpec;
49
import javax.crypto.spec.DHParameterSpec;
50
50
51
/**
51
/**
52
 * <p>A base asbtract class for both public and private Diffie-Hellman keys. It
52
 * A base asbtract class for both public and private Diffie-Hellman keys. It
53
 * encapsulates the two DH numbers: <code>p</code>, and <code>g</code>.</p>
53
 * encapsulates the two DH numbers: <code>p</code>, and <code>g</code>.
54
 *
54
 * <p>
55
 * <p>According to the JDK, cryptographic <i>Keys</i> all have a <i>format</i>.
55
 * According to the JDK, cryptographic <i>Keys</i> all have a <i>format</i>.
56
 * The format used in this implementation is called <i>Raw</i>, and basically
56
 * The format used in this implementation is called <i>Raw</i>, and basically
57
 * consists of the raw byte sequences of algorithm parameters. The exact order
57
 * consists of the raw byte sequences of algorithm parameters. The exact order
58
 * of the byte sequences and the implementation details are given in each of
58
 * of the byte sequences and the implementation details are given in each of the
59
 * the relevant <code>getEncoded()</code> methods of each of the private and
59
 * relevant <code>getEncoded()</code> methods of each of the private and
60
 * public keys.</p>
60
 * public keys.
61
 *
61
 * <p>
62
 * <p>Reference:</p>
62
 * Reference:
63
 * <ol>
63
 * <ol>
64
 *    <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
64
 * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
65
 *    Agreement Method</a><br>
65
 * Agreement Method</a><br>
66
 *    Eric Rescorla.</li>
66
 * Eric Rescorla.</li>
67
 * </ol>
67
 * </ol>
68
 */
68
 */
69
public abstract class GnuDHKey implements Key, DHKey
69
public abstract class GnuDHKey
70
    implements Key, DHKey
70
{
71
{
71
72
  // Constants and variables
73
  // -------------------------------------------------------------------------
74
75
  /** The public prime q. A prime divisor of p-1. */
72
  /** The public prime q. A prime divisor of p-1. */
76
  protected BigInteger q;
73
  protected BigInteger q;
77
78
  /** The public prime p. */
74
  /** The public prime p. */
79
  protected BigInteger p;
75
  protected BigInteger p;
80
81
  /** The generator g. */
76
  /** The generator g. */
82
  protected BigInteger g;
77
  protected BigInteger g;
83
84
  /**
78
  /**
85
   * Identifier of the default encoding format to use when externalizing the
79
   * Identifier of the default encoding format to use when externalizing the key
86
   * key material.
80
   * material.
87
   */
81
   */
88
  protected final int defaultFormat;
82
  protected final int defaultFormat;
89
  /** String representation of this key. Cached for speed. */
83
  /** String representation of this key. Cached for speed. */
90
  private transient String str;
84
  private transient String str;
91
85
92
  // Constructor(s)
93
  // -------------------------------------------------------------------------
94
95
  /**
86
  /**
96
   * Trivial protected constructor.
87
   * Trivial protected constructor.
97
   * 
88
   * 
Lines 112-139 Link Here
112
    this.g = g;
103
    this.g = g;
113
  }
104
  }
114
105
115
  // Class methods
116
  // -------------------------------------------------------------------------
117
118
  // Instance methods
119
  // -------------------------------------------------------------------------
120
121
  // javax.crypto.interfaces.DHKey interface implementation ------------------
122
123
  public DHParameterSpec getParams()
106
  public DHParameterSpec getParams()
124
  {
107
  {
125
    if (q == null)
108
    if (q == null)
126
      {
109
      return new DHParameterSpec(p, g);
127
        return new DHParameterSpec(p, g);
110
    return new DHParameterSpec(p, g, q.bitLength());
128
      }
129
    else
130
      {
131
        return new DHParameterSpec(p, g, q.bitLength());
132
      }
133
  }
111
  }
134
112
135
  // java.security.Key interface implementation ------------------------------
136
137
  public String getAlgorithm()
113
  public String getAlgorithm()
138
  {
114
  {
139
    return Registry.DH_KPG;
115
    return Registry.DH_KPG;
Lines 150-181 Link Here
150
    return FormatUtil.getEncodingShortName(defaultFormat);
126
    return FormatUtil.getEncodingShortName(defaultFormat);
151
  }
127
  }
152
128
153
  // Other instance methods --------------------------------------------------
154
155
  public BigInteger getQ()
129
  public BigInteger getQ()
156
  {
130
  {
157
    return q;
131
    return q;
158
  }
132
  }
159
133
160
  /**
134
  /**
161
   * <p>Returns <code>true</code> if the designated object is an instance of
135
   * Returns <code>true</code> if the designated object is an instance of
162
   * {@link DHKey} and has the same Diffie-Hellman parameter values as this
136
   * {@link DHKey} and has the same Diffie-Hellman parameter values as this one.
163
   * one.</p>
137
   * 
164
   *
165
   * @param obj the other non-null DH key to compare to.
138
   * @param obj the other non-null DH key to compare to.
166
   * @return <code>true</code> if the designated object is of the same type and
139
   * @return <code>true</code> if the designated object is of the same type
167
   * value as this one.
140
   *         and value as this one.
168
   */
141
   */
169
  public boolean equals(Object obj)
142
  public boolean equals(Object obj)
170
  {
143
  {
171
    if (obj == null)
144
    if (obj == null)
172
      {
145
      return false;
173
        return false;
146
    if (! (obj instanceof DHKey))
174
      }
147
      return false;
175
    if (!(obj instanceof DHKey))
176
      {
177
        return false;
178
      }
179
    DHKey that = (DHKey) obj;
148
    DHKey that = (DHKey) obj;
180
    return p.equals(that.getParams().getP())
149
    return p.equals(that.getParams().getP())
181
           && g.equals(that.getParams().getG());
150
           && g.equals(that.getParams().getG());
Lines 192-206 Link Here
192
          sb.append("q=null,");
161
          sb.append("q=null,");
193
        else
162
        else
194
          sb.append("q=0x").append(q.toString(16)).append(",");
163
          sb.append("q=0x").append(q.toString(16)).append(",");
195
        sb.append(ls)
164
        sb.append(ls).append("p=0x").append(p.toString(16)).append(",").append(ls)
196
            .append("p=0x").append(p.toString(16)).append(",").append(ls)
197
            .append("g=0x").append(g.toString(16));
165
            .append("g=0x").append(g.toString(16));
198
        str = sb.toString();
166
        str = sb.toString();
199
      }
167
      }
200
    return str;
168
    return str;
201
  }
169
  }
202
170
203
  // abstract methods to be implemented by subclasses ------------------------
204
205
  public abstract byte[] getEncoded(int format);
171
  public abstract byte[] getEncoded(int format);
206
}
172
}
(-)dh/GnuDHKeyPairGenerator.java (-67 / +15 lines)
Lines 56-71 Link Here
56
import javax.crypto.spec.DHParameterSpec;
56
import javax.crypto.spec.DHParameterSpec;
57
57
58
/**
58
/**
59
 * <p>An implementation of a Diffie-Hellman keypair generator.</p>
59
 * An implementation of a Diffie-Hellman keypair generator.
60
 *
60
 * <p>
61
 * <p>Reference:</p>
61
 * Reference:
62
 * <ol>
62
 * <ol>
63
 *    <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
63
 * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
64
 *    Agreement Method</a><br>
64
 * Agreement Method</a><br>
65
 *    Eric Rescorla.</li>
65
 * Eric Rescorla.</li>
66
 * </ol>
66
 * </ol>
67
 */
67
 */
68
public class GnuDHKeyPairGenerator implements IKeyPairGenerator
68
public class GnuDHKeyPairGenerator
69
    implements IKeyPairGenerator
69
{
70
{
70
  private static final Logger log = Logger.getLogger(GnuDHKeyPairGenerator.class.getName());
71
  private static final Logger log = Logger.getLogger(GnuDHKeyPairGenerator.class.getName());
71
  /**
72
  /**
Lines 73-151 Link Here
73
   * default is to use a classloader singleton from {@link PRNG}.
74
   * default is to use a classloader singleton from {@link PRNG}.
74
   */
75
   */
75
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dh.prng";
76
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.dh.prng";
76
77
  /**
77
  /**
78
   * Property name of an optional {@link DHGenParameterSpec} or
78
   * Property name of an optional {@link DHGenParameterSpec} or
79
   * {@link DHParameterSpec} instance to use for this generator.
79
   * {@link DHParameterSpec} instance to use for this generator.
80
   */
80
   */
81
  public static final String DH_PARAMETERS = "gnu.crypto.dh.params";
81
  public static final String DH_PARAMETERS = "gnu.crypto.dh.params";
82
83
  /** Property name of the size in bits (Integer) of the public prime (p). */
82
  /** Property name of the size in bits (Integer) of the public prime (p). */
84
  public static final String PRIME_SIZE = "gnu.crypto.dh.L";
83
  public static final String PRIME_SIZE = "gnu.crypto.dh.L";
85
86
  /** Property name of the size in bits (Integer) of the private exponent (x). */
84
  /** Property name of the size in bits (Integer) of the private exponent (x). */
87
  public static final String EXPONENT_SIZE = "gnu.crypto.dh.m";
85
  public static final String EXPONENT_SIZE = "gnu.crypto.dh.m";
88
89
  /**
86
  /**
90
   * Property name of the preferred encoding format to use when externalizing
87
   * Property name of the preferred encoding format to use when externalizing
91
   * generated instance of key-pairs from this generator. The property is taken
88
   * generated instance of key-pairs from this generator. The property is taken
92
   * to be an {@link Integer} that encapsulates an encoding format identifier.
89
   * to be an {@link Integer} that encapsulates an encoding format identifier.
93
   */
90
   */
94
  public static final String PREFERRED_ENCODING_FORMAT = "gnu.crypto.dh.encoding";
91
  public static final String PREFERRED_ENCODING_FORMAT = "gnu.crypto.dh.encoding";
95
96
  /** Default value for the size in bits of the public prime (p). */
92
  /** Default value for the size in bits of the public prime (p). */
97
  //   private static final int DEFAULT_PRIME_SIZE = 1024;
98
  public static final int DEFAULT_PRIME_SIZE = 512;
93
  public static final int DEFAULT_PRIME_SIZE = 512;
99
100
  /** Default value for the size in bits of the private exponent (x). */
94
  /** Default value for the size in bits of the private exponent (x). */
101
  public static final int DEFAULT_EXPONENT_SIZE = 160;
95
  public static final int DEFAULT_EXPONENT_SIZE = 160;
102
103
  /** Default encoding format to use when none was specified. */
96
  /** Default encoding format to use when none was specified. */
104
  private static final int DEFAULT_ENCODING_FORMAT = Registry.RAW_ENCODING_ID;
97
  private static final int DEFAULT_ENCODING_FORMAT = Registry.RAW_ENCODING_ID;
105
106
  /** The SHA instance to use. */
98
  /** The SHA instance to use. */
107
  private Sha160 sha = new Sha160();
99
  private Sha160 sha = new Sha160();
108
109
  /** The optional {@link SecureRandom} instance to use. */
100
  /** The optional {@link SecureRandom} instance to use. */
110
  private SecureRandom rnd = null;
101
  private SecureRandom rnd = null;
111
112
  /** The desired size in bits of the public prime (p). */
102
  /** The desired size in bits of the public prime (p). */
113
  private int l;
103
  private int l;
114
115
  /** The desired size in bits of the private exponent (x). */
104
  /** The desired size in bits of the private exponent (x). */
116
  private int m;
105
  private int m;
117
118
  private BigInteger seed;
106
  private BigInteger seed;
119
120
  private BigInteger counter;
107
  private BigInteger counter;
121
122
  private BigInteger q;
108
  private BigInteger q;
123
124
  private BigInteger p;
109
  private BigInteger p;
125
126
  private BigInteger j;
110
  private BigInteger j;
127
128
  private BigInteger g;
111
  private BigInteger g;
129
130
  /** Our default source of randomness. */
112
  /** Our default source of randomness. */
131
  private PRNG prng = null;
113
  private PRNG prng = null;
132
133
  /** Preferred encoding format of generated keys. */
114
  /** Preferred encoding format of generated keys. */
134
  private int preferredFormat;
115
  private int preferredFormat;
135
116
136
  // Constructor(s)
137
  // -------------------------------------------------------------------------
138
139
  // default 0-arguments constructor
117
  // default 0-arguments constructor
140
118
141
  // Class methods
142
  // -------------------------------------------------------------------------
143
144
  // Instance methods
145
  // -------------------------------------------------------------------------
146
147
  // gnu.crypto.keys.IKeyPairGenerator interface implementation ---------------
148
149
  public String name()
119
  public String name()
150
  {
120
  {
151
    return Registry.DH_KPG;
121
    return Registry.DH_KPG;
Lines 155-165 Link Here
155
  {
125
  {
156
    // do we have a SecureRandom, or should we use our own?
126
    // do we have a SecureRandom, or should we use our own?
157
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
127
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
158
159
    // are we given a set of Diffie-Hellman generation parameters or we shall
128
    // are we given a set of Diffie-Hellman generation parameters or we shall
160
    // use our own?
129
    // use our own?
161
    Object params = attributes.get(DH_PARAMETERS);
130
    Object params = attributes.get(DH_PARAMETERS);
162
163
    // find out the desired sizes
131
    // find out the desired sizes
164
    if (params instanceof DHGenParameterSpec)
132
    if (params instanceof DHGenParameterSpec)
165
      {
133
      {
Lines 177-183 Link Here
177
        g = jceSpec.getG();
145
        g = jceSpec.getG();
178
        l = p.bitLength();
146
        l = p.bitLength();
179
        m = jceSpec.getL();
147
        m = jceSpec.getL();
180
181
        // If no exponent size was given, generate an exponent as
148
        // If no exponent size was given, generate an exponent as
182
        // large as the prime.
149
        // large as the prime.
183
        if (m == 0)
150
        if (m == 0)
Lines 190-210 Link Here
190
        bi = (Integer) attributes.get(EXPONENT_SIZE);
157
        bi = (Integer) attributes.get(EXPONENT_SIZE);
191
        m = (bi == null ? DEFAULT_EXPONENT_SIZE : bi.intValue());
158
        m = (bi == null ? DEFAULT_EXPONENT_SIZE : bi.intValue());
192
      }
159
      }
193
194
    //      if ((L % 256) != 0 || L < 1024) {
195
    if ((l % 256) != 0 || l < DEFAULT_PRIME_SIZE)
160
    if ((l % 256) != 0 || l < DEFAULT_PRIME_SIZE)
196
      {
161
      throw new IllegalArgumentException("invalid modulus size");
197
        throw new IllegalArgumentException("invalid modulus size");
198
      }
199
    if ((m % 8) != 0 || m < DEFAULT_EXPONENT_SIZE)
162
    if ((m % 8) != 0 || m < DEFAULT_EXPONENT_SIZE)
200
      {
163
      throw new IllegalArgumentException("invalid exponent size");
201
        throw new IllegalArgumentException("invalid exponent size");
202
      }
203
    if (m > l)
164
    if (m > l)
204
      {
165
      throw new IllegalArgumentException("exponent size > modulus size");
205
        throw new IllegalArgumentException("exponent size > modulus size");
206
      }
207
208
    // what is the preferred encoding format
166
    // what is the preferred encoding format
209
    Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
167
    Integer formatID = (Integer) attributes.get(PREFERRED_ENCODING_FORMAT);
210
    preferredFormat = formatID == null ? DEFAULT_ENCODING_FORMAT
168
    preferredFormat = formatID == null ? DEFAULT_ENCODING_FORMAT
Lines 232-243 Link Here
232
            log.fine("g: 0x" + g.toString(16));
190
            log.fine("g: 0x" + g.toString(16));
233
          }
191
          }
234
      }
192
      }
235
236
    // generate a private number x of length m such as: 1 < x < q - 1
193
    // generate a private number x of length m such as: 1 < x < q - 1
237
    BigInteger q_minus_1 = null;
194
    BigInteger q_minus_1 = null;
238
    if (q != null)
195
    if (q != null)
239
      q_minus_1 = q.subtract(BigInteger.ONE);
196
      q_minus_1 = q.subtract(BigInteger.ONE);
240
241
    // We already check if m is modulo 8 in `setup.' This could just
197
    // We already check if m is modulo 8 in `setup.' This could just
242
    // be m >>> 3.
198
    // be m >>> 3.
243
    byte[] mag = new byte[(m + 7) / 8];
199
    byte[] mag = new byte[(m + 7) / 8];
Lines 248-278 Link Here
248
        x = new BigInteger(1, mag);
204
        x = new BigInteger(1, mag);
249
        if (x.bitLength() == m && x.compareTo(BigInteger.ONE) > 0
205
        if (x.bitLength() == m && x.compareTo(BigInteger.ONE) > 0
250
            && (q_minus_1 == null || x.compareTo(q_minus_1) < 0))
206
            && (q_minus_1 == null || x.compareTo(q_minus_1) < 0))
251
          {
207
          break;
252
            break;
253
          }
254
      }
208
      }
255
    BigInteger y = g.modPow(x, p);
209
    BigInteger y = g.modPow(x, p);
256
257
    PrivateKey secK = new GnuDHPrivateKey(preferredFormat, q, p, g, x);
210
    PrivateKey secK = new GnuDHPrivateKey(preferredFormat, q, p, g, x);
258
    PublicKey pubK = new GnuDHPublicKey(preferredFormat, q, p, g, y);
211
    PublicKey pubK = new GnuDHPublicKey(preferredFormat, q, p, g, y);
259
260
    return new KeyPair(pubK, secK);
212
    return new KeyPair(pubK, secK);
261
  }
213
  }
262
214
263
  // other methods -----------------------------------------------------------
264
265
  /**
215
  /**
266
   * <p>Fills the designated byte array with random data.</p>
216
   * Fills the designated byte array with random data.
267
   *
217
   * 
268
   * @param buffer the byte array to fill with random data.
218
   * @param buffer the byte array to fill with random data.
269
   */
219
   */
270
  private void nextRandomBytes(byte[] buffer)
220
  private void nextRandomBytes(byte[] buffer)
271
  {
221
  {
272
    if (rnd != null)
222
    if (rnd != null)
273
      {
223
      rnd.nextBytes(buffer);
274
        rnd.nextBytes(buffer);
275
      }
276
    else
224
    else
277
      getDefaultPRNG().nextBytes(buffer);
225
      getDefaultPRNG().nextBytes(buffer);
278
  }
226
  }
(-)dh/GnuDHPrivateKey.java (-40 / +24 lines)
Lines 48-76 Link Here
48
import javax.crypto.interfaces.DHPrivateKey;
48
import javax.crypto.interfaces.DHPrivateKey;
49
49
50
/**
50
/**
51
 * <p>An implementation of the Diffie-Hellman private key.</p>
51
 * An implementation of the Diffie-Hellman private key.
52
 *
52
 * <p>
53
 * <p>Reference:</p>
53
 * Reference:
54
 * <ol>
54
 * <ol>
55
 *    <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
55
 * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
56
 *    Agreement Method</a><br>
56
 * Agreement Method</a><br>
57
 *    Eric Rescorla.</li>
57
 * Eric Rescorla.</li>
58
 * </ol>
58
 * </ol>
59
 */
59
 */
60
public class GnuDHPrivateKey extends GnuDHKey implements DHPrivateKey
60
public class GnuDHPrivateKey
61
    extends GnuDHKey
62
    implements DHPrivateKey
61
{
63
{
62
63
  // Constants and variables
64
  // -------------------------------------------------------------------------
65
66
  /** The private exponent. */
64
  /** The private exponent. */
67
  private final BigInteger x;
65
  private final BigInteger x;
68
  /** String representation of this key. Cached for speed. */
66
  /** String representation of this key. Cached for speed. */
69
  private transient String str;
67
  private transient String str;
70
68
71
  // Constructor(s)
72
  // -------------------------------------------------------------------------
73
74
  /**
69
  /**
75
   * Convenience constructor. Calls the constructor with five arguments passing
70
   * Convenience constructor. Calls the constructor with five arguments passing
76
   * {@link Registry#RAW_ENCODING_ID} as the value of its first argument.
71
   * {@link Registry#RAW_ENCODING_ID} as the value of its first argument.
Lines 96-126 Link Here
96
   * @param g the generator of the group.
91
   * @param g the generator of the group.
97
   * @param x the private value x.
92
   * @param x the private value x.
98
   */
93
   */
99
  public GnuDHPrivateKey(int preferredFormat,
94
  public GnuDHPrivateKey(int preferredFormat, BigInteger q, BigInteger p,
100
                         BigInteger q, BigInteger p, BigInteger g, BigInteger x)
95
                         BigInteger g, BigInteger x)
101
  {
96
  {
102
    super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.PKCS8_ENCODING_ID
97
    super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.PKCS8_ENCODING_ID
103
                                                       : preferredFormat,
98
                                                       : preferredFormat,
104
          q, p, g);
99
          q, p, g);
105
106
    this.x = x;
100
    this.x = x;
107
  }
101
  }
108
102
109
  // Class methods
110
  // -------------------------------------------------------------------------
111
112
  /**
103
  /**
113
   * <p>A class method that takes the output of the <code>encodePrivateKey()</code>
104
   * A class method that takes the output of the <code>encodePrivateKey()</code>
114
   * method of a DH keypair codec object (an instance implementing
105
   * method of a DH keypair codec object (an instance implementing
115
   * {@link IKeyPairCodec} for DH keys, and re-constructs an instance of this
106
   * {@link IKeyPairCodec} for DH keys, and re-constructs an instance of this
116
   * object.</p>
107
   * object.
117
   *
108
   * 
118
   * @param k the contents of a previously encoded instance of this object.
109
   * @param k the contents of a previously encoded instance of this object.
119
   * @exception ArrayIndexOutOfBoundsException if there is not enough bytes,
110
   * @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
120
   * in <code>k</code>, to represent a valid encoding of an instance of
111
   *              <code>k</code>, to represent a valid encoding of an
121
   * this object.
112
   *              instance of this object.
122
   * @exception IllegalArgumentException if the byte sequence does not
113
   * @exception IllegalArgumentException if the byte sequence does not represent
123
   * represent a valid encoding of an instance of this object.
114
   *              a valid encoding of an instance of this object.
124
   */
115
   */
125
  public static GnuDHPrivateKey valueOf(byte[] k)
116
  public static GnuDHPrivateKey valueOf(byte[] k)
126
  {
117
  {
Lines 133-162 Link Here
133
      catch (IllegalArgumentException ignored)
124
      catch (IllegalArgumentException ignored)
134
        {
125
        {
135
        }
126
        }
136
137
    // try PKCS#8 codec
127
    // try PKCS#8 codec
138
    return (GnuDHPrivateKey) new DHKeyPairPKCS8Codec().decodePrivateKey(k);
128
    return (GnuDHPrivateKey) new DHKeyPairPKCS8Codec().decodePrivateKey(k);
139
  }
129
  }
140
130
141
  // Instance methods
142
  // -------------------------------------------------------------------------
143
144
  // javax.crypto.interfaces.DHPrivateKey interface implementation -----------
145
146
  public BigInteger getX()
131
  public BigInteger getX()
147
  {
132
  {
148
    return x;
133
    return x;
149
  }
134
  }
150
135
151
  // other methods -----------------------------------------------------------
152
153
  /**
136
  /**
154
   * <p>Returns the encoded form of this private key according to the
137
   * Returns the encoded form of this private key according to the designated
155
   * designated format.</p>
138
   * format.
156
   *
139
   * 
157
   * @param format the desired format identifier of the resulting encoding.
140
   * @param format the desired format identifier of the resulting encoding.
158
   * @return the byte sequence encoding this key according to the designated
141
   * @return the byte sequence encoding this key according to the designated
159
   * format.
142
   *         format.
160
   * @exception IllegalArgumentException if the format is not supported.
143
   * @exception IllegalArgumentException if the format is not supported.
161
   * @see DHKeyPairRawCodec
144
   * @see DHKeyPairRawCodec
162
   */
145
   */
Lines 197-202 Link Here
197
    DHPrivateKey that = (DHPrivateKey) obj;
180
    DHPrivateKey that = (DHPrivateKey) obj;
198
    return super.equals(that) && x.equals(that.getX());
181
    return super.equals(that) && x.equals(that.getX());
199
  }
182
  }
183
200
  public String toString()
184
  public String toString()
201
  {
185
  {
202
    if (str == null)
186
    if (str == null)
(-)dh/GnuDHPublicKey.java (-40 / +23 lines)
Lines 47-74 Link Here
47
import javax.crypto.interfaces.DHPublicKey;
47
import javax.crypto.interfaces.DHPublicKey;
48
48
49
/**
49
/**
50
 * <p>An implementation of the Diffie-Hellman public key.</p>
50
 * An implementation of the Diffie-Hellman public key.
51
 *
51
 * <p>
52
 * <p>Reference:</p>
52
 * Reference:
53
 * <ol>
53
 * <ol>
54
 *    <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
54
 * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
55
 *    Agreement Method</a><br>
55
 * Agreement Method</a><br>
56
 *    Eric Rescorla.</li>
56
 * Eric Rescorla.</li>
57
 * </ol>
57
 * </ol>
58
 */
58
 */
59
public class GnuDHPublicKey extends GnuDHKey implements DHPublicKey
59
public class GnuDHPublicKey
60
    extends GnuDHKey
61
    implements DHPublicKey
60
{
62
{
61
62
  // Constants and variables
63
  // -------------------------------------------------------------------------
64
65
  private BigInteger y;
63
  private BigInteger y;
66
  /** String representation of this key. Cached for speed. */
64
  /** String representation of this key. Cached for speed. */
67
  private transient String str;
65
  private transient String str;
68
66
69
  // Constructor(s)
70
  // -------------------------------------------------------------------------
71
72
  /**
67
  /**
73
   * Convenience constructor. Calls the constructor with five arguments passing
68
   * Convenience constructor. Calls the constructor with five arguments passing
74
   * {@link Registry#RAW_ENCODING_ID} as the value of its first argument.
69
   * {@link Registry#RAW_ENCODING_ID} as the value of its first argument.
Lines 94-124 Link Here
94
   * @param g the generator of the group.
89
   * @param g the generator of the group.
95
   * @param y the public value y.
90
   * @param y the public value y.
96
   */
91
   */
97
  public GnuDHPublicKey(int preferredFormat,
92
  public GnuDHPublicKey(int preferredFormat, BigInteger q, BigInteger p,
98
                        BigInteger q, BigInteger p, BigInteger g, BigInteger y)
93
                        BigInteger g, BigInteger y)
99
  {
94
  {
100
    super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.X509_ENCODING_ID
95
    super(preferredFormat == Registry.ASN1_ENCODING_ID ? Registry.X509_ENCODING_ID
101
                                                       : preferredFormat,
96
                                                       : preferredFormat,
102
          q, p, g);
97
          q, p, g);
103
104
    this.y = y;
98
    this.y = y;
105
  }
99
  }
106
100
107
  // Class methods
108
  // -------------------------------------------------------------------------
109
110
  /**
101
  /**
111
   * <p>A class method that takes the output of the <code>encodePublicKey()</code>
102
   * A class method that takes the output of the <code>encodePublicKey()</code>
112
   * method of a DH keypair codec object (an instance implementing
103
   * method of a DH keypair codec object (an instance implementing
113
   * {@link IKeyPairCodec} for DSS keys, and re-constructs an instance of this
104
   * {@link IKeyPairCodec} for DSS keys, and re-constructs an instance of this
114
   * object.</p>
115
   *
116
   * @param k the contents of a previously encoded instance of this object.
117
   * @exception ArrayIndexOutOfBoundsException if there is not enough bytes,
118
   * in <code>k</code>, to represent a valid encoding of an instance of this
119
   * object.
105
   * object.
120
   * @exception IllegalArgumentException if the byte sequence does not
106
   * 
121
   * represent a valid encoding of an instance of this object.
107
   * @param k the contents of a previously encoded instance of this object.
108
   * @exception ArrayIndexOutOfBoundsException if there is not enough bytes, in
109
   *              <code>k</code>, to represent a valid encoding of an
110
   *              instance of this object.
111
   * @exception IllegalArgumentException if the byte sequence does not represent
112
   *              a valid encoding of an instance of this object.
122
   */
113
   */
123
  public static GnuDHPublicKey valueOf(byte[] k)
114
  public static GnuDHPublicKey valueOf(byte[] k)
124
  {
115
  {
Lines 131-160 Link Here
131
      catch (IllegalArgumentException ignored)
122
      catch (IllegalArgumentException ignored)
132
        {
123
        {
133
        }
124
        }
134
135
    // try X.509 codec
125
    // try X.509 codec
136
    return (GnuDHPublicKey) new DHKeyPairX509Codec().decodePublicKey(k);
126
    return (GnuDHPublicKey) new DHKeyPairX509Codec().decodePublicKey(k);
137
  }
127
  }
138
128
139
  // Instance methods
140
  // -------------------------------------------------------------------------
141
142
  // javax.crypto.interfaces.DHPublicKey interface implementation ------------
143
144
  public BigInteger getY()
129
  public BigInteger getY()
145
  {
130
  {
146
    return y;
131
    return y;
147
  }
132
  }
148
133
149
  // other methods -----------------------------------------------------------
150
151
  /**
134
  /**
152
   * <p>Returns the encoded form of this public key according to the designated
135
   * Returns the encoded form of this public key according to the designated
153
   * format.</p>
136
   * format.
154
   *
137
   * 
155
   * @param format the desired format identifier of the resulting encoding.
138
   * @param format the desired format identifier of the resulting encoding.
156
   * @return the byte sequence encoding this key according to the designated
139
   * @return the byte sequence encoding this key according to the designated
157
   * format.
140
   *         format.
158
   * @exception IllegalArgumentException if the format is not supported.
141
   * @exception IllegalArgumentException if the format is not supported.
159
   */
142
   */
160
  public byte[] getEncoded(int format)
143
  public byte[] getEncoded(int format)
(-)dh/RFC2631.java (-65 / +28 lines)
Lines 45-98 Link Here
45
import java.security.SecureRandom;
45
import java.security.SecureRandom;
46
46
47
/**
47
/**
48
 * <p>An implementation of the Diffie-Hellman parameter generation as defined in
48
 * An implementation of the Diffie-Hellman parameter generation as defined in
49
 * RFC-2631.</p>
49
 * RFC-2631.
50
 *
50
 * <p>
51
 * <p>Reference:</p>
51
 * Reference:
52
 * <ol>
52
 * <ol>
53
 *    <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
53
 * <li><a href="http://www.ietf.org/rfc/rfc2631.txt">Diffie-Hellman Key
54
 *    Agreement Method</a><br>
54
 * Agreement Method</a><br>
55
 *    Eric Rescorla.</li>
55
 * Eric Rescorla.</li>
56
 * </ol>
56
 * </ol>
57
 */
57
 */
58
public class RFC2631
58
public class RFC2631
59
{
59
{
60
61
  // Constants and variables
62
  // -------------------------------------------------------------------------
63
64
  public static final int DH_PARAMS_SEED = 0;
60
  public static final int DH_PARAMS_SEED = 0;
65
66
  public static final int DH_PARAMS_COUNTER = 1;
61
  public static final int DH_PARAMS_COUNTER = 1;
67
68
  public static final int DH_PARAMS_Q = 2;
62
  public static final int DH_PARAMS_Q = 2;
69
70
  public static final int DH_PARAMS_P = 3;
63
  public static final int DH_PARAMS_P = 3;
71
72
  public static final int DH_PARAMS_J = 4;
64
  public static final int DH_PARAMS_J = 4;
73
74
  public static final int DH_PARAMS_G = 5;
65
  public static final int DH_PARAMS_G = 5;
75
76
  private static final BigInteger TWO = BigInteger.valueOf(2L);
66
  private static final BigInteger TWO = BigInteger.valueOf(2L);
77
78
  /** The SHA instance to use. */
67
  /** The SHA instance to use. */
79
  private Sha160 sha = new Sha160();
68
  private Sha160 sha = new Sha160();
80
81
  /** Length of private modulus and of q. */
69
  /** Length of private modulus and of q. */
82
  private int m;
70
  private int m;
83
84
  /** Length of public modulus p. */
71
  /** Length of public modulus p. */
85
  private int L;
72
  private int L;
86
87
  /** The optional {@link SecureRandom} instance to use. */
73
  /** The optional {@link SecureRandom} instance to use. */
88
  private SecureRandom rnd = null;
74
  private SecureRandom rnd = null;
89
90
  /** Our default source of randomness. */
75
  /** Our default source of randomness. */
91
  private PRNG prng = null;
76
  private PRNG prng = null;
92
77
93
  // Constructor(s)
94
  // -------------------------------------------------------------------------
95
96
  public RFC2631(int m, int L, SecureRandom rnd)
78
  public RFC2631(int m, int L, SecureRandom rnd)
97
  {
79
  {
98
    super();
80
    super();
Lines 102-113 Link Here
102
    this.rnd = rnd;
84
    this.rnd = rnd;
103
  }
85
  }
104
86
105
  // Class methods
106
  // -------------------------------------------------------------------------
107
108
  // Instance methods
109
  // -------------------------------------------------------------------------
110
111
  public BigInteger[] generateParameters()
87
  public BigInteger[] generateParameters()
112
  {
88
  {
113
    int i, j, counter;
89
    int i, j, counter;
Lines 126-140 Link Here
126
      {
102
      {
127
        step4: while (true)
103
        step4: while (true)
128
          {
104
          {
129
            // 4. Select an arbitrary bit string SEED such that length of SEED >= m
105
            // 4. Select an arbitrary bit string SEED such that length of
106
            //    SEED >= m
130
            nextRandomBytes(seedBytes);
107
            nextRandomBytes(seedBytes);
131
            SEED = new BigInteger(1, seedBytes).setBit(m - 1).setBit(0);
108
            SEED = new BigInteger(1, seedBytes).setBit(m - 1).setBit(0);
132
            // 5. Set U = 0
109
            // 5. Set U = 0
133
            U = BigInteger.ZERO;
110
            U = BigInteger.ZERO;
134
            // 6. For i = 0 to m' - 1
111
            // 6. For i = 0 to m' - 1
135
            //       U = U + (SHA1[SEED + i] XOR SHA1[(SEED + m' + i)) * 2^(160 * i)
112
            //    U = U + (SHA1[SEED + i] XOR SHA1[(SEED + m' + i)) * 2^(160 * i)
136
            //    Note that for m=160, this reduces to the algorithm of [FIPS-186]
113
            //    Note that for m=160, this reduces to the algorithm of FIPS-186
137
            //       U = SHA1[SEED] XOR SHA1[(SEED+1) mod 2^160 ].
114
            //    U = SHA1[SEED] XOR SHA1[(SEED+1) mod 2^160 ].
138
            for (i = 0; i < m_; i++)
115
            for (i = 0; i < m_; i++)
139
              {
116
              {
140
                u1 = SEED.add(BigInteger.valueOf(i)).toByteArray();
117
                u1 = SEED.add(BigInteger.valueOf(i)).toByteArray();
Lines 144-174 Link Here
144
                sha.update(u2, 0, u2.length);
121
                sha.update(u2, 0, u2.length);
145
                u2 = sha.digest();
122
                u2 = sha.digest();
146
                for (j = 0; j < u1.length; j++)
123
                for (j = 0; j < u1.length; j++)
147
                  {
124
                  u1[j] ^= u2[j];
148
                    u1[j] ^= u2[j];
149
                  }
150
                U = U.add(new BigInteger(1, u1).multiply(TWO.pow(160 * i)));
125
                U = U.add(new BigInteger(1, u1).multiply(TWO.pow(160 * i)));
151
              }
126
              }
152
            // 5. Form q from U by computing U mod (2^m) and setting the most
127
            // 5. Form q from U by computing U mod (2^m) and setting the most
153
            //    significant bit (the 2^(m-1) bit) and the least significant bit to
128
            //    significant bit (the 2^(m-1) bit) and the least significant
154
            //    1. In terms of boolean operations, q = U OR 2^(m-1) OR 1. Note
129
            //    bit to 1. In terms of boolean operations, q = U OR 2^(m-1) OR
155
            //    that 2^(m-1) < q < 2^m
130
            //    1. Note that 2^(m-1) < q < 2^m
156
            q = U.setBit(m - 1).setBit(0);
131
            q = U.setBit(m - 1).setBit(0);
157
            // 6. Use a robust primality algorithm to test whether q is prime.
132
            // 6. Use a robust primality algorithm to test whether q is prime.
158
            // 7. If q is not prime then go to 4.
133
            // 7. If q is not prime then go to 4.
159
            if (q.isProbablePrime(80))
134
            if (q.isProbablePrime(80))
160
              {
135
              break step4;
161
                break step4;
162
              }
163
          }
136
          }
164
        // 8. Let counter = 0
137
        // 8. Let counter = 0
165
        counter = 0;
138
        counter = 0;
166
        step9: while (true)
139
        step9: while (true)
167
          {
140
          {
168
            // 9. Set R = seed + 2*m' + (L' * counter)
141
            // 9. Set R = seed + 2*m' + (L' * counter)
169
            R = SEED.add(BigInteger.valueOf(2 * m_)).add(
142
            R = SEED
170
                                                         BigInteger.valueOf(L_
143
                .add(BigInteger.valueOf(2 * m_))
171
                                                                            * counter));
144
                .add(BigInteger.valueOf(L_ * counter));
172
            // 10. Set V = 0
145
            // 10. Set V = 0
173
            V = BigInteger.ZERO;
146
            V = BigInteger.ZERO;
174
            // 12. For i = 0 to L'-1 do: V = V + SHA1(R + i) * 2^(160 * i)
147
            // 12. For i = 0 to L'-1 do: V = V + SHA1(R + i) * 2^(160 * i)
Lines 186-194 Link Here
186
            X = W.setBit(L - 1);
159
            X = W.setBit(L - 1);
187
            // 15. Set p = X - (X mod (2*q)) + 1
160
            // 15. Set p = X - (X mod (2*q)) + 1
188
            p = X.add(BigInteger.ONE).subtract(X.mod(TWO.multiply(q)));
161
            p = X.add(BigInteger.ONE).subtract(X.mod(TWO.multiply(q)));
189
            // 16. If p > 2^(L-1) use a robust primality test to test whether p is
162
            // 16. If p > 2^(L-1) use a robust primality test to test whether p
190
            //     prime. Else go to 18.
163
            //     is prime. Else go to 18.
191
            //17. If p is prime output p, q, seed, counter and stop.
164
            // 17. If p is prime output p, q, seed, counter and stop.
192
            if (p.isProbablePrime(80))
165
            if (p.isProbablePrime(80))
193
              {
166
              {
194
                break algorithm;
167
                break algorithm;
Lines 198-209 Link Here
198
            // 19. If counter < (4096 * N) then go to 8.
171
            // 19. If counter < (4096 * N) then go to 8.
199
            // 20. Output "failure"
172
            // 20. Output "failure"
200
            if (counter >= 4096 * N_)
173
            if (counter >= 4096 * N_)
201
              {
174
              continue algorithm;
202
                continue algorithm;
203
              }
204
          }
175
          }
205
      }
176
      }
206
207
    // compute g. from FIPS-186, Appendix 4:
177
    // compute g. from FIPS-186, Appendix 4:
208
    // 1. Generate p and q as specified in Appendix 2.
178
    // 1. Generate p and q as specified in Appendix 2.
209
    // 2. Let e = (p - 1) / q
179
    // 2. Let e = (p - 1) / q
Lines 218-245 Link Here
218
        // 4. Set g = h**e mod p
188
        // 4. Set g = h**e mod p
219
        g = h.modPow(e, p);
189
        g = h.modPow(e, p);
220
        // 5. If g = 1, go to step 3
190
        // 5. If g = 1, go to step 3
221
        if (!g.equals(BigInteger.ONE))
191
        if (! g.equals(BigInteger.ONE))
222
          {
192
          break;
223
            break;
224
          }
225
      }
193
      }
226
227
    return new BigInteger[] { SEED, BigInteger.valueOf(counter), q, p, e, g };
194
    return new BigInteger[] { SEED, BigInteger.valueOf(counter), q, p, e, g };
228
  }
195
  }
229
196
230
  // helper methods ----------------------------------------------------------
231
232
  /**
197
  /**
233
   * <p>Fills the designated byte array with random data.</p>
198
   * Fills the designated byte array with random data.
234
   *
199
   *
235
   * @param buffer the byte array to fill with random data.
200
   * @param buffer the byte array to fill with random data.
236
   */
201
   */
237
  private void nextRandomBytes(byte[] buffer)
202
  private void nextRandomBytes(byte[] buffer)
238
  {
203
  {
239
    if (rnd != null)
204
    if (rnd != null)
240
      {
205
      rnd.nextBytes(buffer);
241
        rnd.nextBytes(buffer);
242
      }
243
    else
206
    else
244
      getDefaultPRNG().nextBytes(buffer);
207
      getDefaultPRNG().nextBytes(buffer);
245
  }
208
  }
(-)srp6/SRP6Host.java (-67 / +15 lines)
Lines 56-120 Link Here
56
import java.util.Map;
56
import java.util.Map;
57
57
58
/**
58
/**
59
 * <p>The implementation of the Host in the SRP-6 key agreement protocol.</p>
59
 * The implementation of the Host in the SRP-6 key agreement protocol.
60
 *
60
 * <p>
61
 * <p>Reference:</p>
61
 * Reference:
62
 * <ol>
62
 * <ol>
63
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
63
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
64
 *    Thomas J. Wu.</li>
64
 * Thomas J. Wu.</li>
65
 * </ol>
65
 * </ol>
66
 */
66
 */
67
public class SRP6Host extends SRP6KeyAgreement
67
public class SRP6Host
68
    extends SRP6KeyAgreement
68
{
69
{
69
70
  // Constants and variables
71
  // -------------------------------------------------------------------------
72
73
  /** The user's ephemeral key pair. */
70
  /** The user's ephemeral key pair. */
74
  private KeyPair hostKeyPair;
71
  private KeyPair hostKeyPair;
75
72
76
  /** The SRP password database. */
73
  /** The SRP password database. */
77
  private SRPAuthInfoProvider passwordDB;
74
  private SRPAuthInfoProvider passwordDB;
78
75
79
  // Constructor(s)
80
  // -------------------------------------------------------------------------
81
82
  // default 0-arguments constructor
76
  // default 0-arguments constructor
83
77
84
  // Class methods
85
  // -------------------------------------------------------------------------
86
87
  // Instance methods
88
  // -------------------------------------------------------------------------
89
90
  // implementation of abstract methods in base class ------------------------
91
92
  protected void engineInit(final Map attributes) throws KeyAgreementException
78
  protected void engineInit(final Map attributes) throws KeyAgreementException
93
  {
79
  {
94
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
80
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
95
    N = (BigInteger) attributes.get(SHARED_MODULUS);
81
    N = (BigInteger) attributes.get(SHARED_MODULUS);
96
    if (N == null)
82
    if (N == null)
97
      {
83
      throw new KeyAgreementException("missing shared modulus");
98
        throw new KeyAgreementException("missing shared modulus");
99
      }
100
    g = (BigInteger) attributes.get(GENERATOR);
84
    g = (BigInteger) attributes.get(GENERATOR);
101
    if (g == null)
85
    if (g == null)
102
      {
86
      throw new KeyAgreementException("missing generator");
103
        throw new KeyAgreementException("missing generator");
104
      }
105
106
    final String md = (String) attributes.get(HASH_FUNCTION);
87
    final String md = (String) attributes.get(HASH_FUNCTION);
107
    if (md == null || "".equals(md.trim()))
88
    if (md == null || md.trim().length() == 0)
108
      {
89
      throw new KeyAgreementException("missing hash function");
109
        throw new KeyAgreementException("missing hash function");
110
      }
111
    srp = SRP.instance(md);
90
    srp = SRP.instance(md);
112
113
    passwordDB = (SRPAuthInfoProvider) attributes.get(HOST_PASSWORD_DB);
91
    passwordDB = (SRPAuthInfoProvider) attributes.get(HOST_PASSWORD_DB);
114
    if (passwordDB == null)
92
    if (passwordDB == null)
115
      {
93
      throw new KeyAgreementException("missing SRP password database");
116
        throw new KeyAgreementException("missing SRP password database");
117
      }
118
  }
94
  }
119
95
120
  protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
96
  protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
Lines 135-148 Link Here
135
    super.engineReset();
111
    super.engineReset();
136
  }
112
  }
137
113
138
  // own methods -------------------------------------------------------------
139
140
  private OutgoingMessage computeSharedSecret(final IncomingMessage in)
114
  private OutgoingMessage computeSharedSecret(final IncomingMessage in)
141
      throws KeyAgreementException
115
      throws KeyAgreementException
142
  {
116
  {
143
    final String I = in.readString();
117
    final String I = in.readString();
144
    final BigInteger A = in.readMPI();
118
    final BigInteger A = in.readMPI();
145
146
    // get s and v for user identified by I
119
    // get s and v for user identified by I
147
    // ----------------------------------------------------------------------
120
    // ----------------------------------------------------------------------
148
    final Map credentials;
121
    final Map credentials;
Lines 157-212 Link Here
157
      {
130
      {
158
        throw new KeyAgreementException("computeSharedSecret()", x);
131
        throw new KeyAgreementException("computeSharedSecret()", x);
159
      }
132
      }
160
161
    final BigInteger s = new BigInteger(
133
    final BigInteger s = new BigInteger(
162
                                        1,
134
        1,Util.fromBase64((String) credentials.get(SRPRegistry.SALT_FIELD)));
163
                                        Util.fromBase64((String) credentials.get(SRPRegistry.SALT_FIELD)));
164
    final BigInteger v = new BigInteger(
135
    final BigInteger v = new BigInteger(
165
                                        1,
136
        1, Util.fromBase64((String) credentials.get(SRPRegistry.USER_VERIFIER_FIELD)));
166
                                        Util.fromBase64((String) credentials.get(SRPRegistry.USER_VERIFIER_FIELD)));
167
168
    //      Map configuration = null;
169
    //      try {
170
    //         String mode = (String) credentials.get(SRPRegistry.CONFIG_NDX_FIELD);
171
    //         configuration = passwordDB.getConfiguration(mode);
172
    //      } catch (IOException x) {
173
    //         throw new KeyAgreementException("computeSharedSecret()", x);
174
    //      }
175
    //
176
    //      BigInteger N = new BigInteger(1, Util.fromBase64(
177
    //            (String) configuration.get(SRPRegistry.SHARED_MODULUS)));
178
    //      BigInteger g = new BigInteger(1, Util.fromBase64(
179
    //            (String) configuration.get(SRPRegistry.FIELD_GENERATOR)));
180
    // ----------------------------------------------------------------------
181
182
    final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
137
    final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
183
    final Map attributes = new HashMap();
138
    final Map attributes = new HashMap();
184
    if (rnd != null)
139
    if (rnd != null)
185
      {
140
      attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
186
        attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
187
      }
188
    attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
141
    attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
189
    attributes.put(SRPKeyPairGenerator.GENERATOR, g);
142
    attributes.put(SRPKeyPairGenerator.GENERATOR, g);
190
    attributes.put(SRPKeyPairGenerator.USER_VERIFIER, v);
143
    attributes.put(SRPKeyPairGenerator.USER_VERIFIER, v);
191
    kpg.setup(attributes);
144
    kpg.setup(attributes);
192
    hostKeyPair = kpg.generate();
145
    hostKeyPair = kpg.generate();
193
194
    final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();
146
    final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();
195
    final BigInteger u = uValue(A, B); // u = H(A | B)
147
    final BigInteger u = uValue(A, B); // u = H(A | B)
196
197
    // compute S = (Av^u) ^ b
148
    // compute S = (Av^u) ^ b
198
    final BigInteger b = ((SRPPrivateKey) hostKeyPair.getPrivate()).getX();
149
    final BigInteger b = ((SRPPrivateKey) hostKeyPair.getPrivate()).getX();
199
    final BigInteger S = A.multiply(v.modPow(u, N)).modPow(b, N);
150
    final BigInteger S = A.multiply(v.modPow(u, N)).modPow(b, N);
200
201
    final byte[] sBytes = Util.trim(S);
151
    final byte[] sBytes = Util.trim(S);
202
    final IMessageDigest hash = srp.newDigest();
152
    final IMessageDigest hash = srp.newDigest();
203
    hash.update(sBytes, 0, sBytes.length);
153
    hash.update(sBytes, 0, sBytes.length);
204
    K = new BigInteger(1, hash.digest());
154
    K = new BigInteger(1, hash.digest());
205
206
    final OutgoingMessage result = new OutgoingMessage();
155
    final OutgoingMessage result = new OutgoingMessage();
207
    result.writeMPI(s);
156
    result.writeMPI(s);
208
    result.writeMPI(B);
157
    result.writeMPI(B);
209
210
    complete = true;
158
    complete = true;
211
    return result;
159
    return result;
212
  }
160
  }
(-)srp6/SRP6KeyAgreement.java (-72 / +41 lines)
Lines 49-146 Link Here
49
import java.math.BigInteger;
49
import java.math.BigInteger;
50
50
51
/**
51
/**
52
 * <p>The Secure Remote Password (SRP) key agreement protocol, also known as
52
 * The Secure Remote Password (SRP) key agreement protocol, also known as SRP-6,
53
 * SRP-6, is designed by Thomas J. Wu (see references). The protocol, and its
53
 * is designed by Thomas J. Wu (see references). The protocol, and its elements
54
 * elements are described as follows:</p>
54
 * are described as follows:
55
 *
56
 * <pre>
55
 * <pre>
57
 * N    A large safe prime (N = 2q+1, where q is prime)
56
 *  N    A large safe prime (N = 2q+1, where q is prime)
58
 *      All arithmetic is done modulo N.
57
 *       All arithmetic is done modulo N.
59
 * g    A generator modulo N
58
 *  g    A generator modulo N
60
 * s    User's salt
59
 *  s    User's salt
61
 * I    Username
60
 *  I    Username
62
 * p    Cleartext Password
61
 *  p    Cleartext Password
63
 * H()  One-way hash function
62
 *  H()  One-way hash function
64
 * ^    (Modular) Exponentiation
63
 *  &circ;    (Modular) Exponentiation
65
 * u    Random scrambling parameter
64
 *  u    Random scrambling parameter
66
 * a,b  Secret ephemeral values
65
 *  a,b  Secret ephemeral values
67
 * A,B  Public ephemeral values
66
 *  A,B  Public ephemeral values
68
 * x    Private key (derived from p and s)
67
 *  x    Private key (derived from p and s)
69
 * v    Password verifier
68
 *  v    Password verifier
70
 *
69
 * 
71
 * The host stores passwords using the following formula:
70
 *  The host stores passwords using the following formula:
72
 * x = H(s | H(I ":" p))           (s is chosen randomly)
71
 *  x = H(s | H(I &quot;:&quot; p))           (s is chosen randomly)
73
 * v = g^x                   (computes password verifier)
72
 *  v = g&circ;x                         (computes password verifier)
74
 *
73
 * 
75
 * The host then keeps {I, s, v} in its password database.
74
 *  The host then keeps {I, s, v} in its password database.
76
 *
75
 * 
77
 * The authentication protocol itself goes as follows:
76
 *  The authentication protocol itself goes as follows:
78
 * User -> Host:  I, A = g^a         (identifies self, a = random number)
77
 *  User -&gt; Host:  I, A = g&circ;a         (identifies self, a = random number)
79
 * Host -> User:  s, B = 3v + g^b    (sends salt, b = random number)
78
 *  Host -&gt; User:  s, B = 3v + g&circ;b    (sends salt, b = random number)
80
 *
79
 * 
81
 * Both:  u = H(A, B)
80
 *  Both:  u = H(A, B)
82
 *
81
 * 
83
 * User:  x = H(s, p)                (user enters password)
82
 *  User:  x = H(s, p)               (user enters password)
84
 * User:  S = (B - 3g^x) ^ (a + ux)  (computes session key)
83
 *  User:  S = (B - 3g&circ;x) &circ; (a + ux) (computes session key)
85
 * User:  K = H(S)
84
 *  User:  K = H(S)
86
 *
85
 * 
87
 * Host:  S = (Av^u) ^ b             (computes session key)
86
 *  Host:  S = (Av&circ;u) &circ; b            (computes session key)
88
 * Host:  K = H(S)
87
 *  Host:  K = H(S)
89
 * </pre>
88
 * </pre>
90
 *
89
 * <p>
91
 * <p>Reference:</p>
90
 * Reference:
92
 * <ol>
91
 * <ol>
93
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
92
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
94
 *    Thomas J. Wu.</li>
93
 * Thomas J. Wu.</li>
95
 * </ol>
94
 * </ol>
96
 */
95
 */
97
public abstract class SRP6KeyAgreement extends BaseKeyAgreementParty
96
public abstract class SRP6KeyAgreement
97
    extends BaseKeyAgreementParty
98
{
98
{
99
100
  // Constants and variables
101
  // -------------------------------------------------------------------------
102
103
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp6.ka.prng";
99
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp6.ka.prng";
104
105
  public static final String SHARED_MODULUS = "gnu.crypto.srp6.ka.N";
100
  public static final String SHARED_MODULUS = "gnu.crypto.srp6.ka.N";
106
107
  public static final String GENERATOR = "gnu.crypto.srp6.ka.g";
101
  public static final String GENERATOR = "gnu.crypto.srp6.ka.g";
108
109
  public static final String HASH_FUNCTION = "gnu.crypto.srp6.ka.H";
102
  public static final String HASH_FUNCTION = "gnu.crypto.srp6.ka.H";
110
111
  public static final String USER_IDENTITY = "gnu.crypto.srp6.ka.I";
103
  public static final String USER_IDENTITY = "gnu.crypto.srp6.ka.I";
112
113
  public static final String USER_PASSWORD = "gnu.crypto.srp6.ka.p";
104
  public static final String USER_PASSWORD = "gnu.crypto.srp6.ka.p";
114
115
  public static final String HOST_PASSWORD_DB = "gnu.crypto.srp6.ka.password.db";
105
  public static final String HOST_PASSWORD_DB = "gnu.crypto.srp6.ka.password.db";
116
117
  protected static final BigInteger THREE = BigInteger.valueOf(3L);
106
  protected static final BigInteger THREE = BigInteger.valueOf(3L);
118
119
  protected SRP srp;
107
  protected SRP srp;
120
121
  protected BigInteger N;
108
  protected BigInteger N;
122
123
  protected BigInteger g;
109
  protected BigInteger g;
124
125
  /** The shared secret key. */
110
  /** The shared secret key. */
126
  protected BigInteger K;
111
  protected BigInteger K;
127
112
128
  // Constructor(s)
129
  // -------------------------------------------------------------------------
130
131
  protected SRP6KeyAgreement()
113
  protected SRP6KeyAgreement()
132
  {
114
  {
133
    super(Registry.SRP6_KA);
115
    super(Registry.SRP6_KA);
134
  }
116
  }
135
117
136
  // Class methods
137
  // -------------------------------------------------------------------------
138
139
  // Instance methods
140
  // -------------------------------------------------------------------------
141
142
  // implementation of common abstract methods in BaseKeyAGreementParty ------
143
144
  protected byte[] engineSharedSecret() throws KeyAgreementException
118
  protected byte[] engineSharedSecret() throws KeyAgreementException
145
  {
119
  {
146
    return Util.trim(K);
120
    return Util.trim(K);
Lines 148-172 Link Here
148
122
149
  protected void engineReset()
123
  protected void engineReset()
150
  {
124
  {
151
    //      mda = null;
152
    srp = null;
125
    srp = null;
153
    N = null;
126
    N = null;
154
    g = null;
127
    g = null;
155
    K = null;
128
    K = null;
156
  }
129
  }
157
130
158
  // helper methods ----------------------------------------------------------
159
160
  protected BigInteger uValue(final BigInteger A, final BigInteger B)
131
  protected BigInteger uValue(final BigInteger A, final BigInteger B)
161
  {
132
  {
162
    //      IMessageDigest hash = (IMessageDigest) mda.clone();
163
    final IMessageDigest hash = srp.newDigest();
133
    final IMessageDigest hash = srp.newDigest();
164
    byte[] b;
134
    byte[] b;
165
    b = Util.trim(A);
135
    b = Util.trim(A);
166
    hash.update(b, 0, b.length);
136
    hash.update(b, 0, b.length);
167
    b = Util.trim(B);
137
    b = Util.trim(B);
168
    hash.update(b, 0, b.length);
138
    hash.update(b, 0, b.length);
169
170
    return new BigInteger(1, hash.digest());
139
    return new BigInteger(1, hash.digest());
171
  }
140
  }
172
}
141
}
(-)srp6/SRP6SaslClient.java (-32 / +21 lines)
Lines 48-101 Link Here
48
import java.math.BigInteger;
48
import java.math.BigInteger;
49
49
50
/**
50
/**
51
 * <p>A variation of the SRP-6 protocol as used in the SASL-SRP mechanism, for
51
 * A variation of the SRP-6 protocol as used in the SASL-SRP mechanism, for the
52
 * the User (client side).</p>
52
 * User (client side).
53
 *
53
 * <p>
54
 * <p>In this alternative, the exchange goes as follows:</p>
54
 * In this alternative, the exchange goes as follows:
55
 * 
55
 * <pre>
56
 * <pre>
56
 *    C -> S:  I                      (identifies self)
57
 *     C -&gt; S:  I                      (identifies self)
57
 *    S -> C:  N, g, s, B = 3v + g^b  (sends salt, b = random number)
58
 *     S -&gt; C:  N, g, s, B = 3v + g&circ;b  (sends salt, b = random number)
58
 *    C -> S:  A = g^a                (a = random number)
59
 *     C -&gt; S:  A = g&circ;a                (a = random number)
59
 * </pre>
60
 * </pre>
60
 *
61
 * 
61
 * <p>All elements are computed the same way as in the standard version.</p>
62
 * <p>
62
 *
63
 * All elements are computed the same way as in the standard version.
63
 * <p>Reference:</p>
64
 * <p>
65
 * Reference:
64
 * <ol>
66
 * <ol>
65
 *    <li><a href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt">
67
 * <li><a
66
 *    Secure Remote Password Authentication Mechanism</a><br>
68
 * href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt">
67
 *    K. Burdis, R. Naffah.</li>
69
 * Secure Remote Password Authentication Mechanism</a><br>
68
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
70
 * K. Burdis, R. Naffah.</li>
69
 *    Thomas J. Wu.</li>
71
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
72
 * Thomas J. Wu.</li>
70
 * </ol>
73
 * </ol>
71
 */
74
 */
72
public class SRP6SaslClient extends SRP6TLSClient
75
public class SRP6SaslClient
76
    extends SRP6TLSClient
73
{
77
{
74
75
  // Constants and variables
76
  // -------------------------------------------------------------------------
77
78
  // Constructor(s)
79
  // -------------------------------------------------------------------------
80
81
  // default 0-arguments constructor
78
  // default 0-arguments constructor
82
79
83
  // Class methods
84
  // -------------------------------------------------------------------------
85
86
  // Instance methods
87
  // -------------------------------------------------------------------------
88
89
  protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
80
  protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
90
      throws KeyAgreementException
81
      throws KeyAgreementException
91
  {
82
  {
92
    final OutgoingMessage result = super.computeSharedSecret(in);
83
    final OutgoingMessage result = super.computeSharedSecret(in);
93
94
    final byte[] sBytes = Util.trim(K);
84
    final byte[] sBytes = Util.trim(K);
95
    final IMessageDigest hash = srp.newDigest();
85
    final IMessageDigest hash = srp.newDigest();
96
    hash.update(sBytes, 0, sBytes.length);
86
    hash.update(sBytes, 0, sBytes.length);
97
    K = new BigInteger(1, hash.digest());
87
    K = new BigInteger(1, hash.digest());
98
99
    return result;
88
    return result;
100
  }
89
  }
101
}
90
}
(-)srp6/SRP6SaslServer.java (-32 / +21 lines)
Lines 48-101 Link Here
48
import java.math.BigInteger;
48
import java.math.BigInteger;
49
49
50
/**
50
/**
51
 * <p>A variation of the SRP-6 protocol as used in the SASL-SRP mechanism, for
51
 * A variation of the SRP-6 protocol as used in the SASL-SRP mechanism, for the
52
 * the Host (server side).</p>
52
 * Host (server side).
53
 *
53
 * <p>
54
 * <p>In this alternative, the exchange goes as follows:</p>
54
 * In this alternative, the exchange goes as follows:
55
 * 
55
 * <pre>
56
 * <pre>
56
 *    C -> S:  I                      (identifies self)
57
 *     C -&gt; S:  I                      (identifies self)
57
 *    S -> C:  N, g, s, B = 3v + g^b  (sends salt, b = random number)
58
 *     S -&gt; C:  N, g, s, B = 3v + g&circ;b  (sends salt, b = random number)
58
 *    C -> S:  A = g^a                (a = random number)
59
 *     C -&gt; S:  A = g&circ;a                (a = random number)
59
 * </pre>
60
 * </pre>
60
 *
61
 * 
61
 * <p>All elements are computed the same way as in the standard version.</p>
62
 * <p>
62
 *
63
 * All elements are computed the same way as in the standard version.
63
 * <p>Reference:</p>
64
 * <p>
65
 * Reference:
64
 * <ol>
66
 * <ol>
65
 *    <li><a href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt">
67
 * <li><a
66
 *    Secure Remote Password Authentication Mechanism</a><br>
68
 * href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt">
67
 *    K. Burdis, R. Naffah.</li>
69
 * Secure Remote Password Authentication Mechanism</a><br>
68
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
70
 * K. Burdis, R. Naffah.</li>
69
 *    Thomas J. Wu.</li>
71
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
72
 * Thomas J. Wu.</li>
70
 * </ol>
73
 * </ol>
71
 */
74
 */
72
public class SRP6SaslServer extends SRP6TLSServer
75
public class SRP6SaslServer
76
    extends SRP6TLSServer
73
{
77
{
74
75
  // Constants and variables
76
  // -------------------------------------------------------------------------
77
78
  // Constructor(s)
79
  // -------------------------------------------------------------------------
80
81
  // default 0-arguments constructor
78
  // default 0-arguments constructor
82
79
83
  // Class methods
84
  // -------------------------------------------------------------------------
85
86
  // Instance methods
87
  // -------------------------------------------------------------------------
88
89
  protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
80
  protected OutgoingMessage computeSharedSecret(final IncomingMessage in)
90
      throws KeyAgreementException
81
      throws KeyAgreementException
91
  {
82
  {
92
    super.computeSharedSecret(in);
83
    super.computeSharedSecret(in);
93
94
    final byte[] sBytes = Util.trim(K);
84
    final byte[] sBytes = Util.trim(K);
95
    final IMessageDigest hash = srp.newDigest();
85
    final IMessageDigest hash = srp.newDigest();
96
    hash.update(sBytes, 0, sBytes.length);
86
    hash.update(sBytes, 0, sBytes.length);
97
    K = new BigInteger(1, hash.digest());
87
    K = new BigInteger(1, hash.digest());
98
99
    return null;
88
    return null;
100
  }
89
  }
101
}
90
}
(-)srp6/SRP6TLSClient.java (-49 / +13 lines)
Lines 51-112 Link Here
51
import java.util.Map;
51
import java.util.Map;
52
52
53
/**
53
/**
54
 * <p>A variation of the SRP6 key agreement protocol, for the client-side as
54
 * A variation of the SRP6 key agreement protocol, for the client-side as
55
 * proposed in
55
 * proposed in <a
56
 * <a href="http://www.ietf.org/internet-drafts/draft-ietf-tls-srp-05.txt">Using
56
 * href="http://www.ietf.org/internet-drafts/draft-ietf-tls-srp-05.txt">Using
57
 * SRP for TLS Authentication</a>. The only difference between it and the SASL
57
 * SRP for TLS Authentication</a>. The only difference between it and the SASL
58
 * variant is that the shared secret is the entity <code>S</code> and not
58
 * variant is that the shared secret is the entity <code>S</code> and not
59
 * <code>H(S)</code>.</p>
59
 * <code>H(S)</code>.
60
 */
60
 */
61
public class SRP6TLSClient extends SRP6KeyAgreement
61
public class SRP6TLSClient
62
    extends SRP6KeyAgreement
62
{
63
{
63
64
  // Constants and variables
65
  // -------------------------------------------------------------------------
66
67
  /** The user's identity. */
64
  /** The user's identity. */
68
  private String I;
65
  private String I;
69
70
  /** The user's cleartext password. */
66
  /** The user's cleartext password. */
71
  private byte[] p;
67
  private byte[] p;
72
73
  /** The user's ephemeral key pair. */
68
  /** The user's ephemeral key pair. */
74
  private KeyPair userKeyPair;
69
  private KeyPair userKeyPair;
75
70
76
  // Constructor(s)
77
  // -------------------------------------------------------------------------
78
79
  // default 0-arguments constructor
71
  // default 0-arguments constructor
80
72
81
  // Class methods
82
  // -------------------------------------------------------------------------
83
84
  // Instance methods
85
  // -------------------------------------------------------------------------
86
87
  // implementation of abstract methods in base class ------------------------
88
89
  protected void engineInit(final Map attributes) throws KeyAgreementException
73
  protected void engineInit(final Map attributes) throws KeyAgreementException
90
  {
74
  {
91
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
75
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
92
93
    final String md = (String) attributes.get(HASH_FUNCTION);
76
    final String md = (String) attributes.get(HASH_FUNCTION);
94
    if (md == null || "".equals(md.trim()))
77
    if (md == null || md.trim().length() == 0)
95
      {
78
      throw new KeyAgreementException("missing hash function");
96
        throw new KeyAgreementException("missing hash function");
97
      }
98
    srp = SRP.instance(md);
79
    srp = SRP.instance(md);
99
100
    I = (String) attributes.get(USER_IDENTITY);
80
    I = (String) attributes.get(USER_IDENTITY);
101
    if (I == null)
81
    if (I == null)
102
      {
82
      throw new KeyAgreementException("missing user identity");
103
        throw new KeyAgreementException("missing user identity");
104
      }
105
    p = (byte[]) attributes.get(USER_PASSWORD);
83
    p = (byte[]) attributes.get(USER_PASSWORD);
106
    if (p == null)
84
    if (p == null)
107
      {
85
      throw new KeyAgreementException("missing user password");
108
        throw new KeyAgreementException("missing user password");
109
      }
110
  }
86
  }
111
87
112
  protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
88
  protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
Lines 131-144 Link Here
131
    super.engineReset();
107
    super.engineReset();
132
  }
108
  }
133
109
134
  // own methods -------------------------------------------------------------
135
136
  private OutgoingMessage sendIdentity(final IncomingMessage in)
110
  private OutgoingMessage sendIdentity(final IncomingMessage in)
137
      throws KeyAgreementException
111
      throws KeyAgreementException
138
  {
112
  {
139
    final OutgoingMessage result = new OutgoingMessage();
113
    final OutgoingMessage result = new OutgoingMessage();
140
    result.writeString(I);
114
    result.writeString(I);
141
142
    return result;
115
    return result;
143
  }
116
  }
144
117
Lines 149-167 Link Here
149
    g = in.readMPI();
122
    g = in.readMPI();
150
    final BigInteger s = in.readMPI();
123
    final BigInteger s = in.readMPI();
151
    final BigInteger B = in.readMPI();
124
    final BigInteger B = in.readMPI();
152
153
    // generate an ephemeral keypair
125
    // generate an ephemeral keypair
154
    final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
126
    final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
155
    final Map attributes = new HashMap();
127
    final Map attributes = new HashMap();
156
    if (rnd != null)
128
    if (rnd != null)
157
      {
129
      attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
158
        attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
159
      }
160
    attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
130
    attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
161
    attributes.put(SRPKeyPairGenerator.GENERATOR, g);
131
    attributes.put(SRPKeyPairGenerator.GENERATOR, g);
162
    kpg.setup(attributes);
132
    kpg.setup(attributes);
163
    userKeyPair = kpg.generate();
133
    userKeyPair = kpg.generate();
164
165
    final BigInteger A = ((SRPPublicKey) userKeyPair.getPublic()).getY();
134
    final BigInteger A = ((SRPPublicKey) userKeyPair.getPublic()).getY();
166
    final BigInteger u = uValue(A, B); // u = H(A | B)
135
    final BigInteger u = uValue(A, B); // u = H(A | B)
167
    final BigInteger x;
136
    final BigInteger x;
Lines 173-190 Link Here
173
      {
142
      {
174
        throw new KeyAgreementException("computeSharedSecret()", e);
143
        throw new KeyAgreementException("computeSharedSecret()", e);
175
      }
144
      }
176
177
    // compute S = (B - 3g^x) ^ (a + ux)
145
    // compute S = (B - 3g^x) ^ (a + ux)
178
    final BigInteger a = ((SRPPrivateKey) userKeyPair.getPrivate()).getX();
146
    final BigInteger a = ((SRPPrivateKey) userKeyPair.getPrivate()).getX();
179
    final BigInteger S = B.subtract(THREE.multiply(g.modPow(x, N))).modPow(
147
    final BigInteger S = B.subtract(THREE.multiply(g.modPow(x, N)))
180
                                                                           a.add(u.multiply(x)),
148
                          .modPow(a.add(u.multiply(x)), N);
181
                                                                           N);
182
183
    K = S;
149
    K = S;
184
185
    final OutgoingMessage result = new OutgoingMessage();
150
    final OutgoingMessage result = new OutgoingMessage();
186
    result.writeMPI(A);
151
    result.writeMPI(A);
187
188
    complete = true;
152
    complete = true;
189
    return result;
153
    return result;
190
  }
154
  }
(-)srp6/SRP6TLSServer.java (-55 / +14 lines)
Lines 55-108 Link Here
55
import java.util.Map;
55
import java.util.Map;
56
56
57
/**
57
/**
58
 * <p>A variation of the SRP6 key agreement protocol, for the server-side as
58
 * A variation of the SRP6 key agreement protocol, for the server-side as
59
 * proposed in
59
 * proposed in <a
60
 * <a href="http://www.ietf.org/internet-drafts/draft-ietf-tls-srp-05.txt">Using
60
 * href="http://www.ietf.org/internet-drafts/draft-ietf-tls-srp-05.txt">Using
61
 * SRP for TLS Authentication</a>. The only difference between it and the SASL
61
 * SRP for TLS Authentication</a>. The only difference between it and the SASL
62
 * variant is that the shared secret is the entity <code>S</code> and not
62
 * variant is that the shared secret is the entity <code>S</code> and not
63
 * <code>H(S)</code>.</p>
63
 * <code>H(S)</code>.
64
 */
64
 */
65
public class SRP6TLSServer extends SRP6KeyAgreement
65
public class SRP6TLSServer
66
    extends SRP6KeyAgreement
66
{
67
{
67
68
  // Constants and variables
69
  // -------------------------------------------------------------------------
70
71
  /** The user's ephemeral key pair. */
68
  /** The user's ephemeral key pair. */
72
  private KeyPair hostKeyPair;
69
  private KeyPair hostKeyPair;
73
74
  /** The SRP password database. */
70
  /** The SRP password database. */
75
  private SRPAuthInfoProvider passwordDB;
71
  private SRPAuthInfoProvider passwordDB;
76
72
77
  // Constructor(s)
78
  // -------------------------------------------------------------------------
79
80
  // default 0-arguments constructor
73
  // default 0-arguments constructor
81
74
82
  // Class methods
83
  // -------------------------------------------------------------------------
84
85
  // Instance methods
86
  // -------------------------------------------------------------------------
87
88
  // implementation of abstract methods in base class ------------------------
89
90
  protected void engineInit(final Map attributes) throws KeyAgreementException
75
  protected void engineInit(final Map attributes) throws KeyAgreementException
91
  {
76
  {
92
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
77
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
93
94
    final String md = (String) attributes.get(HASH_FUNCTION);
78
    final String md = (String) attributes.get(HASH_FUNCTION);
95
    if (md == null || "".equals(md.trim()))
79
    if (md == null || md.trim().length() == 0)
96
      {
80
      throw new KeyAgreementException("missing hash function");
97
        throw new KeyAgreementException("missing hash function");
98
      }
99
    srp = SRP.instance(md);
81
    srp = SRP.instance(md);
100
101
    passwordDB = (SRPAuthInfoProvider) attributes.get(HOST_PASSWORD_DB);
82
    passwordDB = (SRPAuthInfoProvider) attributes.get(HOST_PASSWORD_DB);
102
    if (passwordDB == null)
83
    if (passwordDB == null)
103
      {
84
      throw new KeyAgreementException("missing SRP password database");
104
        throw new KeyAgreementException("missing SRP password database");
105
      }
106
  }
85
  }
107
86
108
  protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
87
  protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
Lines 125-137 Link Here
125
    super.engineReset();
104
    super.engineReset();
126
  }
105
  }
127
106
128
  // own methods -------------------------------------------------------------
129
130
  private OutgoingMessage sendParameters(final IncomingMessage in)
107
  private OutgoingMessage sendParameters(final IncomingMessage in)
131
      throws KeyAgreementException
108
      throws KeyAgreementException
132
  {
109
  {
133
    final String I = in.readString();
110
    final String I = in.readString();
134
135
    // get s and v for user identified by I
111
    // get s and v for user identified by I
136
    // ----------------------------------------------------------------------
112
    // ----------------------------------------------------------------------
137
    final Map credentials;
113
    final Map credentials;
Lines 148-159 Link Here
148
      }
124
      }
149
125
150
    final BigInteger s = new BigInteger(
126
    final BigInteger s = new BigInteger(
151
                                        1,
127
        1, Util.fromBase64((String) credentials.get(SRPRegistry.SALT_FIELD)));
152
                                        Util.fromBase64((String) credentials.get(SRPRegistry.SALT_FIELD)));
153
    final BigInteger v = new BigInteger(
128
    final BigInteger v = new BigInteger(
154
                                        1,
129
        1, Util.fromBase64((String) credentials.get(SRPRegistry.USER_VERIFIER_FIELD)));
155
                                        Util.fromBase64((String) credentials.get(SRPRegistry.USER_VERIFIER_FIELD)));
156
157
    final Map configuration;
130
    final Map configuration;
158
    try
131
    try
159
      {
132
      {
Lines 164-199 Link Here
164
      {
137
      {
165
        throw new KeyAgreementException("computeSharedSecret()", x);
138
        throw new KeyAgreementException("computeSharedSecret()", x);
166
      }
139
      }
167
168
    N = new BigInteger(
140
    N = new BigInteger(
169
                       1,
141
        1, Util.fromBase64((String) configuration.get(SRPRegistry.SHARED_MODULUS)));
170
                       Util.fromBase64((String) configuration.get(SRPRegistry.SHARED_MODULUS)));
171
    g = new BigInteger(
142
    g = new BigInteger(
172
                       1,
143
        1, Util.fromBase64((String) configuration.get(SRPRegistry.FIELD_GENERATOR)));
173
                       Util.fromBase64((String) configuration.get(SRPRegistry.FIELD_GENERATOR)));
174
    // ----------------------------------------------------------------------
175
176
    // generate an ephemeral keypair
144
    // generate an ephemeral keypair
177
    final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
145
    final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
178
    final Map attributes = new HashMap();
146
    final Map attributes = new HashMap();
179
    if (rnd != null)
147
    if (rnd != null)
180
      {
148
      attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
181
        attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
182
      }
183
    attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
149
    attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
184
    attributes.put(SRPKeyPairGenerator.GENERATOR, g);
150
    attributes.put(SRPKeyPairGenerator.GENERATOR, g);
185
    attributes.put(SRPKeyPairGenerator.USER_VERIFIER, v);
151
    attributes.put(SRPKeyPairGenerator.USER_VERIFIER, v);
186
    kpg.setup(attributes);
152
    kpg.setup(attributes);
187
    hostKeyPair = kpg.generate();
153
    hostKeyPair = kpg.generate();
188
189
    final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();
154
    final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();
190
191
    final OutgoingMessage result = new OutgoingMessage();
155
    final OutgoingMessage result = new OutgoingMessage();
192
    result.writeMPI(N);
156
    result.writeMPI(N);
193
    result.writeMPI(g);
157
    result.writeMPI(g);
194
    result.writeMPI(s);
158
    result.writeMPI(s);
195
    result.writeMPI(B);
159
    result.writeMPI(B);
196
197
    return result;
160
    return result;
198
  }
161
  }
199
162
Lines 201-217 Link Here
201
      throws KeyAgreementException
164
      throws KeyAgreementException
202
  {
165
  {
203
    final BigInteger A = in.readMPI();
166
    final BigInteger A = in.readMPI();
204
205
    final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();
167
    final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY();
206
    final BigInteger u = uValue(A, B); // u = H(A | B)
168
    final BigInteger u = uValue(A, B); // u = H(A | B)
207
208
    // compute S = (Av^u) ^ b
169
    // compute S = (Av^u) ^ b
209
    final BigInteger b = ((SRPPrivateKey) hostKeyPair.getPrivate()).getX();
170
    final BigInteger b = ((SRPPrivateKey) hostKeyPair.getPrivate()).getX();
210
    final BigInteger v = ((SRPPrivateKey) hostKeyPair.getPrivate()).getV();
171
    final BigInteger v = ((SRPPrivateKey) hostKeyPair.getPrivate()).getV();
211
    final BigInteger S = A.multiply(v.modPow(u, N)).modPow(b, N);
172
    final BigInteger S = A.multiply(v.modPow(u, N)).modPow(b, N);
212
213
    K = S;
173
    K = S;
214
215
    complete = true;
174
    complete = true;
216
    return null;
175
    return null;
217
  }
176
  }
(-)srp6/SRP6User.java (-56 / +16 lines)
Lines 52-124 Link Here
52
import java.util.Map;
52
import java.util.Map;
53
53
54
/**
54
/**
55
 * <p>The implementation of the User in the SRP-6 protocol.</p>
55
 * The implementation of the User in the SRP-6 protocol.
56
 *
56
 * <p>
57
 * <p>Reference:</p>
57
 * Reference:
58
 * <ol>
58
 * <ol>
59
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
59
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
60
 *    Thomas J. Wu.</li>
60
 * Thomas J. Wu.</li>
61
 * </ol>
61
 * </ol>
62
 */
62
 */
63
public class SRP6User extends SRP6KeyAgreement
63
public class SRP6User
64
    extends SRP6KeyAgreement
64
{
65
{
65
66
  // Constants and variables
67
  // -------------------------------------------------------------------------
68
69
  /** The user's identity. */
66
  /** The user's identity. */
70
  private String I;
67
  private String I;
71
72
  /** The user's cleartext password. */
68
  /** The user's cleartext password. */
73
  private byte[] p;
69
  private byte[] p;
74
75
  /** The user's ephemeral key pair. */
70
  /** The user's ephemeral key pair. */
76
  private KeyPair userKeyPair;
71
  private KeyPair userKeyPair;
77
72
78
  // Constructor(s)
79
  // -------------------------------------------------------------------------
80
81
  // default 0-arguments constructor
73
  // default 0-arguments constructor
82
74
83
  // Class methods
84
  // -------------------------------------------------------------------------
85
86
  // Instance methods
87
  // -------------------------------------------------------------------------
88
89
  // implementation of abstract methods in base class ------------------------
90
91
  protected void engineInit(final Map attributes) throws KeyAgreementException
75
  protected void engineInit(final Map attributes) throws KeyAgreementException
92
  {
76
  {
93
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
77
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
94
    N = (BigInteger) attributes.get(SHARED_MODULUS);
78
    N = (BigInteger) attributes.get(SHARED_MODULUS);
95
    if (N == null)
79
    if (N == null)
96
      {
80
      throw new KeyAgreementException("missing shared modulus");
97
        throw new KeyAgreementException("missing shared modulus");
98
      }
99
    g = (BigInteger) attributes.get(GENERATOR);
81
    g = (BigInteger) attributes.get(GENERATOR);
100
    if (g == null)
82
    if (g == null)
101
      {
83
      throw new KeyAgreementException("missing generator");
102
        throw new KeyAgreementException("missing generator");
103
      }
104
105
    final String md = (String) attributes.get(HASH_FUNCTION);
84
    final String md = (String) attributes.get(HASH_FUNCTION);
106
    if (md == null || "".equals(md.trim()))
85
    if (md == null || md.trim().length() == 0)
107
      {
86
      throw new KeyAgreementException("missing hash function");
108
        throw new KeyAgreementException("missing hash function");
109
      }
110
    srp = SRP.instance(md);
87
    srp = SRP.instance(md);
111
112
    I = (String) attributes.get(USER_IDENTITY);
88
    I = (String) attributes.get(USER_IDENTITY);
113
    if (I == null)
89
    if (I == null)
114
      {
90
      throw new KeyAgreementException("missing user identity");
115
        throw new KeyAgreementException("missing user identity");
116
      }
117
    p = (byte[]) attributes.get(USER_PASSWORD);
91
    p = (byte[]) attributes.get(USER_PASSWORD);
118
    if (p == null)
92
    if (p == null)
119
      {
93
      throw new KeyAgreementException("missing user password");
120
        throw new KeyAgreementException("missing user password");
121
      }
122
  }
94
  }
123
95
124
  protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
96
  protected OutgoingMessage engineProcessMessage(final IncomingMessage in)
Lines 143-150 Link Here
143
    super.engineReset();
115
    super.engineReset();
144
  }
116
  }
145
117
146
  // own methods -------------------------------------------------------------
147
148
  private OutgoingMessage sendIdentity(final IncomingMessage in)
118
  private OutgoingMessage sendIdentity(final IncomingMessage in)
149
      throws KeyAgreementException
119
      throws KeyAgreementException
150
  {
120
  {
Lines 152-169 Link Here
152
    final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
122
    final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator();
153
    final Map attributes = new HashMap();
123
    final Map attributes = new HashMap();
154
    if (rnd != null)
124
    if (rnd != null)
155
      {
125
      attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
156
        attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd);
157
      }
158
    attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
126
    attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N);
159
    attributes.put(SRPKeyPairGenerator.GENERATOR, g);
127
    attributes.put(SRPKeyPairGenerator.GENERATOR, g);
160
    kpg.setup(attributes);
128
    kpg.setup(attributes);
161
    userKeyPair = kpg.generate();
129
    userKeyPair = kpg.generate();
162
163
    final OutgoingMessage result = new OutgoingMessage();
130
    final OutgoingMessage result = new OutgoingMessage();
164
    result.writeString(I);
131
    result.writeString(I);
165
    result.writeMPI(((SRPPublicKey) userKeyPair.getPublic()).getY());
132
    result.writeMPI(((SRPPublicKey) userKeyPair.getPublic()).getY());
166
167
    return result;
133
    return result;
168
  }
134
  }
169
135
Lines 172-181 Link Here
172
  {
138
  {
173
    final BigInteger s = in.readMPI();
139
    final BigInteger s = in.readMPI();
174
    final BigInteger B = in.readMPI();
140
    final BigInteger B = in.readMPI();
175
176
    final BigInteger A = ((SRPPublicKey) userKeyPair.getPublic()).getY();
141
    final BigInteger A = ((SRPPublicKey) userKeyPair.getPublic()).getY();
177
    final BigInteger u = uValue(A, B); // u = H(A | B)
142
    final BigInteger u = uValue(A, B); // u = H(A | B)
178
179
    final BigInteger x;
143
    final BigInteger x;
180
    try
144
    try
181
      {
145
      {
Lines 185-202 Link Here
185
      {
149
      {
186
        throw new KeyAgreementException("computeSharedSecret()", e);
150
        throw new KeyAgreementException("computeSharedSecret()", e);
187
      }
151
      }
188
189
    // compute S = (B - 3g^x) ^ (a + ux)
152
    // compute S = (B - 3g^x) ^ (a + ux)
190
    final BigInteger a = ((SRPPrivateKey) userKeyPair.getPrivate()).getX();
153
    final BigInteger a = ((SRPPrivateKey) userKeyPair.getPrivate()).getX();
191
    final BigInteger S = B.subtract(THREE.multiply(g.modPow(x, N))).modPow(
154
    final BigInteger S = B.subtract(THREE.multiply(g.modPow(x, N)))
192
                                                                           a.add(u.multiply(x)),
155
                          .modPow(a.add(u.multiply(x)), N);
193
                                                                           N);
194
195
    final byte[] sBytes = Util.trim(S);
156
    final byte[] sBytes = Util.trim(S);
196
    final IMessageDigest hash = srp.newDigest();
157
    final IMessageDigest hash = srp.newDigest();
197
    hash.update(sBytes, 0, sBytes.length);
158
    hash.update(sBytes, 0, sBytes.length);
198
    K = new BigInteger(1, hash.digest());
159
    K = new BigInteger(1, hash.digest());
199
200
    complete = true;
160
    complete = true;
201
    return null;
161
    return null;
202
  }
162
  }
(-)srp6/SRPAlgorithm.java (-87 / +44 lines)
Lines 43-51 Link Here
43
import java.math.BigInteger;
43
import java.math.BigInteger;
44
44
45
/**
45
/**
46
 * <p>Utilities for use with SRP-6 based methods and protocols.</p>
46
 * Utilities for use with SRP-6 based methods and protocols.
47
 *
47
 * <p>
48
 * <p>Reference:</p>
48
 * Reference:
49
 * <ol>
49
 * <ol>
50
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
50
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
51
 *    Thomas J. Wu.</li>
51
 *    Thomas J. Wu.</li>
Lines 53-174 Link Here
53
 */
53
 */
54
public class SRPAlgorithm
54
public class SRPAlgorithm
55
{
55
{
56
57
  // Constants and variables
58
  // -------------------------------------------------------------------------
59
60
  // lifted from draft-burdis-cat-srp-sasl-09
56
  // lifted from draft-burdis-cat-srp-sasl-09
61
  public static final BigInteger N_2048 = new BigInteger(
57
  public static final BigInteger N_2048 = new BigInteger(
62
                                                         "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050"
58
      "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050"
63
                                                             + "A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50"
59
    + "A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50"
64
                                                             + "E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B8"
60
    + "E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B8"
65
                                                             + "55F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773B"
61
    + "55F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773B"
66
                                                             + "CA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748"
62
    + "CA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748"
67
                                                             + "544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6"
63
    + "544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6"
68
                                                             + "AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6"
64
    + "AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6"
69
                                                             + "94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73",
65
    + "94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", 16);
70
                                                         16);
71
72
  public static final BigInteger N_1536 = new BigInteger(
66
  public static final BigInteger N_1536 = new BigInteger(
73
                                                         "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D"
67
      "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D"
74
                                                             + "5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DC"
68
    + "5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DC"
75
                                                             + "DF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC"
69
    + "DF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC"
76
                                                             + "764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C486"
70
    + "764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C486"
77
                                                             + "65772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E"
71
    + "65772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E"
78
                                                             + "5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB",
72
    + "5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB", 16);
79
                                                         16);
80
81
  public static final BigInteger N_1280 = new BigInteger(
73
  public static final BigInteger N_1280 = new BigInteger(
82
                                                         "D77946826E811914B39401D56A0A7843A8E7575D738C672A090AB1187D690DC4"
74
      "D77946826E811914B39401D56A0A7843A8E7575D738C672A090AB1187D690DC4"
83
                                                             + "3872FC06A7B6A43F3B95BEAEC7DF04B9D242EBDC481111283216CE816E004B78"
75
    + "3872FC06A7B6A43F3B95BEAEC7DF04B9D242EBDC481111283216CE816E004B78"
84
                                                             + "6C5FCE856780D41837D95AD787A50BBE90BD3A9C98AC0F5FC0DE744B1CDE1891"
76
    + "6C5FCE856780D41837D95AD787A50BBE90BD3A9C98AC0F5FC0DE744B1CDE1891"
85
                                                             + "690894BC1F65E00DE15B4B2AA6D87100C9ECC2527E45EB849DEB14BB2049B163"
77
    + "690894BC1F65E00DE15B4B2AA6D87100C9ECC2527E45EB849DEB14BB2049B163"
86
                                                             + "EA04187FD27C1BD9C7958CD40CE7067A9C024F9B7C5A0B4F5003686161F0605B",
78
    + "EA04187FD27C1BD9C7958CD40CE7067A9C024F9B7C5A0B4F5003686161F0605B", 16);
87
                                                         16);
88
89
  public static final BigInteger N_1024 = new BigInteger(
79
  public static final BigInteger N_1024 = new BigInteger(
90
                                                         "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576"
80
      "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576"
91
                                                             + "D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD1"
81
    + "D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD1"
92
                                                             + "5DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC"
82
    + "5DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC"
93
                                                             + "68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3",
83
    + "68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3", 16);
94
                                                         16);
95
96
  public static final BigInteger N_768 = new BigInteger(
84
  public static final BigInteger N_768 = new BigInteger(
97
                                                        "B344C7C4F8C495031BB4E04FF8F84EE95008163940B9558276744D91F7CC9F40"
85
      "B344C7C4F8C495031BB4E04FF8F84EE95008163940B9558276744D91F7CC9F40"
98
                                                            + "2653BE7147F00F576B93754BCDDF71B636F2099E6FFF90E79575F3D0DE694AFF"
86
    + "2653BE7147F00F576B93754BCDDF71B636F2099E6FFF90E79575F3D0DE694AFF"
99
                                                            + "737D9BE9713CEF8D837ADA6380B1093E94B6A529A8C6C2BE33E0867C60C3262B",
87
    + "737D9BE9713CEF8D837ADA6380B1093E94B6A529A8C6C2BE33E0867C60C3262B", 16);
100
                                                        16);
101
102
  public static final BigInteger N_640 = new BigInteger(
88
  public static final BigInteger N_640 = new BigInteger(
103
                                                        "C94D67EB5B1A2346E8AB422FC6A0EDAEDA8C7F894C9EEEC42F9ED250FD7F0046"
89
      "C94D67EB5B1A2346E8AB422FC6A0EDAEDA8C7F894C9EEEC42F9ED250FD7F0046"
104
                                                            + "E5AF2CF73D6B2FA26BB08033DA4DE322E144E7A8E9B12A0E4637F6371F34A207"
90
    + "E5AF2CF73D6B2FA26BB08033DA4DE322E144E7A8E9B12A0E4637F6371F34A207"
105
                                                            + "1C4B3836CBEEAB15034460FAA7ADF483",
91
    + "1C4B3836CBEEAB15034460FAA7ADF483", 16);
106
                                                        16);
107
108
  public static final BigInteger N_512 = new BigInteger(
92
  public static final BigInteger N_512 = new BigInteger(
109
                                                        "D4C7F8A2B32C11B8FBA9581EC4BA4F1B04215642EF7355E37C0FC0443EF756EA"
93
      "D4C7F8A2B32C11B8FBA9581EC4BA4F1B04215642EF7355E37C0FC0443EF756EA"
110
                                                            + "2C6B8EEB755A1C723027663CAA265EF785B8FF6A9B35227A52D86633DBDFCA43",
94
    + "2C6B8EEB755A1C723027663CAA265EF785B8FF6A9B35227A52D86633DBDFCA43", 16);
111
                                                        16);
112
113
  public static final BigInteger N_384 = new BigInteger(
95
  public static final BigInteger N_384 = new BigInteger(
114
                                                        "8025363296FB943FCE54BE717E0E2958A02A9672EF561953B2BAA3BAACC3ED57"
96
      "8025363296FB943FCE54BE717E0E2958A02A9672EF561953B2BAA3BAACC3ED57"
115
                                                            + "54EB764C7AB7184578C57D5949CCB41B",
97
    + "54EB764C7AB7184578C57D5949CCB41B", 16);
116
                                                        16);
117
118
  public static final BigInteger N_264 = new BigInteger(
98
  public static final BigInteger N_264 = new BigInteger(
119
                                                        "115B8B692E0E045692CF280B436735C77A5A9E8A9E7ED56C965F87DB5B2A2ECE3",
99
      "115B8B692E0E045692CF280B436735C77A5A9E8A9E7ED56C965F87DB5B2A2ECE3", 16);
120
                                                        16);
121
122
  private static final BigInteger ZERO = BigInteger.ZERO;
100
  private static final BigInteger ZERO = BigInteger.ZERO;
123
124
  private static final BigInteger ONE = BigInteger.ONE;
101
  private static final BigInteger ONE = BigInteger.ONE;
125
126
  private static final BigInteger TWO = BigInteger.valueOf(2L);
102
  private static final BigInteger TWO = BigInteger.valueOf(2L);
127
103
128
  // Constructor(s)
129
  // -------------------------------------------------------------------------
130
131
  /** Trivial constructor to enforce usage through class methods. */
104
  /** Trivial constructor to enforce usage through class methods. */
132
  private SRPAlgorithm()
105
  private SRPAlgorithm()
133
  {
106
  {
134
    super();
107
    super();
135
  }
108
  }
136
109
137
  // Class methods
138
  // -------------------------------------------------------------------------
139
140
  public static void checkParams(final BigInteger N, final BigInteger g)
110
  public static void checkParams(final BigInteger N, final BigInteger g)
141
  {
111
  {
142
    // 1. N should be at least 512-bit long
112
    // 1. N should be at least 512-bit long
143
    final int blen = N.bitLength();
113
    final int blen = N.bitLength();
144
    if (blen < SRPRegistry.MINIMUM_MODULUS_BITLENGTH)
114
    if (blen < SRPRegistry.MINIMUM_MODULUS_BITLENGTH)
145
      {
115
      throw new IllegalArgumentException("Bit length of N ("
146
        throw new IllegalArgumentException(
116
                                         + blen
147
                                           "Bit length of N ("
117
                                         + ") is too low. Should be at least "
148
                                               + blen
118
                                         + SRPRegistry.MINIMUM_MODULUS_BITLENGTH);
149
                                               + ") is too low. Should be at least "
150
                                               + SRPRegistry.MINIMUM_MODULUS_BITLENGTH);
151
      }
152
    // 2. N should be a prime
119
    // 2. N should be a prime
153
    if (! N.isProbablePrime(80))
120
    if (! N.isProbablePrime(80))
154
      {
121
      throw new IllegalArgumentException("N should be prime but isn't");
155
        throw new IllegalArgumentException("N should be prime but isn't");
156
      }
157
    // 3. N should be of the form 2*q + 1, where q is prime
122
    // 3. N should be of the form 2*q + 1, where q is prime
158
    final BigInteger q = N.subtract(ONE).divide(TWO);
123
    final BigInteger q = N.subtract(ONE).divide(TWO);
159
    if (! q.isProbablePrime(80))
124
    if (! q.isProbablePrime(80))
160
      {
125
      throw new IllegalArgumentException("(N-1)/2 should be prime but isn't");
161
        throw new IllegalArgumentException("(N-1)/2 should be prime but isn't");
162
      }
163
    // 4. g**q should be -1 mod N
126
    // 4. g**q should be -1 mod N
164
    final BigInteger gq = g.modPow(q, N).add(ONE).mod(N);
127
    final BigInteger gq = g.modPow(q, N).add(ONE).mod(N);
165
    if (gq.compareTo(ZERO) != 0)
128
    if (gq.compareTo(ZERO) != 0)
166
      {
129
      throw new IllegalArgumentException("g**q should be -1 (mod N) but isn't");
167
        throw new IllegalArgumentException(
168
                                           "g**q should be -1 (mod N) but isn't");
169
      }
170
  }
130
  }
171
172
  // Instance methods
173
  // -------------------------------------------------------------------------
174
}
131
}
(-)srp6/SRPKey.java (-51 / +28 lines)
Lines 46-82 Link Here
46
import java.security.Key;
46
import java.security.Key;
47
47
48
/**
48
/**
49
 * <p>An abstract representation of a base SRP ephemeral key.</p>
49
 * An abstract representation of a base SRP ephemeral key.
50
 *
50
 * <p>
51
 * <p>This object encapsulates the two numbers:</p>
51
 * This object encapsulates the two numbers:
52
 * <ul>
52
 * <ul>
53
 *    <li><b>N</b>: A large safe prime (N = 2q+1, where q is prime).</li>
53
 * <li><b>N</b>: A large safe prime (N = 2q+1, where q is prime).</li>
54
 *    <li><b>g</b>: A generator modulo N.</li>
54
 * <li><b>g</b>: A generator modulo N.</li>
55
 * </ul>
55
 * </ul>
56
 *
56
 * <p>
57
 * <p>Note that in SRP, all arithmetic is done modulo N.</p>
57
 * Note that in SRP, all arithmetic is done modulo N.
58
 *
58
 * <p>
59
 * <p>Reference:</p>
59
 * Reference:
60
 * <ol>
60
 * <ol>
61
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
61
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
62
 *    Thomas J. Wu.</li>
62
 * Thomas J. Wu.</li>
63
 * </ol>
63
 * </ol>
64
 */
64
 */
65
public abstract class SRPKey implements Key, Serializable
65
public abstract class SRPKey
66
    implements Key, Serializable
66
{
67
{
67
68
  // Constants and variables
69
  // -------------------------------------------------------------------------
70
71
  /** The public, Germaine prime, shared modulus. */
68
  /** The public, Germaine prime, shared modulus. */
72
  protected final BigInteger N;
69
  protected final BigInteger N;
73
74
  /** The generator. */
70
  /** The generator. */
75
  protected final BigInteger g;
71
  protected final BigInteger g;
76
72
77
  // Constructor(s)
78
  // -------------------------------------------------------------------------
79
80
  protected SRPKey(BigInteger N, BigInteger g)
73
  protected SRPKey(BigInteger N, BigInteger g)
81
  {
74
  {
82
    super();
75
    super();
Lines 85-101 Link Here
85
    this.g = g;
78
    this.g = g;
86
  }
79
  }
87
80
88
  // Class methods
89
  // -------------------------------------------------------------------------
90
91
  // Instance methods
92
  // -------------------------------------------------------------------------
93
94
  // java.security.Key interface implementation ------------------------------
95
96
  /**
81
  /**
97
   * <p>Returns the standard algorithm name for this key.</p>
82
   * Returns the standard algorithm name for this key.
98
   *
83
   * 
99
   * @return the standard algorithm name for this key.
84
   * @return the standard algorithm name for this key.
100
   */
85
   */
101
  public String getAlgorithm()
86
  public String getAlgorithm()
Lines 112-118 Link Here
112
  /**
97
  /**
113
   * Returns {@link Registry#RAW_ENCODING_SHORT_NAME} which is the sole format
98
   * Returns {@link Registry#RAW_ENCODING_SHORT_NAME} which is the sole format
114
   * supported for this type of keys.
99
   * supported for this type of keys.
115
   *
100
   * 
116
   * @return {@link Registry#RAW_ENCODING_SHORT_NAME} ALWAYS.
101
   * @return {@link Registry#RAW_ENCODING_SHORT_NAME} ALWAYS.
117
   */
102
   */
118
  public String getFormat()
103
  public String getFormat()
Lines 120-130 Link Here
120
    return Registry.RAW_ENCODING_SHORT_NAME;
105
    return Registry.RAW_ENCODING_SHORT_NAME;
121
  }
106
  }
122
107
123
  // other methods -----------------------------------------------------------
124
125
  /**
108
  /**
126
   * <p>Returns the public shared modulus.</p>
109
   * Returns the public shared modulus.
127
   *
110
   * 
128
   * @return <code>N</code>.
111
   * @return <code>N</code>.
129
   */
112
   */
130
  public BigInteger getN()
113
  public BigInteger getN()
Lines 133-140 Link Here
133
  }
116
  }
134
117
135
  /**
118
  /**
136
   * <p>Returns the generator.</p>
119
   * Returns the generator.
137
   *
120
   * 
138
   * @return <code>g</code>.
121
   * @return <code>g</code>.
139
   */
122
   */
140
  public BigInteger getG()
123
  public BigInteger getG()
Lines 143-170 Link Here
143
  }
126
  }
144
127
145
  /**
128
  /**
146
   * <p>Returns <code>true</code> if the designated object is an instance of
129
   * Returns <code>true</code> if the designated object is an instance of
147
   * <code>SRPKey</code> and has the same SRP parameter values as this one.</p>
130
   * <code>SRPKey</code> and has the same SRP parameter values as this one.
148
   *
131
   * 
149
   * @param obj the other non-null SRP key to compare to.
132
   * @param obj the other non-null SRP key to compare to.
150
   * @return <code>true</code> if the designated object is of the same type and
133
   * @return <code>true</code> if the designated object is of the same type
151
   * value as this one.
134
   *         and value as this one.
152
   */
135
   */
153
  public boolean equals(Object obj)
136
  public boolean equals(Object obj)
154
  {
137
  {
155
    if (obj == null)
138
    if (obj == null)
156
      {
139
      return false;
157
        return false;
140
    if (! (obj instanceof SRPKey))
158
      }
141
      return false;
159
    if (!(obj instanceof SRPKey))
160
      {
161
        return false;
162
      }
163
    SRPKey that = (SRPKey) obj;
142
    SRPKey that = (SRPKey) obj;
164
    return N.equals(that.getN()) && g.equals(that.getG());
143
    return N.equals(that.getN()) && g.equals(that.getG());
165
  }
144
  }
166
145
167
  // abstract methods to be implemented by subclasses ------------------------
168
169
  public abstract byte[] getEncoded(int format);
146
  public abstract byte[] getEncoded(int format);
170
}
147
}
(-)srp6/SRPKeyPairGenerator.java (-70 / +20 lines)
Lines 50-129 Link Here
50
import java.util.logging.Logger;
50
import java.util.logging.Logger;
51
51
52
/**
52
/**
53
 *
53
 * Reference:
54
 *
55
 * <p>Reference:</p>
56
 * <ol>
54
 * <ol>
57
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
55
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
58
 *    Thomas J. Wu.</li>
56
 * Thomas J. Wu.</li>
59
 * </ol>
57
 * </ol>
60
 */
58
 */
61
public class SRPKeyPairGenerator implements IKeyPairGenerator
59
public class SRPKeyPairGenerator
60
    implements IKeyPairGenerator
62
{
61
{
63
  private static final Logger log = Logger.getLogger(SRPKeyPairGenerator.class.getName());
62
  private static final Logger log = Logger.getLogger(SRPKeyPairGenerator.class.getName());
64
  private static final BigInteger ZERO = BigInteger.ZERO;
63
  private static final BigInteger ZERO = BigInteger.ZERO;
65
66
  private static final BigInteger ONE = BigInteger.ONE;
64
  private static final BigInteger ONE = BigInteger.ONE;
67
68
  private static final BigInteger TWO = BigInteger.valueOf(2L);
65
  private static final BigInteger TWO = BigInteger.valueOf(2L);
69
70
  private static final BigInteger THREE = BigInteger.valueOf(3L);
66
  private static final BigInteger THREE = BigInteger.valueOf(3L);
71
72
  /** Property name of the length (Integer) of the modulus (N) of an SRP key. */
67
  /** Property name of the length (Integer) of the modulus (N) of an SRP key. */
73
  public static final String MODULUS_LENGTH = "gnu.crypto.srp.L";
68
  public static final String MODULUS_LENGTH = "gnu.crypto.srp.L";
74
75
  /** Property name of the Boolean indicating wether or not to use defaults. */
69
  /** Property name of the Boolean indicating wether or not to use defaults. */
76
  public static final String USE_DEFAULTS = "gnu.crypto.srp.use.defaults";
70
  public static final String USE_DEFAULTS = "gnu.crypto.srp.use.defaults";
77
78
  /** Property name of the modulus (N) of an SRP key. */
71
  /** Property name of the modulus (N) of an SRP key. */
79
  public static final String SHARED_MODULUS = "gnu.crypto.srp.N";
72
  public static final String SHARED_MODULUS = "gnu.crypto.srp.N";
80
81
  /** Property name of the generator (g) of an SRP key. */
73
  /** Property name of the generator (g) of an SRP key. */
82
  public static final String GENERATOR = "gnu.crypto.srp.g";
74
  public static final String GENERATOR = "gnu.crypto.srp.g";
83
84
  /** Property name of the user's verifier (v) for a Server SRP key. */
75
  /** Property name of the user's verifier (v) for a Server SRP key. */
85
  public static final String USER_VERIFIER = "gnu.crypto.srp.v";
76
  public static final String USER_VERIFIER = "gnu.crypto.srp.v";
86
87
  /**
77
  /**
88
   * Property name of an optional {@link SecureRandom} instance to use. The
78
   * Property name of an optional {@link SecureRandom} instance to use. The
89
   * default is to use a classloader singleton from {@link PRNG}.
79
   * default is to use a classloader singleton from {@link PRNG}.
90
   */
80
   */
91
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp.prng";
81
  public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp.prng";
92
93
  /** Default value for the modulus length. */
82
  /** Default value for the modulus length. */
94
  private static final int DEFAULT_MODULUS_LENGTH = 1024;
83
  private static final int DEFAULT_MODULUS_LENGTH = 1024;
95
96
  /** The optional {@link SecureRandom} instance to use. */
84
  /** The optional {@link SecureRandom} instance to use. */
97
  private SecureRandom rnd = null;
85
  private SecureRandom rnd = null;
98
99
  /** Bit length of the shared modulus. */
86
  /** Bit length of the shared modulus. */
100
  private int l;
87
  private int l;
101
102
  /** The shared public modulus. */
88
  /** The shared public modulus. */
103
  private BigInteger N;
89
  private BigInteger N;
104
105
  /** The Field generator. */
90
  /** The Field generator. */
106
  private BigInteger g;
91
  private BigInteger g;
107
108
  /** The user's verifier MPI. */
92
  /** The user's verifier MPI. */
109
  private BigInteger v;
93
  private BigInteger v;
110
111
  /** Our default source of randomness. */
94
  /** Our default source of randomness. */
112
  private PRNG prng = null;
95
  private PRNG prng = null;
113
96
114
  // Constructor(s)
115
  // -------------------------------------------------------------------------
116
117
  // implicit 0-arguments constructor
97
  // implicit 0-arguments constructor
118
98
119
  // Class methods
120
  // -------------------------------------------------------------------------
121
122
  // Instance methods
123
  // -------------------------------------------------------------------------
124
125
  // gnu.crypto.key.IKeyPairGenerator interface implementation ---------------
126
127
  public String name()
99
  public String name()
128
  {
100
  {
129
    return Registry.SRP_KPG;
101
    return Registry.SRP_KPG;
Lines 133-157 Link Here
133
  {
105
  {
134
    // do we have a SecureRandom, or should we use our own?
106
    // do we have a SecureRandom, or should we use our own?
135
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
107
    rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS);
136
137
    N = (BigInteger) attributes.get(SHARED_MODULUS);
108
    N = (BigInteger) attributes.get(SHARED_MODULUS);
138
    if (N != null)
109
    if (N != null)
139
      {
110
      {
140
        l = N.bitLength();
111
        l = N.bitLength();
141
        g = (BigInteger) attributes.get(GENERATOR);
112
        g = (BigInteger) attributes.get(GENERATOR);
142
        if (g == null)
113
        if (g == null)
143
          {
114
          g = TWO;
144
            g = TWO;
145
          }
146
        SRPAlgorithm.checkParams(N, g);
115
        SRPAlgorithm.checkParams(N, g);
147
      }
116
      }
148
    else
117
    else
149
      { // generate or use default values for N and g
118
      { // generate or use default values for N and g
150
        Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS);
119
        Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS);
151
        if (useDefaults == null)
120
        if (useDefaults == null)
152
          {
121
          useDefaults = Boolean.TRUE;
153
            useDefaults = Boolean.TRUE;
154
          }
155
        Integer L = (Integer) attributes.get(MODULUS_LENGTH);
122
        Integer L = (Integer) attributes.get(MODULUS_LENGTH);
156
        l = DEFAULT_MODULUS_LENGTH;
123
        l = DEFAULT_MODULUS_LENGTH;
157
        if (useDefaults.equals(Boolean.TRUE))
124
        if (useDefaults.equals(Boolean.TRUE))
Lines 184-209 Link Here
184
                    break;
151
                    break;
185
                  default:
152
                  default:
186
                    throw new IllegalArgumentException(
153
                    throw new IllegalArgumentException(
187
                                                       "unknown default shared modulus bit length");
154
                        "unknown default shared modulus bit length");
188
                  }
155
                  }
189
                g = TWO;
156
                g = TWO;
190
                l = N.bitLength();
157
                l = N.bitLength();
191
              }
158
              }
192
          }
159
          }
193
        else
160
        else // generate new N and g
194
          { // generate new N and g
161
          {
195
            if (L != null)
162
            if (L != null)
196
              {
163
              {
197
                l = L.intValue();
164
                l = L.intValue();
198
                if ((l % 256) != 0 || l < 512 || l > 2048)
165
                if ((l % 256) != 0 || l < 512 || l > 2048)
199
                  {
166
                  throw new IllegalArgumentException(
200
                    throw new IllegalArgumentException(
167
                      "invalid shared modulus bit length");
201
                                                       "invalid shared modulus bit length");
202
                  }
203
              }
168
              }
204
          }
169
          }
205
      }
170
      }
206
207
    // are we using this generator on the server side, or the client side?
171
    // are we using this generator on the server side, or the client side?
208
    v = (BigInteger) attributes.get(USER_VERIFIER);
172
    v = (BigInteger) attributes.get(USER_VERIFIER);
209
  }
173
  }
Lines 223-238 Link Here
223
            log.fine("g: " + g.toString(16));
187
            log.fine("g: " + g.toString(16));
224
          }
188
          }
225
      }
189
      }
226
227
    return (v != null ? hostKeyPair() : userKeyPair());
190
    return (v != null ? hostKeyPair() : userKeyPair());
228
  }
191
  }
229
192
230
  // helper methods ----------------------------------------------------------
231
232
  private synchronized BigInteger[] generateParameters()
193
  private synchronized BigInteger[] generateParameters()
233
  {
194
  {
234
    // N    A large safe prime (N = 2q+1, where q is prime)
195
    // N A large safe prime (N = 2q+1, where q is prime)
235
    // g    A generator modulo N
196
    // g A generator modulo N
236
    BigInteger q, p, g;
197
    BigInteger q, p, g;
237
    byte[] qBytes = new byte[l / 8];
198
    byte[] qBytes = new byte[l / 8];
238
    do
199
    do
Lines 247-253 Link Here
247
        p = q.multiply(TWO).add(ONE);
208
        p = q.multiply(TWO).add(ONE);
248
      }
209
      }
249
    while (p.bitLength() != l || ! p.isProbablePrime(80));
210
    while (p.bitLength() != l || ! p.isProbablePrime(80));
250
251
    // compute g. from FIPS-186, Appendix 4: e == 2
211
    // compute g. from FIPS-186, Appendix 4: e == 2
252
    BigInteger p_minus_1 = p.subtract(ONE);
212
    BigInteger p_minus_1 = p.subtract(ONE);
253
    g = TWO;
213
    g = TWO;
Lines 258-269 Link Here
258
        // Set g = h**2 mod p
218
        // Set g = h**2 mod p
259
        g = h.modPow(TWO, p);
219
        g = h.modPow(TWO, p);
260
        // If g = 1, go to step 3
220
        // If g = 1, go to step 3
261
        if (!g.equals(ONE))
221
        if (! g.equals(ONE))
262
          {
222
          break;
263
            break;
264
          }
265
      }
223
      }
266
267
    return new BigInteger[] { q, p, g };
224
    return new BigInteger[] { q, p, g };
268
  }
225
  }
269
226
Lines 282-292 Link Here
282
        B = THREE.multiply(v).add(g.modPow(b, N)).mod(N);
239
        B = THREE.multiply(v).add(g.modPow(b, N)).mod(N);
283
      }
240
      }
284
    while (B.compareTo(ZERO) == 0 || B.compareTo(N) >= 0);
241
    while (B.compareTo(ZERO) == 0 || B.compareTo(N) >= 0);
285
242
    KeyPair result = new KeyPair(new SRPPublicKey(new BigInteger[] { N, g, B }),
286
    KeyPair result = new KeyPair(
243
                                 new SRPPrivateKey(new BigInteger[] { N, g, b, v }));
287
                                 new SRPPublicKey(new BigInteger[] { N, g, B }),
288
                                 new SRPPrivateKey(new BigInteger[] { N, g, b,
289
                                                                     v }));
290
    return result;
244
    return result;
291
  }
245
  }
292
246
Lines 305-313 Link Here
305
        A = g.modPow(a, N);
259
        A = g.modPow(a, N);
306
      }
260
      }
307
    while (A.compareTo(ZERO) == 0 || A.compareTo(N) >= 0);
261
    while (A.compareTo(ZERO) == 0 || A.compareTo(N) >= 0);
308
262
    KeyPair result = new KeyPair(new SRPPublicKey(new BigInteger[] { N, g, A }),
309
    KeyPair result = new KeyPair(
310
                                 new SRPPublicKey(new BigInteger[] { N, g, A }),
311
                                 new SRPPrivateKey(new BigInteger[] { N, g, a }));
263
                                 new SRPPrivateKey(new BigInteger[] { N, g, a }));
312
    return result;
264
    return result;
313
  }
265
  }
Lines 315-323 Link Here
315
  private void nextRandomBytes(byte[] buffer)
267
  private void nextRandomBytes(byte[] buffer)
316
  {
268
  {
317
    if (rnd != null)
269
    if (rnd != null)
318
      {
270
      rnd.nextBytes(buffer);
319
        rnd.nextBytes(buffer);
320
      }
321
    else
271
    else
322
      getDefaultPRNG().nextBytes(buffer);
272
      getDefaultPRNG().nextBytes(buffer);
323
  }
273
  }
(-)srp6/SRPKeyPairRawCodec.java (-169 / +123 lines)
Lines 47-162 Link Here
47
import java.security.PublicKey;
47
import java.security.PublicKey;
48
48
49
/**
49
/**
50
 * <p>An object that implements the {@link IKeyPairCodec} operations for the
50
 * An object that implements the {@link IKeyPairCodec} operations for the
51
 * <i>Raw</i> format to use with SRP keypairs.</p>
51
 * <i>Raw</i> format to use with SRP keypairs.
52
 *
52
 * <p>
53
 * <p>Reference:</p>
53
 * Reference:
54
 * <ol>
54
 * <ol>
55
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
55
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
56
 *    Thomas J. Wu.</li>
56
 * Thomas J. Wu.</li>
57
 * </ol>
57
 * </ol>
58
 */
58
 */
59
public class SRPKeyPairRawCodec implements IKeyPairCodec
59
public class SRPKeyPairRawCodec
60
    implements IKeyPairCodec
60
{
61
{
61
62
  // Constants and variables
63
  // -------------------------------------------------------------------------
64
65
  // Constructor(s)
66
  // -------------------------------------------------------------------------
67
68
  // implicit 0-arguments constructor
62
  // implicit 0-arguments constructor
69
63
70
  // Class methods
71
  // -------------------------------------------------------------------------
72
73
  // Instance methods
74
  // -------------------------------------------------------------------------
75
76
  // gnu.crypto.keys.IKeyPairCodec interface implementation ------------------
77
78
  public int getFormatID()
64
  public int getFormatID()
79
  {
65
  {
80
    return RAW_FORMAT;
66
    return RAW_FORMAT;
81
  }
67
  }
82
68
83
  /**
69
  /**
84
   * <p>Returns the encoded form of the designated SRP public key according to
70
   * Returns the encoded form of the designated SRP public key according to the
85
   * the <i>Raw</i> format supported by this library.</p>
71
   * <i>Raw</i> format supported by this library.
86
   *
72
   * <p>
87
   * <p>The <i>Raw</i> format for an SRP public key, in this implementation, is
73
   * The <i>Raw</i> format for an SRP public key, in this implementation, is a
88
   * a byte sequence consisting of the following:</p>
74
   * byte sequence consisting of the following:
89
   * <ol>
75
   * <ol>
90
   *    <li>4-byte magic consisting of the value of the literal
76
   * <li>4-byte magic consisting of the value of the literal
91
   *    {@link Registry#MAGIC_RAW_SRP_PUBLIC_KEY},<li>
77
   * {@link Registry#MAGIC_RAW_SRP_PUBLIC_KEY},</li>
92
   *    <li>1-byte version consisting of the constant: 0x01,</li>
78
   * <li>1-byte version consisting of the constant: 0x01,</li>
93
   *    <li>4-byte count of following bytes representing the SRP parameter
79
   * <li>4-byte count of following bytes representing the SRP parameter
94
   *    <code>N</code> in internet order,</li>
80
   * <code>N</code> in internet order,</li>
95
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
81
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
96
   *    the <code>toByteArray()</code> method on the SRP parameter
82
   * the <code>toByteArray()</code> method on the SRP parameter <code>N</code>,
97
   *    <code>N</code>,</li>
83
   * </li>
98
   *    <li>4-byte count of following bytes representing the SRP parameter
84
   * <li>4-byte count of following bytes representing the SRP parameter
99
   *    <code>g</code>,</li>
85
   * <code>g</code>,</li>
100
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
86
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
101
   *    the <code>toByteArray()</code> method on the SRP parameter
87
   * the <code>toByteArray()</code> method on the SRP parameter <code>g</code>,
102
   *    <code>g</code>,</li>
88
   * </li>
103
   *    <li>4-byte count of following bytes representing the SRP parameter
89
   * <li>4-byte count of following bytes representing the SRP parameter
104
   *    <code>y</code>,</li>
90
   * <code>y</code>,</li>
105
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
91
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
106
   *    the <code>toByteArray()</code> method on the SRP parameter
92
   * the <code>toByteArray()</code> method on the SRP parameter <code>y</code>,
107
   *    <code>y</code>,</li>
93
   * </li>
108
   * </ol>
94
   * </ol>
109
   *
95
   * 
110
   * @param key the key to encode.
96
   * @param key the key to encode.
111
   * @return the <i>Raw</i> format encoding of the designated key.
97
   * @return the <i>Raw</i> format encoding of the designated key.
112
   * @throws IllegalArgumentException if the designated key is not an SRP one.
98
   * @throws IllegalArgumentException if the designated key is not an SRP one.
113
   */
99
   */
114
  public byte[] encodePublicKey(PublicKey key)
100
  public byte[] encodePublicKey(PublicKey key)
115
  {
101
  {
116
    if (!(key instanceof SRPPublicKey))
102
    if (! (key instanceof SRPPublicKey))
117
      {
103
      throw new IllegalArgumentException("key");
118
        throw new IllegalArgumentException("key");
119
      }
120
121
    SRPPublicKey srpKey = (SRPPublicKey) key;
104
    SRPPublicKey srpKey = (SRPPublicKey) key;
122
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
105
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
123
124
    // magic
106
    // magic
125
    baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[0]);
107
    baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[0]);
126
    baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[1]);
108
    baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[1]);
127
    baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[2]);
109
    baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[2]);
128
    baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[3]);
110
    baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[3]);
129
130
    // version
111
    // version
131
    baos.write(0x01);
112
    baos.write(0x01);
132
133
    // N
113
    // N
134
    byte[] buffer = srpKey.getN().toByteArray();
114
    byte[] buffer = srpKey.getN().toByteArray();
135
    int length = buffer.length;
115
    int length = buffer.length;
136
    baos.write(length >>> 24);
116
    baos.write( length >>> 24);
137
    baos.write((length >>> 16) & 0xFF);
117
    baos.write((length >>> 16) & 0xFF);
138
    baos.write((length >>> 8) & 0xFF);
118
    baos.write((length >>>  8) & 0xFF);
139
    baos.write(length & 0xFF);
119
    baos.write( length         & 0xFF);
140
    baos.write(buffer, 0, length);
120
    baos.write(buffer, 0, length);
141
142
    // g
121
    // g
143
    buffer = srpKey.getG().toByteArray();
122
    buffer = srpKey.getG().toByteArray();
144
    length = buffer.length;
123
    length = buffer.length;
145
    baos.write(length >>> 24);
124
    baos.write( length >>> 24);
146
    baos.write((length >>> 16) & 0xFF);
125
    baos.write((length >>> 16) & 0xFF);
147
    baos.write((length >>> 8) & 0xFF);
126
    baos.write((length >>>  8) & 0xFF);
148
    baos.write(length & 0xFF);
127
    baos.write( length         & 0xFF);
149
    baos.write(buffer, 0, length);
128
    baos.write(buffer, 0, length);
150
151
    // y
129
    // y
152
    buffer = srpKey.getY().toByteArray();
130
    buffer = srpKey.getY().toByteArray();
153
    length = buffer.length;
131
    length = buffer.length;
154
    baos.write(length >>> 24);
132
    baos.write( length >>> 24);
155
    baos.write((length >>> 16) & 0xFF);
133
    baos.write((length >>> 16) & 0xFF);
156
    baos.write((length >>> 8) & 0xFF);
134
    baos.write((length >>>  8) & 0xFF);
157
    baos.write(length & 0xFF);
135
    baos.write( length         & 0xFF);
158
    baos.write(buffer, 0, length);
136
    baos.write(buffer, 0, length);
159
160
    return baos.toByteArray();
137
    return baos.toByteArray();
161
  }
138
  }
162
139
Lines 167-316 Link Here
167
        || k[1] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[1]
144
        || k[1] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[1]
168
        || k[2] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[2]
145
        || k[2] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[2]
169
        || k[3] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[3])
146
        || k[3] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[3])
170
      {
147
      throw new IllegalArgumentException("magic");
171
        throw new IllegalArgumentException("magic");
172
      }
173
174
    // version
148
    // version
175
    if (k[4] != 0x01)
149
    if (k[4] != 0x01)
176
      {
150
      throw new IllegalArgumentException("version");
177
        throw new IllegalArgumentException("version");
178
      }
179
    int i = 5;
151
    int i = 5;
180
181
    int l;
152
    int l;
182
    byte[] buffer;
153
    byte[] buffer;
183
184
    // N
154
    // N
185
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
155
    l =  k[i++]         << 24
186
        | (k[i++] & 0xFF);
156
      | (k[i++] & 0xFF) << 16
157
      | (k[i++] & 0xFF) << 8
158
      | (k[i++] & 0xFF);
187
    buffer = new byte[l];
159
    buffer = new byte[l];
188
    System.arraycopy(k, i, buffer, 0, l);
160
    System.arraycopy(k, i, buffer, 0, l);
189
    i += l;
161
    i += l;
190
    BigInteger N = new BigInteger(1, buffer);
162
    BigInteger N = new BigInteger(1, buffer);
191
192
    // g
163
    // g
193
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
164
    l =  k[i++]         << 24
194
        | (k[i++] & 0xFF);
165
      | (k[i++] & 0xFF) << 16
166
      | (k[i++] & 0xFF) << 8
167
      | (k[i++] & 0xFF);
195
    buffer = new byte[l];
168
    buffer = new byte[l];
196
    System.arraycopy(k, i, buffer, 0, l);
169
    System.arraycopy(k, i, buffer, 0, l);
197
    i += l;
170
    i += l;
198
    BigInteger g = new BigInteger(1, buffer);
171
    BigInteger g = new BigInteger(1, buffer);
199
200
    // y
172
    // y
201
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
173
    l =  k[i++]         << 24
202
        | (k[i++] & 0xFF);
174
      | (k[i++] & 0xFF) << 16
175
      | (k[i++] & 0xFF) << 8
176
      | (k[i++] & 0xFF);
203
    buffer = new byte[l];
177
    buffer = new byte[l];
204
    System.arraycopy(k, i, buffer, 0, l);
178
    System.arraycopy(k, i, buffer, 0, l);
205
    i += l;
179
    i += l;
206
    BigInteger y = new BigInteger(1, buffer);
180
    BigInteger y = new BigInteger(1, buffer);
207
208
    return new SRPPublicKey(N, g, y);
181
    return new SRPPublicKey(N, g, y);
209
  }
182
  }
210
183
211
  /**
184
  /**
212
   * <p>Returns the encoded form of the designated SRP private key according to
185
   * Returns the encoded form of the designated SRP private key according to the
213
   * the <i>Raw</i> format supported by this library.</p>
186
   * <i>Raw</i> format supported by this library.
214
   *
187
   * <p>
215
   * <p>The <i>Raw</i> format for an SRP private key, in this implementation,
188
   * The <i>Raw</i> format for an SRP private key, in this implementation, is a
216
   * is a byte sequence consisting of the following:</p>
189
   * byte sequence consisting of the following:
217
   * <ol>
190
   * <ol>
218
   *    <li>4-byte magic consisting of the value of the literal
191
   * <li>4-byte magic consisting of the value of the literal
219
   *    {@link Registry#MAGIC_RAW_SRP_PRIVATE_KEY},<li>
192
   * {@link Registry#MAGIC_RAW_SRP_PRIVATE_KEY},</li>
220
   *    <li>1-byte version consisting of the constant: 0x01,</li>
193
   * <li>1-byte version consisting of the constant: 0x01,</li>
221
   *    <li>4-byte count of following bytes representing the SRP parameter
194
   * <li>4-byte count of following bytes representing the SRP parameter
222
   *    <code>N</code> in internet order,</li>
195
   * <code>N</code> in internet order,</li>
223
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
196
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
224
   *    the <code>toByteArray()</code> method on the SRP parameter
197
   * the <code>toByteArray()</code> method on the SRP parameter <code>N</code>,
225
   *    <code>N</code>,</li>
198
   * </li>
226
   *    <li>4-byte count of following bytes representing the SRP parameter
199
   * <li>4-byte count of following bytes representing the SRP parameter
227
   *    <code>g</code>,</li>
200
   * <code>g</code>,</li>
228
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
201
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
229
   *    the <code>toByteArray()</code> method on the SRP parameter
202
   * the <code>toByteArray()</code> method on the SRP parameter <code>g</code>,
230
   *    <code>g</code>,</li>
203
   * </li>
231
   *    <li>4-byte count of following bytes representing the SRP parameter
204
   * <li>4-byte count of following bytes representing the SRP parameter
232
   *    <code>x</code>,</li>
205
   * <code>x</code>,</li>
233
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
206
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
234
   *    the <code>toByteArray()</code> method on the SRP parameter
207
   * the <code>toByteArray()</code> method on the SRP parameter <code>x</code>,
235
   *    <code>x</code>,</li>
208
   * </li>
236
   *    <li>one byte which indicates whether the SRP parameter <code>v</code>
209
   * <li>one byte which indicates whether the SRP parameter <code>v</code> is
237
   *    is included in this encoding (value <code>0x01</code>) or not
210
   * included in this encoding (value <code>0x01</code>) or not (value
238
   *    (value <code>0x00</code>).</li>
211
   * <code>0x00</code>).</li>
239
   *    <li>4-byte count of following bytes representing the SRP parameter
212
   * <li>4-byte count of following bytes representing the SRP parameter
240
   *    <code>v</code>,</li>
213
   * <code>v</code>,</li>
241
   *    <li>n-bytes representation of a {@link BigInteger} obtained by invoking
214
   * <li>n-bytes representation of a {@link BigInteger} obtained by invoking
242
   *    the <code>toByteArray()</code> method on the SRP parameter
215
   * the <code>toByteArray()</code> method on the SRP parameter <code>v</code>,
243
   *    <code>v</code>,</li>
216
   * </li>
244
   * </ol>
217
   * </ol>
245
   *
218
   * 
246
   * @param key the key to encode.
219
   * @param key the key to encode.
247
   * @return the <i>Raw</i> format encoding of the designated key.
220
   * @return the <i>Raw</i> format encoding of the designated key.
248
   * @throws IllegalArgumentException if the designated key is not an SRP one.
221
   * @throws IllegalArgumentException if the designated key is not an SRP one.
249
   */
222
   */
250
  public byte[] encodePrivateKey(PrivateKey key)
223
  public byte[] encodePrivateKey(PrivateKey key)
251
  {
224
  {
252
    if (!(key instanceof SRPPrivateKey))
225
    if (! (key instanceof SRPPrivateKey))
253
      {
226
      throw new IllegalArgumentException("key");
254
        throw new IllegalArgumentException("key");
255
      }
256
257
    SRPPrivateKey srpKey = (SRPPrivateKey) key;
227
    SRPPrivateKey srpKey = (SRPPrivateKey) key;
258
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
228
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
259
260
    // magic
229
    // magic
261
    baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[0]);
230
    baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[0]);
262
    baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[1]);
231
    baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[1]);
263
    baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[2]);
232
    baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[2]);
264
    baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[3]);
233
    baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[3]);
265
266
    // version
234
    // version
267
    baos.write(0x01);
235
    baos.write(0x01);
268
269
    // N
236
    // N
270
    byte[] buffer = srpKey.getN().toByteArray();
237
    byte[] buffer = srpKey.getN().toByteArray();
271
    int length = buffer.length;
238
    int length = buffer.length;
272
    baos.write(length >>> 24);
239
    baos.write( length >>> 24);
273
    baos.write((length >>> 16) & 0xFF);
240
    baos.write((length >>> 16) & 0xFF);
274
    baos.write((length >>> 8) & 0xFF);
241
    baos.write((length >>>  8) & 0xFF);
275
    baos.write(length & 0xFF);
242
    baos.write( length         & 0xFF);
276
    baos.write(buffer, 0, length);
243
    baos.write(buffer, 0, length);
277
278
    // g
244
    // g
279
    buffer = srpKey.getG().toByteArray();
245
    buffer = srpKey.getG().toByteArray();
280
    length = buffer.length;
246
    length = buffer.length;
281
    baos.write(length >>> 24);
247
    baos.write( length >>> 24);
282
    baos.write((length >>> 16) & 0xFF);
248
    baos.write((length >>> 16) & 0xFF);
283
    baos.write((length >>> 8) & 0xFF);
249
    baos.write((length >>>  8) & 0xFF);
284
    baos.write(length & 0xFF);
250
    baos.write( length         & 0xFF);
285
    baos.write(buffer, 0, length);
251
    baos.write(buffer, 0, length);
286
287
    // x
252
    // x
288
    buffer = srpKey.getX().toByteArray();
253
    buffer = srpKey.getX().toByteArray();
289
    length = buffer.length;
254
    length = buffer.length;
290
    baos.write(length >>> 24);
255
    baos.write( length >>> 24);
291
    baos.write((length >>> 16) & 0xFF);
256
    baos.write((length >>> 16) & 0xFF);
292
    baos.write((length >>> 8) & 0xFF);
257
    baos.write((length >>>  8) & 0xFF);
293
    baos.write(length & 0xFF);
258
    baos.write( length         & 0xFF);
294
    baos.write(buffer, 0, length);
259
    baos.write(buffer, 0, length);
295
296
    // v
260
    // v
297
    if (srpKey.getV() != null)
261
    if (srpKey.getV() != null)
298
      {
262
      {
299
        baos.write(0x01);
263
        baos.write(0x01);
300
301
        buffer = srpKey.getV().toByteArray();
264
        buffer = srpKey.getV().toByteArray();
302
        length = buffer.length;
265
        length = buffer.length;
303
        baos.write(length >>> 24);
266
        baos.write( length >>> 24);
304
        baos.write((length >>> 16) & 0xFF);
267
        baos.write((length >>> 16) & 0xFF);
305
        baos.write((length >>> 8) & 0xFF);
268
        baos.write((length >>>  8) & 0xFF);
306
        baos.write(length & 0xFF);
269
        baos.write( length         & 0xFF);
307
        baos.write(buffer, 0, length);
270
        baos.write(buffer, 0, length);
308
      }
271
      }
309
    else
272
    else
310
      {
273
      baos.write(0x00);
311
        baos.write(0x00);
312
      }
313
314
    return baos.toByteArray();
274
    return baos.toByteArray();
315
  }
275
  }
316
276
Lines 321-380 Link Here
321
        || k[1] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[1]
281
        || k[1] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[1]
322
        || k[2] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[2]
282
        || k[2] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[2]
323
        || k[3] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[3])
283
        || k[3] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[3])
324
      {
284
      throw new IllegalArgumentException("magic");
325
        throw new IllegalArgumentException("magic");
326
      }
327
328
    // version
285
    // version
329
    if (k[4] != 0x01)
286
    if (k[4] != 0x01)
330
      {
287
      throw new IllegalArgumentException("version");
331
        throw new IllegalArgumentException("version");
332
      }
333
    int i = 5;
288
    int i = 5;
334
335
    int l;
289
    int l;
336
    byte[] buffer;
290
    byte[] buffer;
337
338
    // N
291
    // N
339
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
292
    l =  k[i++]         << 24
340
        | (k[i++] & 0xFF);
293
      | (k[i++] & 0xFF) << 16
294
      | (k[i++] & 0xFF) << 8
295
      | (k[i++] & 0xFF);
341
    buffer = new byte[l];
296
    buffer = new byte[l];
342
    System.arraycopy(k, i, buffer, 0, l);
297
    System.arraycopy(k, i, buffer, 0, l);
343
    i += l;
298
    i += l;
344
    BigInteger N = new BigInteger(1, buffer);
299
    BigInteger N = new BigInteger(1, buffer);
345
346
    // g
300
    // g
347
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
301
    l =  k[i++]         << 24
348
        | (k[i++] & 0xFF);
302
      | (k[i++] & 0xFF) << 16
303
      | (k[i++] & 0xFF) << 8
304
      | (k[i++] & 0xFF);
349
    buffer = new byte[l];
305
    buffer = new byte[l];
350
    System.arraycopy(k, i, buffer, 0, l);
306
    System.arraycopy(k, i, buffer, 0, l);
351
    i += l;
307
    i += l;
352
    BigInteger g = new BigInteger(1, buffer);
308
    BigInteger g = new BigInteger(1, buffer);
353
354
    // x
309
    // x
355
    l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
310
    l =  k[i++]         << 24
356
        | (k[i++] & 0xFF);
311
      | (k[i++] & 0xFF) << 16
312
      | (k[i++] & 0xFF) << 8
313
      | (k[i++] & 0xFF);
357
    buffer = new byte[l];
314
    buffer = new byte[l];
358
    System.arraycopy(k, i, buffer, 0, l);
315
    System.arraycopy(k, i, buffer, 0, l);
359
    i += l;
316
    i += l;
360
    BigInteger x = new BigInteger(1, buffer);
317
    BigInteger x = new BigInteger(1, buffer);
361
362
    // v
318
    // v
363
    l = k[i++];
319
    l = k[i++];
364
    if (l == 0x01)
320
    if (l == 0x01)
365
      {
321
      {
366
        l = k[i++] << 24 | (k[i++] & 0xFF) << 16 | (k[i++] & 0xFF) << 8
322
        l =  k[i++]         << 24
367
            | (k[i++] & 0xFF);
323
          | (k[i++] & 0xFF) << 16
324
          | (k[i++] & 0xFF) << 8
325
          | (k[i++] & 0xFF);
368
        buffer = new byte[l];
326
        buffer = new byte[l];
369
        System.arraycopy(k, i, buffer, 0, l);
327
        System.arraycopy(k, i, buffer, 0, l);
370
        i += l;
328
        i += l;
371
        BigInteger v = new BigInteger(1, buffer);
329
        BigInteger v = new BigInteger(1, buffer);
372
373
        return new SRPPrivateKey(N, g, x, v);
330
        return new SRPPrivateKey(N, g, x, v);
374
      }
331
      }
375
    else
332
    return new SRPPrivateKey(N, g, x);
376
      {
377
        return new SRPPrivateKey(N, g, x);
378
      }
379
  }
333
  }
380
}
334
}
(-)srp6/SRPPrivateKey.java (-76 / +53 lines)
Lines 45-83 Link Here
45
import java.security.PrivateKey;
45
import java.security.PrivateKey;
46
46
47
/**
47
/**
48
 * <p>A representation of an SRP ephemeral private key.</p>
48
 * A representation of an SRP ephemeral private key.
49
 *
49
 * <p>
50
 * <p>Reference:</p>
50
 * Reference:
51
 * <ol>
51
 * <ol>
52
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
52
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
53
 *    Thomas J. Wu.</li>
53
 * Thomas J. Wu.</li>
54
 * </ol>
54
 * </ol>
55
 */
55
 */
56
public class SRPPrivateKey extends SRPKey implements PrivateKey
56
public class SRPPrivateKey
57
    extends SRPKey
58
    implements PrivateKey
57
{
59
{
58
59
  // Constants and variables
60
  // -------------------------------------------------------------------------
61
62
  /**
60
  /**
63
   * The private exponent for either the server or the client engaged in the
61
   * The private exponent for either the server or the client engaged in the SRP
64
   * SRP protocol exchange.
62
   * protocol exchange.
65
   */
63
   */
66
  private final BigInteger X;
64
  private final BigInteger X;
67
68
  /**
65
  /**
69
   * The user's verifier (v) --for the server-- also computed at the client
66
   * The user's verifier (v) --for the server-- also computed at the client side
70
   * side as g.modPow(x, N), where x is the hashed output of the user name and
67
   * as g.modPow(x, N), where x is the hashed output of the user name and
71
   * password .
68
   * password .
72
   */
69
   */
73
  private final BigInteger v;
70
  private final BigInteger v;
74
71
75
  // Constructor(s)
76
  // -------------------------------------------------------------------------
77
78
  /**
72
  /**
79
   * <p>Public constructor for use from outside this package.</p>
73
   * Public constructor for use from outside this package.
80
   *
74
   * 
81
   * @param N the public shared modulus.
75
   * @param N the public shared modulus.
82
   * @param g the generator.
76
   * @param g the generator.
83
   * @param x the private exponent of the ephemeral key.
77
   * @param x the private exponent of the ephemeral key.
Lines 88-95 Link Here
88
  }
82
  }
89
83
90
  /**
84
  /**
91
   * <p>Public constructor for use from outside this package.</p>
85
   * Public constructor for use from outside this package.
92
   *
86
   * 
93
   * @param N the public shared modulus.
87
   * @param N the public shared modulus.
94
   * @param g the generator.
88
   * @param g the generator.
95
   * @param x the private exponent of the ephemeral key.
89
   * @param x the private exponent of the ephemeral key.
Lines 105-119 Link Here
105
  }
99
  }
106
100
107
  /**
101
  /**
108
   * <p>Default constructor. Assumes N and g are already validated.</p>
102
   * Default constructor. Assumes N and g are already validated.
109
   *
103
   * 
110
   * @param params an array of either 3 or 4 values representing N, g, and
104
   * @param params an array of either 3 or 4 values representing N, g, and
111
   * either v and X for the server, or just X for the client. Those values
105
   *          either v and X for the server, or just X for the client. Those
112
   * represent the following:
106
   *          values represent the following:
113
   * <ol>
107
   *          <ol>
114
   *    <li>v (server side): the user's verifier.</li>
108
   *          <li>v (server side): the user's verifier.</li>
115
   *    <li>X (both sides): the server's or client's ephemeral private exponent.</li>
109
   *          <li>X (both sides): the server's or client's ephemeral private
116
   * </ol>
110
   *          exponent.</li>
111
   *          </ol>
117
   */
112
   */
118
  SRPPrivateKey(BigInteger[] params)
113
  SRPPrivateKey(BigInteger[] params)
119
  {
114
  {
Lines 130-160 Link Here
130
        v = params[3];
125
        v = params[3];
131
      }
126
      }
132
    else
127
    else
133
      {
128
      throw new IllegalArgumentException("invalid number of SRP parameters");
134
        throw new IllegalArgumentException("invalid number of SRP parameters");
135
      }
136
  }
129
  }
137
130
138
  // Class methods
139
  // -------------------------------------------------------------------------
140
141
  /**
131
  /**
142
   * <p>A class method that takes the output of the <code>encodePrivateKey()</code>
132
   * A class method that takes the output of the <code>encodePrivateKey()</code>
143
   * method of an SRP keypair codec object (an instance implementing
133
   * method of an SRP keypair codec object (an instance implementing
144
   * {@link IKeyPairCodec} for DSS keys, and re-constructs an instance of this
134
   * {@link IKeyPairCodec} for DSS keys, and re-constructs an instance of this
145
   * object.</p>
135
   * object.
146
   *
136
   * 
147
   * @param k the contents of a previously encoded instance of this object.
137
   * @param k the contents of a previously encoded instance of this object.
148
   * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
138
   * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
149
   * <code>k</code>, to represent a valid encoding of an instance of this object.
139
   *           <code>k</code>, to represent a valid encoding of an instance
140
   *           of this object.
150
   * @throws IllegalArgumentException if the byte sequence does not represent a
141
   * @throws IllegalArgumentException if the byte sequence does not represent a
151
   * valid encoding of an instance of this object.
142
   *           valid encoding of an instance of this object.
152
   */
143
   */
153
  public static SRPPrivateKey valueOf(byte[] k)
144
  public static SRPPrivateKey valueOf(byte[] k)
154
  {
145
  {
155
    // check magic...
146
    // check magic...
156
    // we should parse here enough bytes to know which codec to use, and
147
    // we should parse here enough bytes to know which codec to use, and
157
    // direct the byte array to the appropriate codec.  since we only have one
148
    // direct the byte array to the appropriate codec. since we only have one
158
    // codec, we could have immediately tried it; nevertheless since testing
149
    // codec, we could have immediately tried it; nevertheless since testing
159
    // one byte is cheaper than instatiating a codec that will fail we test
150
    // one byte is cheaper than instatiating a codec that will fail we test
160
    // the first byte before we carry on.
151
    // the first byte before we carry on.
Lines 164-181 Link Here
164
        IKeyPairCodec codec = new SRPKeyPairRawCodec();
155
        IKeyPairCodec codec = new SRPKeyPairRawCodec();
165
        return (SRPPrivateKey) codec.decodePrivateKey(k);
156
        return (SRPPrivateKey) codec.decodePrivateKey(k);
166
      }
157
      }
167
    else
158
    throw new IllegalArgumentException("magic");
168
      {
169
        throw new IllegalArgumentException("magic");
170
      }
171
  }
159
  }
172
160
173
  // Instance methods
174
  // -------------------------------------------------------------------------
175
176
  /**
161
  /**
177
   * <p>Returns the private exponent of the key as a {@link BigInteger}.</p>
162
   * Returns the private exponent of the key as a {@link BigInteger}.
178
   *
163
   * 
179
   * @return the private exponent of the key as a {@link BigInteger}.
164
   * @return the private exponent of the key as a {@link BigInteger}.
180
   */
165
   */
181
  public BigInteger getX()
166
  public BigInteger getX()
Lines 184-209 Link Here
184
  }
169
  }
185
170
186
  /**
171
  /**
187
   * <p>Returns the user's verifier as a {@link BigInteger}.</p>
172
   * Returns the user's verifier as a {@link BigInteger}.
188
   *
173
   * 
189
   * @return the user's verifier as a {@link BigInteger} if this is an SRP
174
   * @return the user's verifier as a {@link BigInteger} if this is an SRP
190
   * private key of a Host, or <code>null</code> if this is a private SRP key
175
   *         private key of a Host, or <code>null</code> if this is a private
191
   * for a User.
176
   *         SRP key for a User.
192
   */
177
   */
193
  public BigInteger getV()
178
  public BigInteger getV()
194
  {
179
  {
195
    return v;
180
    return v;
196
  }
181
  }
197
182
198
  // Other instance methods --------------------------------------------------
199
200
  /**
183
  /**
201
   * <p>Returns the encoded form of this private key according to the
184
   * Returns the encoded form of this private key according to the designated
202
   * designated format.</p>
185
   * format.
203
   *
186
   * 
204
   * @param format the desired format identifier of the resulting encoding.
187
   * @param format the desired format identifier of the resulting encoding.
205
   * @return the byte sequence encoding this key according to the designated
188
   * @return the byte sequence encoding this key according to the designated
206
   * format.
189
   *         format.
207
   * @throws IllegalArgumentException if the format is not supported.
190
   * @throws IllegalArgumentException if the format is not supported.
208
   */
191
   */
209
  public byte[] getEncoded(int format)
192
  public byte[] getEncoded(int format)
Lines 221-250 Link Here
221
  }
204
  }
222
205
223
  /**
206
  /**
224
   * <p>Returns <code>true</code> if the designated object is an instance of
207
   * Returns <code>true</code> if the designated object is an instance of
225
   * <code>SRPPrivateKey</code> and has the same SRP parameter values as this
208
   * <code>SRPPrivateKey</code> and has the same SRP parameter values as this
226
   * one.</p>
209
   * one.
227
   *
210
   * 
228
   * @param obj the other non-null SRP key to compare to.
211
   * @param obj the other non-null SRP key to compare to.
229
   * @return <code>true</code> if the designated object is of the same type and
212
   * @return <code>true</code> if the designated object is of the same type
230
   * value as this one.
213
   *         and value as this one.
231
   */
214
   */
232
  public boolean equals(Object obj)
215
  public boolean equals(Object obj)
233
  {
216
  {
234
    if (obj == null)
217
    if (obj == null)
235
      {
218
      return false;
236
        return false;
219
    if (! (obj instanceof SRPPrivateKey))
237
      }
220
      return false;
238
    if (!(obj instanceof SRPPrivateKey))
239
      {
240
        return false;
241
      }
242
    SRPPrivateKey that = (SRPPrivateKey) obj;
221
    SRPPrivateKey that = (SRPPrivateKey) obj;
243
    boolean result = super.equals(that) && X.equals(that.getX());
222
    boolean result = super.equals(that) && X.equals(that.getX());
244
    if (v != null)
223
    if (v != null)
245
      {
224
      result = result && v.equals(that.getV());
246
        result = result && v.equals(that.getV());
247
      }
248
    return result;
225
    return result;
249
  }
226
  }
250
}
227
}
(-)srp6/SRPPublicKey.java (-57 / +38 lines)
Lines 45-76 Link Here
45
import java.security.PublicKey;
45
import java.security.PublicKey;
46
46
47
/**
47
/**
48
 * <p>A representation of an SRP ephemeral public key.</p>
48
 * A representation of an SRP ephemeral public key.
49
 *
49
 * <p>
50
 * <p>Reference:</p>
50
 * Reference:
51
 * <ol>
51
 * <ol>
52
 *    <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
52
 * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br>
53
 *    Thomas J. Wu.</li>
53
 * Thomas J. Wu.</li>
54
 * </ol>
54
 * </ol>
55
 */
55
 */
56
public class SRPPublicKey extends SRPKey implements PublicKey
56
public class SRPPublicKey
57
    extends SRPKey
58
    implements PublicKey
57
{
59
{
58
59
  // Constants and variables
60
  // -------------------------------------------------------------------------
61
62
  /**
60
  /**
63
   * The public exponent for either the server or the client engaged in the
61
   * The public exponent for either the server or the client engaged in the SRP
64
   * SRP protocol exchange.
62
   * protocol exchange.
65
   */
63
   */
66
  private final BigInteger Y;
64
  private final BigInteger Y;
67
65
68
  // Constructor(s)
69
  // -------------------------------------------------------------------------
70
71
  /**
66
  /**
72
   * <p>Public constructor for use from outside this package.</p>
67
   * Public constructor for use from outside this package.
73
   *
68
   * 
74
   * @param N the public shared modulus.
69
   * @param N the public shared modulus.
75
   * @param g the generator.
70
   * @param g the generator.
76
   * @param Y the public exponent of the ephemeral key.
71
   * @param Y the public exponent of the ephemeral key.
Lines 84-93 Link Here
84
  }
79
  }
85
80
86
  /**
81
  /**
87
   * <p>Default constructor. Assumes that N and g are already validated.</p>
82
   * Default constructor. Assumes that N and g are already validated.
88
   *
83
   * 
89
   * @param params an array of 3 values representing N, g and Y; the latter
84
   * @param params an array of 3 values representing N, g and Y; the latter
90
   * being the client's or server's public exponent.
85
   *          being the client's or server's public exponent.
91
   */
86
   */
92
  SRPPublicKey(BigInteger[] params)
87
  SRPPublicKey(BigInteger[] params)
93
  {
88
  {
Lines 96-121 Link Here
96
    this.Y = params[2];
91
    this.Y = params[2];
97
  }
92
  }
98
93
99
  // Class methods
100
  // -------------------------------------------------------------------------
101
102
  /**
94
  /**
103
   * <p>A class method that takes the output of the <code>encodePublicKey()</code>
95
   * A class method that takes the output of the <code>encodePublicKey()</code>
104
   * method of an SRP keypair codec object (an instance implementing
96
   * method of an SRP keypair codec object (an instance implementing
105
   * {@link IKeyPairCodec} for SRP keys, and re-constructs an instance of this
97
   * {@link IKeyPairCodec} for SRP keys, and re-constructs an instance of this
106
   * object.</p>
98
   * object.
107
   *
99
   * 
108
   * @param k the contents of a previously encoded instance of this object.
100
   * @param k the contents of a previously encoded instance of this object.
109
   * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
101
   * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in
110
   * <code>k</code>, to represent a valid encoding of an instance of this object.
102
   *           <code>k</code>, to represent a valid encoding of an instance
103
   *           of this object.
111
   * @throws IllegalArgumentException if the byte sequence does not represent a
104
   * @throws IllegalArgumentException if the byte sequence does not represent a
112
   * valid encoding of an instance of this object.
105
   *           valid encoding of an instance of this object.
113
   */
106
   */
114
  public static SRPPublicKey valueOf(byte[] k)
107
  public static SRPPublicKey valueOf(byte[] k)
115
  {
108
  {
116
    // check magic...
109
    // check magic...
117
    // we should parse here enough bytes to know which codec to use, and
110
    // we should parse here enough bytes to know which codec to use, and
118
    // direct the byte array to the appropriate codec.  since we only have one
111
    // direct the byte array to the appropriate codec. since we only have one
119
    // codec, we could have immediately tried it; nevertheless since testing
112
    // codec, we could have immediately tried it; nevertheless since testing
120
    // one byte is cheaper than instatiating a codec that will fail we test
113
    // one byte is cheaper than instatiating a codec that will fail we test
121
    // the first byte before we carry on.
114
    // the first byte before we carry on.
Lines 125-142 Link Here
125
        IKeyPairCodec codec = new SRPKeyPairRawCodec();
118
        IKeyPairCodec codec = new SRPKeyPairRawCodec();
126
        return (SRPPublicKey) codec.decodePublicKey(k);
119
        return (SRPPublicKey) codec.decodePublicKey(k);
127
      }
120
      }
128
    else
121
    throw new IllegalArgumentException("magic");
129
      {
130
        throw new IllegalArgumentException("magic");
131
      }
132
  }
122
  }
133
123
134
  // Instance methods
135
  // -------------------------------------------------------------------------
136
137
  /**
124
  /**
138
   * <p>Returns the public exponent of the key as a {@link BigInteger}.</p>
125
   * Returns the public exponent of the key as a {@link BigInteger}.
139
   *
126
   * 
140
   * @return the public exponent of the key as a {@link BigInteger}.
127
   * @return the public exponent of the key as a {@link BigInteger}.
141
   */
128
   */
142
  public BigInteger getY()
129
  public BigInteger getY()
Lines 144-158 Link Here
144
    return Y;
131
    return Y;
145
  }
132
  }
146
133
147
  // Other instance methods --------------------------------------------------
148
149
  /**
134
  /**
150
   * <p>Returns the encoded form of this public key according to the designated
135
   * Returns the encoded form of this public key according to the designated
151
   * format.</p>
136
   * format.
152
   *
137
   * 
153
   * @param format the desired format identifier of the resulting encoding.
138
   * @param format the desired format identifier of the resulting encoding.
154
   * @return the byte sequence encoding this key according to the designated
139
   * @return the byte sequence encoding this key according to the designated
155
   * format.
140
   *         format.
156
   * @throws IllegalArgumentException if the format is not supported.
141
   * @throws IllegalArgumentException if the format is not supported.
157
   */
142
   */
158
  public byte[] getEncoded(int format)
143
  public byte[] getEncoded(int format)
Lines 170-193 Link Here
170
  }
155
  }
171
156
172
  /**
157
  /**
173
   * <p>Returns <code>true</code> if the designated object is an instance of
158
   * Returns <code>true</code> if the designated object is an instance of
174
   * <code>SRPPublicKey</code>and has the same SRP parameter values as this one.
159
   * <code>SRPPublicKey</code>and has the same SRP parameter values as this
175
   * </p>
160
   * one.
176
   *
161
   * 
177
   * @param obj the other non-null SRP key to compare to.
162
   * @param obj the other non-null SRP key to compare to.
178
   * @return <code>true</code> if the designated object is of the same type and
163
   * @return <code>true</code> if the designated object is of the same type
179
   * value as this one.
164
   *         and value as this one.
180
   */
165
   */
181
  public boolean equals(Object obj)
166
  public boolean equals(Object obj)
182
  {
167
  {
183
    if (obj == null)
168
    if (obj == null)
184
      {
169
      return false;
185
        return false;
170
    if (! (obj instanceof SRPPublicKey))
186
      }
171
      return false;
187
    if (!(obj instanceof SRPPublicKey))
188
      {
189
        return false;
190
      }
191
    SRPPublicKey that = (SRPPublicKey) obj;
172
    SRPPublicKey that = (SRPPublicKey) obj;
192
    return super.equals(that) && Y.equals(that.getY());
173
    return super.equals(that) && Y.equals(that.getY());
193
  }
174
  }

Return to bug 26067