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

Collapse All | Expand All

(-)AuthenticatedEntry.java (-65 / +24 lines)
Lines 53-78 Link Here
53
import java.util.HashMap;
53
import java.util.HashMap;
54
import java.util.Iterator;
54
import java.util.Iterator;
55
55
56
public final class AuthenticatedEntry extends MaskableEnvelopeEntry implements
56
public final class AuthenticatedEntry
57
    Registry
57
    extends MaskableEnvelopeEntry
58
    implements Registry
58
{
59
{
59
60
  // Constants and fields.
61
  // ------------------------------------------------------------------------
62
63
  public static final int TYPE = 2;
60
  public static final int TYPE = 2;
64
61
65
  // Constructor.
66
  // ------------------------------------------------------------------------
67
68
  public AuthenticatedEntry(String mac, int macLen, Properties properties)
62
  public AuthenticatedEntry(String mac, int macLen, Properties properties)
69
  {
63
  {
70
    super(TYPE, properties);
64
    super(TYPE, properties);
71
72
    if (macLen <= 0)
65
    if (macLen <= 0)
73
      {
66
      throw new IllegalArgumentException("invalid mac length");
74
        throw new IllegalArgumentException("invalid mac length");
75
      }
76
    this.properties.put("mac", mac);
67
    this.properties.put("mac", mac);
77
    this.properties.put("maclen", String.valueOf(macLen));
68
    this.properties.put("maclen", String.valueOf(macLen));
78
    setMasked(false);
69
    setMasked(false);
Lines 84-115 Link Here
84
    setMasked(true);
75
    setMasked(true);
85
  }
76
  }
86
77
87
  // Class methods.
88
  // ------------------------------------------------------------------------
89
90
  public static AuthenticatedEntry decode(DataInputStream in)
78
  public static AuthenticatedEntry decode(DataInputStream in)
91
      throws IOException
79
      throws IOException
92
  {
80
  {
93
    AuthenticatedEntry entry = new AuthenticatedEntry();
81
    AuthenticatedEntry entry = new AuthenticatedEntry();
94
    entry.properties.decode(in);
82
    entry.properties.decode(in);
95
    if (!entry.properties.containsKey("mac"))
83
    if (! entry.properties.containsKey("mac"))
96
      {
84
      throw new MalformedKeyringException("no mac specified");
97
        throw new MalformedKeyringException("no mac specified");
85
    if (! entry.properties.containsKey("maclen"))
98
      }
86
      throw new MalformedKeyringException("no mac length specified");
99
    if (!entry.properties.containsKey("maclen"))
100
      {
101
        throw new MalformedKeyringException("no mac length specified");
102
      }
103
    return entry;
87
    return entry;
104
  }
88
  }
105
89
106
  // Instance methods.
107
  // ------------------------------------------------------------------------
108
109
  /**
90
  /**
110
   * Computes the mac over this envelope's data. This method <b>must</b> be
91
   * Computes the mac over this envelope's data. This method <b>must</b> be
111
   * called before this entry in encoded.
92
   * called before this entry in encoded.
112
   *
93
   * 
113
   * @param key The key to authenticate with.
94
   * @param key The key to authenticate with.
114
   * @throws IOException If encoding fails.
95
   * @throws IOException If encoding fails.
115
   * @throws InvalidKeyException If the supplied key is bad.
96
   * @throws InvalidKeyException If the supplied key is bad.
Lines 117-127 Link Here
117
  public void authenticate(byte[] key) throws IOException, InvalidKeyException
98
  public void authenticate(byte[] key) throws IOException, InvalidKeyException
118
  {
99
  {
119
    if (isMasked())
100
    if (isMasked())
120
      {
101
      throw new IllegalStateException("entry is masked");
121
        throw new IllegalStateException("entry is masked");
122
      }
123
    IMac m = getMac(key);
102
    IMac m = getMac(key);
124
125
    ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
103
    ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
126
    MacOutputStream macout = new MacOutputStream(bout, m);
104
    MacOutputStream macout = new MacOutputStream(bout, m);
127
    DataOutputStream out2 = new DataOutputStream(macout);
105
    DataOutputStream out2 = new DataOutputStream(macout);
Lines 135-170 Link Here
135
  }
113
  }
136
114
137
  /**
115
  /**
138
   * Verifies this entry's payload. This method will unmask this entry,
116
   * Verifies this entry's payload. This method will unmask this entry, thus it
139
   * thus it must be called before accessing its contents.
117
   * must be called before accessing its contents.
140
   *
118
   * 
141
   * @param key The key to use to authenticate.
119
   * @param key The key to use to authenticate.
142
   * @throws InvalidKeyException If the given key is improper.
120
   * @throws InvalidKeyException If the given key is improper.
143
   */
121
   */
144
  public void verify(byte[] key) throws InvalidKeyException
122
  public void verify(byte[] key) throws InvalidKeyException
145
  {
123
  {
146
    if (!isMasked() || payload == null)
124
    if (! isMasked() || payload == null)
147
      {
125
      return;
148
        return;
149
      }
150
    IMac m = getMac(key);
126
    IMac m = getMac(key);
151
152
    m.update(payload, 0, payload.length - m.macSize());
127
    m.update(payload, 0, payload.length - m.macSize());
153
    byte[] macValue = new byte[m.macSize()];
128
    byte[] macValue = new byte[m.macSize()];
154
    System.arraycopy(payload, payload.length - macValue.length, macValue, 0,
129
    System.arraycopy(payload, payload.length - macValue.length, macValue, 0,
155
                     macValue.length);
130
                     macValue.length);
156
    if (!Arrays.equals(macValue, m.digest()))
131
    if (! Arrays.equals(macValue, m.digest()))
157
      {
132
      throw new IllegalArgumentException("MAC verification failed");
158
        throw new IllegalArgumentException("MAC verification failed");
159
      }
160
    try
133
    try
161
      {
134
      {
162
        DataInputStream in = new DataInputStream(
135
        int len = payload.length - m.macSize();
163
                                                 new ByteArrayInputStream(
136
        ByteArrayInputStream bais = new ByteArrayInputStream(payload, 0, len);
164
                                                                          payload,
137
        DataInputStream in = new DataInputStream(bais);
165
                                                                          0,
166
                                                                          payload.length
167
                                                                              - m.macSize()));
168
        decodeEnvelope(in);
138
        decodeEnvelope(in);
169
      }
139
      }
170
    catch (IOException ioe)
140
    catch (IOException ioe)
Lines 178-204 Link Here
178
  protected void encodePayload() throws IOException
148
  protected void encodePayload() throws IOException
179
  {
149
  {
180
    if (payload == null)
150
    if (payload == null)
181
      {
151
      throw new IllegalStateException("not authenticated");
182
        throw new IllegalStateException("not authenticated");
183
      }
184
  }
152
  }
185
153
186
  // Own methods.
187
  // ------------------------------------------------------------------------
188
189
  private IMac getMac(byte[] key) throws InvalidKeyException
154
  private IMac getMac(byte[] key) throws InvalidKeyException
190
  {
155
  {
191
    IMac mac = MacFactory.getInstance(properties.get("mac"));
156
    IMac mac = MacFactory.getInstance(properties.get("mac"));
192
    if (mac == null)
157
    if (mac == null)
193
      {
158
      throw new IllegalArgumentException("no such mac: " + properties.get("mac"));
194
        throw new IllegalArgumentException("no such mac: "
195
                                           + properties.get("mac"));
196
      }
197
    int maclen = 0;
159
    int maclen = 0;
198
    if (!properties.containsKey("maclen"))
160
    if (! properties.containsKey("maclen"))
199
      {
161
      throw new IllegalArgumentException("no MAC length");
200
        throw new IllegalArgumentException("no MAC length");
201
      }
202
    try
162
    try
203
      {
163
      {
204
        maclen = Integer.parseInt(properties.get("maclen"));
164
        maclen = Integer.parseInt(properties.get("maclen"));
Lines 207-213 Link Here
207
      {
167
      {
208
        throw new IllegalArgumentException("bad MAC length");
168
        throw new IllegalArgumentException("bad MAC length");
209
      }
169
      }
210
211
    HashMap macAttr = new HashMap();
170
    HashMap macAttr = new HashMap();
212
    macAttr.put(IMac.MAC_KEY_MATERIAL, key);
171
    macAttr.put(IMac.MAC_KEY_MATERIAL, key);
213
    macAttr.put(IMac.TRUNCATED_SIZE, Integer.valueOf(maclen));
172
    macAttr.put(IMac.TRUNCATED_SIZE, Integer.valueOf(maclen));
(-)BaseKeyring.java (-60 / +20 lines)
Lines 38-123 Link Here
38
38
39
package gnu.javax.crypto.keyring;
39
package gnu.javax.crypto.keyring;
40
40
41
import java.io.InputStream;
41
import gnu.java.security.Registry;
42
42
import java.io.IOException;
43
import java.io.IOException;
44
import java.io.InputStream;
43
import java.io.OutputStream;
45
import java.io.OutputStream;
44
45
import java.util.Enumeration;
46
import java.util.Enumeration;
46
import java.util.List;
47
import java.util.List;
47
import java.util.Map;
48
import java.util.Map;
48
import java.util.StringTokenizer;
49
import java.util.StringTokenizer;
49
50
50
import gnu.java.security.Registry;
51
public abstract class BaseKeyring
51
52
    implements IKeyring
52
public abstract class BaseKeyring implements IKeyring
53
{
53
{
54
54
  /** The top-level keyring data. */
55
  // Fields.
56
  // ------------------------------------------------------------------------
57
58
  /**
59
   * The top-level keyring data.
60
   */
61
  protected PasswordAuthenticatedEntry keyring;
55
  protected PasswordAuthenticatedEntry keyring;
62
63
  protected CompressedEntry keyring2;
56
  protected CompressedEntry keyring2;
64
57
65
  // Constructors.
66
  // ------------------------------------------------------------------------
67
68
  public BaseKeyring()
58
  public BaseKeyring()
69
  {
59
  {
70
  }
60
  }
71
61
72
  // Instance methods.
73
  // ------------------------------------------------------------------------
74
75
  public void load(Map attributes) throws IOException
62
  public void load(Map attributes) throws IOException
76
  {
63
  {
77
    InputStream in = (InputStream) attributes.get(KEYRING_DATA_IN);
64
    InputStream in = (InputStream) attributes.get(KEYRING_DATA_IN);
78
    if (in == null)
65
    if (in == null)
79
      {
66
      throw new IllegalArgumentException("no input stream");
80
        throw new IllegalArgumentException("no input stream");
81
      }
82
    char[] password = (char[]) attributes.get(KEYRING_PASSWORD);
67
    char[] password = (char[]) attributes.get(KEYRING_PASSWORD);
83
    if (password == null)
68
    if (password == null)
84
      {
69
      password = new char[0];
85
        password = new char[0];
86
      }
87
70
88
    if (in.read() != Registry.GKR_MAGIC[0]
71
    if (in.read() != Registry.GKR_MAGIC[0]
89
        || in.read() != Registry.GKR_MAGIC[1]
72
        || in.read() != Registry.GKR_MAGIC[1]
90
        || in.read() != Registry.GKR_MAGIC[2]
73
        || in.read() != Registry.GKR_MAGIC[2]
91
        || in.read() != Registry.GKR_MAGIC[3])
74
        || in.read() != Registry.GKR_MAGIC[3])
92
      {
75
      throw new MalformedKeyringException("magic");
93
        throw new MalformedKeyringException("magic");
94
      }
95
76
96
    load(in, password);
77
    load(in, password);
97
98
    List l = keyring.getEntries();
78
    List l = keyring.getEntries();
99
    if (l.size() == 1 && (l.get(0) instanceof CompressedEntry))
79
    if (l.size() == 1 && (l.get(0) instanceof CompressedEntry))
100
      {
80
      keyring2 = (CompressedEntry) l.get(0);
101
        keyring2 = (CompressedEntry) l.get(0);
102
      }
103
  }
81
  }
104
82
105
  public void store(Map attributes) throws IOException
83
  public void store(Map attributes) throws IOException
106
  {
84
  {
107
    OutputStream out = (OutputStream) attributes.get(KEYRING_DATA_OUT);
85
    OutputStream out = (OutputStream) attributes.get(KEYRING_DATA_OUT);
108
    if (out == null)
86
    if (out == null)
109
      {
87
      throw new IllegalArgumentException("no output stream");
110
        throw new IllegalArgumentException("no output stream");
111
      }
112
    char[] password = (char[]) attributes.get(KEYRING_PASSWORD);
88
    char[] password = (char[]) attributes.get(KEYRING_PASSWORD);
113
    if (password == null)
89
    if (password == null)
114
      {
90
      password = new char[0];
115
        password = new char[0];
91
    if (keyring == null)
116
      }
92
      throw new IllegalStateException("empty keyring");
117
    if (keyring == null)
118
      {
119
        throw new IllegalStateException("empty keyring");
120
      }
121
93
122
    out.write(Registry.GKR_MAGIC);
94
    out.write(Registry.GKR_MAGIC);
123
    store(out, password);
95
    store(out, password);
Lines 131-175 Link Here
131
  public int size()
103
  public int size()
132
  {
104
  {
133
    if (keyring == null)
105
    if (keyring == null)
134
      {
106
      throw new IllegalStateException("keyring not loaded");
135
        throw new IllegalStateException ("keyring not loaded");
136
      }
137
    return ((StringTokenizer) aliases()).countTokens();
107
    return ((StringTokenizer) aliases()).countTokens();
138
  }
108
  }
139
109
140
  public Enumeration aliases()
110
  public Enumeration aliases()
141
  {
111
  {
142
    if (keyring == null)
112
    if (keyring == null)
143
      {
113
      throw new IllegalStateException("keyring not loaded");
144
        throw new IllegalStateException ("keyring not loaded");
145
      }
146
    return new StringTokenizer(keyring.getAliasList(), ";");
114
    return new StringTokenizer(keyring.getAliasList(), ";");
147
  }
115
  }
148
116
149
  public boolean containsAlias(String alias)
117
  public boolean containsAlias(String alias)
150
  {
118
  {
151
    if (keyring == null)
119
    if (keyring == null)
152
      {
120
      throw new IllegalStateException("keyring not loaded");
153
        throw new IllegalStateException("keyring not loaded");
154
      }
155
    return keyring.containsAlias(alias);
121
    return keyring.containsAlias(alias);
156
  }
122
  }
157
123
158
  public List get(String alias)
124
  public List get(String alias)
159
  {
125
  {
160
    if (keyring == null)
126
    if (keyring == null)
161
      {
127
      throw new IllegalStateException("keyring not loaded");
162
        throw new IllegalStateException("keyring not loaded");
163
      }
164
    return keyring.get(alias);
128
    return keyring.get(alias);
165
  }
129
  }
166
130
167
  public void add(Entry entry)
131
  public void add(Entry entry)
168
  {
132
  {
169
    if (keyring == null)
133
    if (keyring == null)
170
      {
134
      throw new IllegalStateException("keyring not loaded");
171
        throw new IllegalStateException("keyring not loaded");
172
      }
173
    if (keyring2 != null)
135
    if (keyring2 != null)
174
      keyring2.add(entry);
136
      keyring2.add(entry);
175
    else
137
    else
Lines 179-187 Link Here
179
  public void remove(String alias)
141
  public void remove(String alias)
180
  {
142
  {
181
    if (keyring == null)
143
    if (keyring == null)
182
      {
144
      throw new IllegalStateException("keyring not loaded");
183
        throw new IllegalStateException("keyring not loaded");
184
      }
185
    keyring.remove(alias);
145
    keyring.remove(alias);
186
  }
146
  }
187
147
(-)BinaryDataEntry.java (-28 / +11 lines)
Lines 40-68 Link Here
40
40
41
import java.io.DataInputStream;
41
import java.io.DataInputStream;
42
import java.io.IOException;
42
import java.io.IOException;
43
44
import java.util.Date;
43
import java.util.Date;
45
44
46
/**
45
/**
47
 * A binary data entry is a primitive entry that simply contains some amount
46
 * A binary data entry is a primitive entry that simply contains some amount of
48
 * of arbitrary binary data and an optional content type.
47
 * arbitrary binary data and an optional content type.
49
 */
48
 */
50
public class BinaryDataEntry extends PrimitiveEntry
49
public class BinaryDataEntry
50
    extends PrimitiveEntry
51
{
51
{
52
53
  // Fields.
54
  // ------------------------------------------------------------------------
55
56
  public static final int TYPE = 9;
52
  public static final int TYPE = 9;
57
53
58
  // Constructors.
59
  // ------------------------------------------------------------------------
60
61
  /**
54
  /**
62
   * Creates a new binary data entry.
55
   * Creates a new binary data entry.
63
   *
56
   * 
64
   * @param contentType The content type of this entry. This parameter can
57
   * @param contentType The content type of this entry. This parameter can be
65
   *   be <code>null</code> if no content type is needed.
58
   *          <code>null</code> if no content type is needed.
66
   * @param data The data.
59
   * @param data The data.
67
   * @param creationDate The creation date.
60
   * @param creationDate The creation date.
68
   * @param properties This entry's properties.
61
   * @param properties This entry's properties.
Lines 72-85 Link Here
72
  {
65
  {
73
    super(TYPE, creationDate, properties);
66
    super(TYPE, creationDate, properties);
74
    if (data == null)
67
    if (data == null)
75
      {
68
      throw new IllegalArgumentException("no data");
76
        throw new IllegalArgumentException("no data");
77
      }
78
    payload = (byte[]) data.clone();
69
    payload = (byte[]) data.clone();
79
    if (contentType != null)
70
    if (contentType != null)
80
      {
71
      this.properties.put("content-type", contentType);
81
        this.properties.put("content-type", contentType);
82
      }
83
  }
72
  }
84
73
85
  private BinaryDataEntry()
74
  private BinaryDataEntry()
Lines 87-95 Link Here
87
    super(TYPE);
76
    super(TYPE);
88
  }
77
  }
89
78
90
  // Class methods.
91
  // ------------------------------------------------------------------------
92
93
  public static BinaryDataEntry decode(DataInputStream in) throws IOException
79
  public static BinaryDataEntry decode(DataInputStream in) throws IOException
94
  {
80
  {
95
    BinaryDataEntry entry = new BinaryDataEntry();
81
    BinaryDataEntry entry = new BinaryDataEntry();
Lines 97-109 Link Here
97
    return entry;
83
    return entry;
98
  }
84
  }
99
85
100
  // Instance methods.
101
  // ------------------------------------------------------------------------
102
103
  /**
86
  /**
104
   * Returns the content type of this entry, or <code>null</code> if this
87
   * Returns the content type of this entry, or <code>null</code> if this
105
   * property is not set.
88
   * property is not set.
106
   *
89
   * 
107
   * @return The content type.
90
   * @return The content type.
108
   */
91
   */
109
  public String getContentType()
92
  public String getContentType()
Lines 113-119 Link Here
113
96
114
  /**
97
  /**
115
   * Returns this object's data field.
98
   * Returns this object's data field.
116
   *
99
   * 
117
   * @return The data.
100
   * @return The data.
118
   */
101
   */
119
  public byte[] getData()
102
  public byte[] getData()
(-)CertPathEntry.java (-23 / +5 lines)
Lines 50-76 Link Here
50
/**
50
/**
51
 * A primitive entry that contains a path of X.509 certificates.
51
 * A primitive entry that contains a path of X.509 certificates.
52
 */
52
 */
53
public final class CertPathEntry extends PrimitiveEntry
53
public final class CertPathEntry
54
    extends PrimitiveEntry
54
{
55
{
55
56
  // Constants and fields.
57
  // ------------------------------------------------------------------------
58
59
  public static final int TYPE = 8;
56
  public static final int TYPE = 8;
60
61
  private Certificate[] path;
57
  private Certificate[] path;
62
58
63
  // Constructor.
64
  // ------------------------------------------------------------------------
65
66
  public CertPathEntry(Certificate[] path, Date creationDate,
59
  public CertPathEntry(Certificate[] path, Date creationDate,
67
                       Properties properties)
60
                       Properties properties)
68
  {
61
  {
69
    super(TYPE, creationDate, properties);
62
    super(TYPE, creationDate, properties);
70
    if (path == null || path.length == 0)
63
    if (path == null || path.length == 0)
71
      {
64
      throw new IllegalArgumentException("no certificate path");
72
        throw new IllegalArgumentException("no certificate path");
73
      }
74
    this.path = (Certificate[]) path.clone();
65
    this.path = (Certificate[]) path.clone();
75
  }
66
  }
76
67
Lines 79-87 Link Here
79
    super(TYPE);
70
    super(TYPE);
80
  }
71
  }
81
72
82
  // Class method.
83
  // ------------------------------------------------------------------------
84
85
  public static CertPathEntry decode(DataInputStream in) throws IOException
73
  public static CertPathEntry decode(DataInputStream in) throws IOException
86
  {
74
  {
87
    CertPathEntry entry = new CertPathEntry();
75
    CertPathEntry entry = new CertPathEntry();
Lines 92-99 Link Here
92
    try
80
    try
93
      {
81
      {
94
        CertificateFactory fact = CertificateFactory.getInstance("X.509");
82
        CertificateFactory fact = CertificateFactory.getInstance("X.509");
95
        entry.path = (Certificate[]) fact.generateCertificates(in2).toArray(
83
        entry.path = (Certificate[]) fact.generateCertificates(in2).toArray(new Certificate[0]);
96
                                                                            new Certificate[0]);
97
      }
84
      }
98
    catch (CertificateException ce)
85
    catch (CertificateException ce)
99
      {
86
      {
Lines 102-110 Link Here
102
    return entry;
89
    return entry;
103
  }
90
  }
104
91
105
  // Instance methods.
106
  // ------------------------------------------------------------------------
107
108
  public Certificate[] getCertPath()
92
  public Certificate[] getCertPath()
109
  {
93
  {
110
    return path;
94
    return path;
Lines 117-125 Link Here
117
    try
101
    try
118
      {
102
      {
119
        for (int i = 0; i < path.length; i++)
103
        for (int i = 0; i < path.length; i++)
120
          {
104
          bout.write(path[i].getEncoded());
121
            bout.write(path[i].getEncoded());
122
          }
123
      }
105
      }
124
    catch (CertificateEncodingException cee)
106
    catch (CertificateEncodingException cee)
125
      {
107
      {
(-)CertificateEntry.java (-30 / +10 lines)
Lines 47-86 Link Here
47
import java.util.Date;
47
import java.util.Date;
48
48
49
/**
49
/**
50
 * <p>An immutable class representing a trusted certificate entry.</p>
50
 * An immutable class representing a trusted certificate entry.
51
 */
51
 */
52
public final class CertificateEntry extends PrimitiveEntry
52
public final class CertificateEntry
53
    extends PrimitiveEntry
53
{
54
{
54
55
  // Constants and variables
56
  // -------------------------------------------------------------------------
57
58
  public static final int TYPE = 5;
55
  public static final int TYPE = 5;
59
60
  /** The certificate. */
56
  /** The certificate. */
61
  private Certificate certificate;
57
  private Certificate certificate;
62
58
63
  // Constructor(s)
64
  // -------------------------------------------------------------------------
65
66
  /**
59
  /**
67
   * Creates a new certificate entry.
60
   * Creates a new certificate entry.
68
   *
61
   * 
69
   * @param certificate The certificate.
62
   * @param certificate The certificate.
70
   * @param creationDate The creation date.
63
   * @param creationDate The creation date.
71
   * @param properties The alias.
64
   * @param properties The alias.
72
   * @throws IllegalArgumentException If any argument is null, or if the alias
65
   * @throws IllegalArgumentException If any argument is null, or if the alias
73
   * is empty.
66
   *           is empty.
74
   */
67
   */
75
  public CertificateEntry(Certificate certificate, Date creationDate,
68
  public CertificateEntry(Certificate certificate, Date creationDate,
76
                          Properties properties)
69
                          Properties properties)
77
  {
70
  {
78
    super(TYPE, creationDate, properties);
71
    super(TYPE, creationDate, properties);
79
80
    if (certificate == null)
72
    if (certificate == null)
81
      {
73
      throw new IllegalArgumentException("no certificate");
82
        throw new IllegalArgumentException("no certificate");
83
      }
84
    this.certificate = certificate;
74
    this.certificate = certificate;
85
    this.properties.put("type", certificate.getType());
75
    this.properties.put("type", certificate.getType());
86
  }
76
  }
Lines 90-98 Link Here
90
    super(TYPE);
80
    super(TYPE);
91
  }
81
  }
92
82
93
  // Class methods
94
  // -------------------------------------------------------------------------
95
96
  public static CertificateEntry decode(DataInputStream in) throws IOException
83
  public static CertificateEntry decode(DataInputStream in) throws IOException
97
  {
84
  {
98
    CertificateEntry entry = new CertificateEntry();
85
    CertificateEntry entry = new CertificateEntry();
Lines 100-108 Link Here
100
    entry.makeCreationDate();
87
    entry.makeCreationDate();
101
    String type = entry.properties.get("type");
88
    String type = entry.properties.get("type");
102
    if (type == null)
89
    if (type == null)
103
      {
90
      throw new MalformedKeyringException("no certificate type");
104
        throw new MalformedKeyringException("no certificate type");
105
      }
106
    int len = in.readInt();
91
    int len = in.readInt();
107
    MeteredInputStream in2 = new MeteredInputStream(in, len);
92
    MeteredInputStream in2 = new MeteredInputStream(in, len);
108
    try
93
    try
Lines 114-132 Link Here
114
      {
99
      {
115
        throw new MalformedKeyringException(ce.toString());
100
        throw new MalformedKeyringException(ce.toString());
116
      }
101
      }
117
    if (!in2.limitReached())
102
    if (! in2.limitReached())
118
      {
103
      throw new MalformedKeyringException("extra data at end of payload");
119
        throw new MalformedKeyringException("extra data at end of payload");
120
      }
121
    return entry;
104
    return entry;
122
  }
105
  }
123
106
124
  // Instance methods
125
  // -------------------------------------------------------------------------
126
127
  /**
107
  /**
128
   * Returns this entry's certificate.
108
   * Returns this entry's certificate.
129
   *
109
   * 
130
   * @return The certificate.
110
   * @return The certificate.
131
   */
111
   */
132
  public Certificate getCertificate()
112
  public Certificate getCertificate()
(-)CompressedEntry.java (-27 / +7 lines)
Lines 42-63 Link Here
42
import java.io.DataInputStream;
42
import java.io.DataInputStream;
43
import java.io.DataOutputStream;
43
import java.io.DataOutputStream;
44
import java.io.IOException;
44
import java.io.IOException;
45
46
import java.util.Iterator;
45
import java.util.Iterator;
47
import java.util.zip.DeflaterOutputStream;
46
import java.util.zip.DeflaterOutputStream;
48
import java.util.zip.InflaterInputStream;
47
import java.util.zip.InflaterInputStream;
49
48
50
public class CompressedEntry extends EnvelopeEntry
49
public class CompressedEntry
50
    extends EnvelopeEntry
51
{
51
{
52
53
  // Constants and fields.
54
  // ------------------------------------------------------------------------
55
56
  public static final int TYPE = 4;
52
  public static final int TYPE = 4;
57
53
58
  // Constructor.
59
  // ------------------------------------------------------------------------
60
61
  public CompressedEntry(Properties properties)
54
  public CompressedEntry(Properties properties)
62
  {
55
  {
63
    super(TYPE, properties);
56
    super(TYPE, properties);
Lines 69-92 Link Here
69
    this(new Properties());
62
    this(new Properties());
70
  }
63
  }
71
64
72
  // Class methods.
73
  // ------------------------------------------------------------------------
74
75
  public static CompressedEntry decode(DataInputStream in) throws IOException
65
  public static CompressedEntry decode(DataInputStream in) throws IOException
76
  {
66
  {
77
    CompressedEntry entry = new CompressedEntry();
67
    CompressedEntry entry = new CompressedEntry();
78
    entry.properties.decode(in);
68
    entry.properties.decode(in);
79
    String alg = entry.properties.get("algorithm");
69
    String alg = entry.properties.get("algorithm");
80
    if (alg == null)
70
    if (alg == null)
81
      {
71
      throw new MalformedKeyringException("no compression algorithm");
82
        throw new MalformedKeyringException("no compression algorithm");
72
    if (! alg.equalsIgnoreCase("DEFLATE"))
83
      }
73
      throw new MalformedKeyringException("unsupported compression algorithm: "
84
    if (!alg.equalsIgnoreCase("DEFLATE"))
74
                                          + alg);
85
      {
86
        throw new MalformedKeyringException(
87
                                            "unsupported compression algorithm: "
88
                                                + alg);
89
      }
90
    int len = in.readInt();
75
    int len = in.readInt();
91
    MeteredInputStream min = new MeteredInputStream(in, len);
76
    MeteredInputStream min = new MeteredInputStream(in, len);
92
    InflaterInputStream infin = new InflaterInputStream(min);
77
    InflaterInputStream infin = new InflaterInputStream(min);
Lines 95-112 Link Here
95
    return entry;
80
    return entry;
96
  }
81
  }
97
82
98
  // Instance methods.
99
  // ------------------------------------------------------------------------
100
101
  protected void encodePayload() throws IOException
83
  protected void encodePayload() throws IOException
102
  {
84
  {
103
    ByteArrayOutputStream buf = new ByteArrayOutputStream(1024);
85
    ByteArrayOutputStream buf = new ByteArrayOutputStream(1024);
104
    DeflaterOutputStream dout = new DeflaterOutputStream(buf);
86
    DeflaterOutputStream dout = new DeflaterOutputStream(buf);
105
    DataOutputStream out2 = new DataOutputStream(dout);
87
    DataOutputStream out2 = new DataOutputStream(dout);
106
    for (Iterator it = entries.iterator(); it.hasNext();)
88
    for (Iterator it = entries.iterator(); it.hasNext();)
107
      {
89
      ((Entry) it.next()).encode(out2);
108
        ((Entry) it.next()).encode(out2);
109
      }
110
    dout.finish();
90
    dout.finish();
111
    payload = buf.toByteArray();
91
    payload = buf.toByteArray();
112
  }
92
  }
(-)EncryptedEntry.java (-51 / +13 lines)
Lines 58-80 Link Here
58
58
59
public class EncryptedEntry extends MaskableEnvelopeEntry implements Registry
59
public class EncryptedEntry extends MaskableEnvelopeEntry implements Registry
60
{
60
{
61
62
  // Constants and fields.
63
  // ------------------------------------------------------------------------
64
65
  public static final int TYPE = 0;
61
  public static final int TYPE = 0;
66
62
67
  // Constructor.
68
  // ------------------------------------------------------------------------
69
70
  public EncryptedEntry(String cipher, String mode, Properties properties)
63
  public EncryptedEntry(String cipher, String mode, Properties properties)
71
  {
64
  {
72
    super(TYPE, properties);
65
    super(TYPE, properties);
73
    if (cipher == null || mode == null)
66
    if (cipher == null || mode == null)
74
      {
67
      throw new IllegalArgumentException("neither cipher nor mode can be null");
75
        throw new IllegalArgumentException(
76
                                           "neither cipher nor mode can be null");
77
      }
78
    properties.put("cipher", cipher);
68
    properties.put("cipher", cipher);
79
    properties.put("mode", mode);
69
    properties.put("mode", mode);
80
    setMasked(false);
70
    setMasked(false);
Lines 86-119 Link Here
86
    setMasked(true);
76
    setMasked(true);
87
  }
77
  }
88
78
89
  // Class methods.
90
  // ------------------------------------------------------------------------
91
92
  public static EncryptedEntry decode(DataInputStream in) throws IOException
79
  public static EncryptedEntry decode(DataInputStream in) throws IOException
93
  {
80
  {
94
    EncryptedEntry entry = new EncryptedEntry();
81
    EncryptedEntry entry = new EncryptedEntry();
95
    entry.defaultDecode(in);
82
    entry.defaultDecode(in);
96
    if (!entry.properties.containsKey("cipher"))
83
    if (! entry.properties.containsKey("cipher"))
97
      {
84
      throw new MalformedKeyringException("no cipher");
98
        throw new MalformedKeyringException("no cipher");
85
    if (! entry.properties.containsKey("cipher"))
99
      }
86
      throw new MalformedKeyringException("no cipher");
100
    if (!entry.properties.containsKey("cipher"))
101
      {
102
        throw new MalformedKeyringException("no cipher");
103
      }
104
    return entry;
87
    return entry;
105
  }
88
  }
106
89
107
  // Instance methods.
108
  // ------------------------------------------------------------------------
109
110
  public void decrypt(byte[] key, byte[] iv) throws IllegalArgumentException,
90
  public void decrypt(byte[] key, byte[] iv) throws IllegalArgumentException,
111
      WrongPaddingException
91
      WrongPaddingException
112
  {
92
  {
113
    if (!isMasked() || payload == null)
93
    if (! isMasked() || payload == null)
114
      {
94
      return;
115
        return;
116
      }
117
    IMode mode = getMode(key, iv, IMode.DECRYPTION);
95
    IMode mode = getMode(key, iv, IMode.DECRYPTION);
118
    IPad padding = null;
96
    IPad padding = null;
119
    padding = PadFactory.getInstance("PKCS7");
97
    padding = PadFactory.getInstance("PKCS7");
Lines 126-137 Link Here
126
        count += mode.currentBlockSize();
104
        count += mode.currentBlockSize();
127
      }
105
      }
128
    int padlen = padding.unpad(buf, 0, buf.length);
106
    int padlen = padding.unpad(buf, 0, buf.length);
129
    DataInputStream in = new DataInputStream(
107
    int len = buf.length - padlen;
130
                                             new ByteArrayInputStream(
108
    DataInputStream in = new DataInputStream(new ByteArrayInputStream(buf, 0, len));
131
                                                                      buf,
132
                                                                      0,
133
                                                                      buf.length
134
                                                                          - padlen));
135
    try
109
    try
136
      {
110
      {
137
        decodeEnvelope(in);
111
        decodeEnvelope(in);
Lines 175-196 Link Here
175
  public void encodePayload() throws IOException
149
  public void encodePayload() throws IOException
176
  {
150
  {
177
    if (payload == null)
151
    if (payload == null)
178
      {
152
      throw new IOException("not encrypted");
179
        throw new IOException("not encrypted");
180
      }
181
  }
153
  }
182
154
183
  // Own methods.
184
  // ------------------------------------------------------------------------
185
186
  private IMode getMode(byte[] key, byte[] iv, int state)
155
  private IMode getMode(byte[] key, byte[] iv, int state)
187
  {
156
  {
188
    IBlockCipher cipher = CipherFactory.getInstance(properties.get("cipher"));
157
    IBlockCipher cipher = CipherFactory.getInstance(properties.get("cipher"));
189
    if (cipher == null)
158
    if (cipher == null)
190
      {
159
      throw new IllegalArgumentException("no such cipher: " + properties.get("cipher"));
191
        throw new IllegalArgumentException("no such cipher: "
192
                                           + properties.get("cipher"));
193
      }
194
    int blockSize = cipher.defaultBlockSize();
160
    int blockSize = cipher.defaultBlockSize();
195
    if (properties.containsKey("block-size"))
161
    if (properties.containsKey("block-size"))
196
      {
162
      {
Lines 204-216 Link Here
204
                                               + nfe.getMessage());
170
                                               + nfe.getMessage());
205
          }
171
          }
206
      }
172
      }
207
    IMode mode = ModeFactory.getInstance(properties.get("mode"), cipher,
173
    IMode mode = ModeFactory.getInstance(properties.get("mode"), cipher, blockSize);
208
                                         blockSize);
209
    if (mode == null)
174
    if (mode == null)
210
      {
175
      throw new IllegalArgumentException("no such mode: " + properties.get("mode"));
211
        throw new IllegalArgumentException("no such mode: "
212
                                           + properties.get("mode"));
213
      }
214
176
215
    HashMap modeAttr = new HashMap();
177
    HashMap modeAttr = new HashMap();
216
    modeAttr.put(IMode.KEY_MATERIAL, key);
178
    modeAttr.put(IMode.KEY_MATERIAL, key);
(-)Entry.java (-48 / +27 lines)
Lines 50-95 Link Here
50
 */
50
 */
51
public abstract class Entry
51
public abstract class Entry
52
{
52
{
53
  // Fields.
54
  // ------------------------------------------------------------------------
55
56
  private static final Logger log = Logger.getLogger(Entry.class.getName());
53
  private static final Logger log = Logger.getLogger(Entry.class.getName());
57
  private static final String[] TYPES = new String[]
54
  private static final String[] TYPES = new String[] {
58
  {
55
      "Encrypted",
59
    "Encrypted", "PasswordEncrypted", "Authenticated", "PasswordAuthenticated",
56
      "PasswordEncrypted",
60
    "Compressed", "Certificate", "PublicKey", "PrivateKey", "CertPath",
57
      "Authenticated",
61
    "BinaryData"
58
      "PasswordAuthenticated",
62
  };
59
      "Compressed",
60
      "Certificate",
61
      "PublicKey",
62
      "PrivateKey",
63
      "CertPath",
64
      "BinaryData" };
63
  /** This entry's type identifier. */
65
  /** This entry's type identifier. */
64
  protected int type;
66
  protected int type;
65
66
  /** This entry's property set. */
67
  /** This entry's property set. */
67
  protected Properties properties;
68
  protected Properties properties;
68
69
  /** This entry's payload. */
69
  /** This entry's payload. */
70
  protected byte[] payload;
70
  protected byte[] payload;
71
71
72
  // Constructor.
73
  // ------------------------------------------------------------------------
74
75
  /**
72
  /**
76
   * Creates a new Entry.
73
   * Creates a new Entry.
77
   *
74
   * 
78
   * @param type This entry's type.
75
   * @param type This entry's type.
79
   * @param properties This entry's properties.
76
   * @param properties This entry's properties.
80
   * @throws IllegalArgumentException If the properties argument is null,
77
   * @throws IllegalArgumentException If the properties argument is null, or if
81
   *   or if the type is out of range.
78
   *           the type is out of range.
82
   */
79
   */
83
  protected Entry(int type, Properties properties)
80
  protected Entry(int type, Properties properties)
84
  {
81
  {
85
    if (type < 0 || type > 255)
82
    if (type < 0 || type > 255)
86
      {
83
      throw new IllegalArgumentException("invalid packet type");
87
        throw new IllegalArgumentException("invalid packet type");
88
      }
89
    if (properties == null)
84
    if (properties == null)
90
      {
85
      throw new IllegalArgumentException("no properties");
91
        throw new IllegalArgumentException("no properties");
92
      }
93
    this.type = type;
86
    this.type = type;
94
    this.properties = (Properties) properties.clone();
87
    this.properties = (Properties) properties.clone();
95
  }
88
  }
Lines 100-119 Link Here
100
  protected Entry(final int type)
93
  protected Entry(final int type)
101
  {
94
  {
102
    if (type < 0 || type > 255)
95
    if (type < 0 || type > 255)
103
      {
96
      throw new IllegalArgumentException("invalid packet type");
104
        throw new IllegalArgumentException("invalid packet type");
105
      }
106
    this.type = type;
97
    this.type = type;
107
    properties = new Properties();
98
    properties = new Properties();
108
  }
99
  }
109
100
110
  // Instance methods.
111
  // ------------------------------------------------------------------------
112
113
  /**
101
  /**
114
   * Returns this entry's properties object. The properties are cloned before
102
   * Returns this entry's properties object. The properties are cloned before
115
   * being returned.
103
   * being returned.
116
   *
104
   * 
117
   * @return The properties.
105
   * @return The properties.
118
   */
106
   */
119
  public Properties getProperties()
107
  public Properties getProperties()
Lines 132-153 Link Here
132
  }
120
  }
133
121
134
  /**
122
  /**
135
   * This method is called when this entry needs to be written to an
123
   * This method is called when this entry needs to be written to an output
136
   * output stream.
124
   * stream.
137
   *
125
   * 
138
   * @param out The stream to write to.
126
   * @param out The stream to write to.
139
   * @throws IOException If an I/O exception occurs.
127
   * @throws IOException If an I/O exception occurs.
140
   */
128
   */
141
  public void encode(DataOutputStream out) throws IOException
129
  public void encode(DataOutputStream out) throws IOException
142
  {
130
  {
143
    if (payload == null)
131
    if (payload == null)
144
      {
132
      encodePayload();
145
        encodePayload();
146
      }
147
    if (out == null)
133
    if (out == null)
148
      {
134
      return;
149
        return;
150
      }
151
    out.write(type);
135
    out.write(type);
152
    properties.encode(out);
136
    properties.encode(out);
153
    out.writeInt(payload.length);
137
    out.writeInt(payload.length);
Lines 156-168 Link Here
156
140
157
  public String toString()
141
  public String toString()
158
  {
142
  {
159
    
160
    return new StringBuilder("Entry{")
143
    return new StringBuilder("Entry{")
161
        .append("type=").append(TYPES[type])
144
        .append("type=").append(TYPES[type])
162
        .append(", properties=").append(properties)
145
        .append(", properties=").append(properties)
163
        .append(", payload=")
146
        .append(", payload=")
164
        .append(payload == null? "-" : "byte[" + payload.length + "]")
147
        .append(payload == null ? "-" : "byte[" + payload.length + "]")
165
        .append("}").toString();
148
        .append( "}")
149
        .toString();
166
  }
150
  }
167
151
168
  /**
152
  /**
Lines 178-195 Link Here
178
    properties.decode(in);
162
    properties.decode(in);
179
    int len = in.readInt();
163
    int len = in.readInt();
180
    if (len < 0)
164
    if (len < 0)
181
      {
165
      throw new IOException("corrupt length");
182
        throw new IOException("corrupt length");
183
      }
184
    if (Configuration.DEBUG)
166
    if (Configuration.DEBUG)
185
      log.fine("About to instantiate new payload byte array for " + this);
167
      log.fine("About to instantiate new payload byte array for " + this);
186
    payload = new byte[len];
168
    payload = new byte[len];
187
    in.readFully(payload);
169
    in.readFully(payload);
188
  }
170
  }
189
171
190
  // Abstract methods.
191
  // ------------------------------------------------------------------------
192
193
  /**
172
  /**
194
   * This method is called of subclasses when the payload data needs to be
173
   * This method is called of subclasses when the payload data needs to be
195
   * created.
174
   * created.
(-)EnvelopeEntry.java (-71 / +41 lines)
Lines 52-83 Link Here
52
import java.util.logging.Logger;
52
import java.util.logging.Logger;
53
53
54
/**
54
/**
55
 * An envelope entry is a generic container for some number of primitive
55
 * An envelope entry is a generic container for some number of primitive and
56
 * and other envelope entries.
56
 * other envelope entries.
57
 */
57
 */
58
public abstract class EnvelopeEntry extends Entry
58
public abstract class EnvelopeEntry
59
    extends Entry
59
{
60
{
60
  // Fields.
61
  // ------------------------------------------------------------------------
62
63
  private static final Logger log = Logger.getLogger(EnvelopeEntry.class.getName());
61
  private static final Logger log = Logger.getLogger(EnvelopeEntry.class.getName());
64
  /** The envelope that contains this one (if any). */
62
  /** The envelope that contains this one (if any). */
65
  protected EnvelopeEntry containingEnvelope;
63
  protected EnvelopeEntry containingEnvelope;
66
67
  /** The contained entries. */
64
  /** The contained entries. */
68
  protected List entries;
65
  protected List entries;
69
66
70
  // Constructor.
71
  // ------------------------------------------------------------------------
72
73
  public EnvelopeEntry(int type, Properties properties)
67
  public EnvelopeEntry(int type, Properties properties)
74
  {
68
  {
75
    super(type, properties);
69
    super(type, properties);
76
    entries = new LinkedList();
70
    entries = new LinkedList();
77
    if (this.properties.get("alias-list") != null)
71
    if (this.properties.get("alias-list") != null)
78
      {
72
      this.properties.remove("alias-list");
79
        this.properties.remove("alias-list");
80
      }
81
  }
73
  }
82
74
83
  protected EnvelopeEntry(int type)
75
  protected EnvelopeEntry(int type)
Lines 86-97 Link Here
86
    entries = new LinkedList();
78
    entries = new LinkedList();
87
  }
79
  }
88
80
89
  // Instance methods.
90
  // ------------------------------------------------------------------------
91
92
  /**
81
  /**
93
   * Adds an entry to this envelope.
82
   * Adds an entry to this envelope.
94
   *
83
   * 
95
   * @param entry The entry to add.
84
   * @param entry The entry to add.
96
   */
85
   */
97
  public void add(Entry entry)
86
  public void add(Entry entry)
Lines 102-108 Link Here
102
      {
91
      {
103
        if (entry instanceof EnvelopeEntry)
92
        if (entry instanceof EnvelopeEntry)
104
          ((EnvelopeEntry) entry).setContainingEnvelope(this);
93
          ((EnvelopeEntry) entry).setContainingEnvelope(this);
105
106
        entries.add(entry);
94
        entries.add(entry);
107
        if (Configuration.DEBUG)
95
        if (Configuration.DEBUG)
108
          log.fine("Payload is " + (payload == null ? "" : "not ") + "null");
96
          log.fine("Payload is " + (payload == null ? "" : "not ") + "null");
Lines 113-124 Link Here
113
  }
101
  }
114
102
115
  /**
103
  /**
116
   * Tests if this envelope contains a primitive entry with the
104
   * Tests if this envelope contains a primitive entry with the given alias.
117
   * given alias.
105
   * 
118
   *
119
   * @param alias The alias to test.
106
   * @param alias The alias to test.
120
   * @return True if this envelope (or one of the contained envelopes)
107
   * @return True if this envelope (or one of the contained envelopes) contains
121
   *   contains a primitive entry with the given alias.
108
   *         a primitive entry with the given alias.
122
   */
109
   */
123
  public boolean containsAlias(String alias)
110
  public boolean containsAlias(String alias)
124
  {
111
  {
Lines 146-179 Link Here
146
133
147
  /**
134
  /**
148
   * Tests if this envelope contains the given entry.
135
   * Tests if this envelope contains the given entry.
149
   *
136
   * 
150
   * @param entry The entry to test.
137
   * @param entry The entry to test.
151
   * @return True if this envelope contains the given entry.
138
   * @return True if this envelope contains the given entry.
152
   */
139
   */
153
  public boolean containsEntry(Entry entry)
140
  public boolean containsEntry(Entry entry)
154
  {
141
  {
155
    if (entry instanceof EnvelopeEntry)
142
    if (entry instanceof EnvelopeEntry)
156
      {
143
      return entries.contains(entry);
157
        return entries.contains(entry);
144
    if (entry instanceof PrimitiveEntry)
158
      }
145
      for (Iterator it = entries.iterator(); it.hasNext();)
159
    else if (entry instanceof PrimitiveEntry)
146
        {
160
      {
147
          Entry e = (Entry) it.next();
161
        for (Iterator it = entries.iterator(); it.hasNext();)
148
          if (e.equals(entry))
162
          {
149
            return true;
163
            Entry e = (Entry) it.next();
150
          if ((e instanceof EnvelopeEntry)
164
            if (e.equals(entry))
151
              && ((EnvelopeEntry) e).containsEntry(entry))
165
              return true;
152
            return true;
166
            if ((e instanceof EnvelopeEntry)
153
        }
167
                && ((EnvelopeEntry) e).containsEntry(entry))
168
              return true;
169
          }
170
      }
171
    return false;
154
    return false;
172
  }
155
  }
173
156
174
  /**
157
  /**
175
   * Returns a copy of all entries this envelope contains.
158
   * Returns a copy of all entries this envelope contains.
176
   *
159
   * 
177
   * @return All contained entries.
160
   * @return All contained entries.
178
   */
161
   */
179
  public List getEntries()
162
  public List getEntries()
Lines 182-191 Link Here
182
  }
165
  }
183
166
184
  /**
167
  /**
185
   * Gets all primitive entries that have the given alias. If there
168
   * Gets all primitive entries that have the given alias. If there are any
186
   * are any masked entries that contain the given alias, they will
169
   * masked entries that contain the given alias, they will be returned as well.
187
   * be returned as well.
170
   * 
188
   *
189
   * @param alias The alias of the entries to get.
171
   * @param alias The alias of the entries to get.
190
   * @return A list of all primitive entries that have the given alias.
172
   * @return A list of all primitive entries that have the given alias.
191
   */
173
   */
Lines 202-208 Link Here
202
            EnvelopeEntry ee = (EnvelopeEntry) e;
184
            EnvelopeEntry ee = (EnvelopeEntry) e;
203
            if (! ee.containsAlias(alias))
185
            if (! ee.containsAlias(alias))
204
              continue;
186
              continue;
205
206
            if (ee instanceof MaskableEnvelopeEntry)
187
            if (ee instanceof MaskableEnvelopeEntry)
207
              {
188
              {
208
                MaskableEnvelopeEntry mee = (MaskableEnvelopeEntry) ee;
189
                MaskableEnvelopeEntry mee = (MaskableEnvelopeEntry) ee;
Lines 231-257 Link Here
231
  }
212
  }
232
213
233
  /**
214
  /**
234
   * Returns the list of all aliases contained by this envelope,
215
   * Returns the list of all aliases contained by this envelope, separated by a
235
   * separated by a semicolon (';').
216
   * semicolon (';').
236
   *
217
   * 
237
   * @return The list of aliases.
218
   * @return The list of aliases.
238
   */
219
   */
239
  public String getAliasList()
220
  public String getAliasList()
240
  {
221
  {
241
    String list = properties.get("alias-list");
222
    String list = properties.get("alias-list");
242
    if (list == null)
223
    if (list == null)
243
      {
224
      return "";
244
        return "";
245
      }
246
    else
225
    else
247
      {
226
      return list;
248
        return list;
249
      }
250
  }
227
  }
251
228
252
  /**
229
  /**
253
   * Removes the specified entry.
230
   * Removes the specified entry.
254
   *
231
   * 
255
   * @param entry The entry.
232
   * @param entry The entry.
256
   * @return True if an entry was removed.
233
   * @return True if an entry was removed.
257
   */
234
   */
Lines 352-358 Link Here
352
    return new StringBuilder("Envelope{")
329
    return new StringBuilder("Envelope{")
353
        .append(super.toString())
330
        .append(super.toString())
354
        .append(", entries=").append(entries)
331
        .append(", entries=").append(entries)
355
        .append("}").toString();
332
        .append("}")
333
        .toString();
356
  }
334
  }
357
335
358
  // Protected methods.
336
  // Protected methods.
Lines 363-379 Link Here
363
    ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
341
    ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
364
    DataOutputStream out = new DataOutputStream(bout);
342
    DataOutputStream out = new DataOutputStream(bout);
365
    for (Iterator it = entries.iterator(); it.hasNext();)
343
    for (Iterator it = entries.iterator(); it.hasNext();)
366
      {
344
      ((Entry) it.next()).encode(out);
367
        ((Entry) it.next()).encode(out);
368
      }
369
  }
345
  }
370
346
371
  protected void setContainingEnvelope(EnvelopeEntry e)
347
  protected void setContainingEnvelope(EnvelopeEntry e)
372
  {
348
  {
373
    if (containingEnvelope != null)
349
    if (containingEnvelope != null)
374
      {
350
      throw new IllegalArgumentException("envelopes may not be shared");
375
        throw new IllegalArgumentException("envelopes may not be shared");
376
      }
377
    containingEnvelope = e;
351
    containingEnvelope = e;
378
  }
352
  }
379
353
Lines 423-431 Link Here
423
      }
397
      }
424
  }
398
  }
425
399
426
  // Own methods.
427
  // ------------------------------------------------------------------------
428
429
  private void makeAliasList()
400
  private void makeAliasList()
430
  {
401
  {
431
    if (Configuration.DEBUG)
402
    if (Configuration.DEBUG)
Lines 444-459 Link Here
444
              aliasOrList = ((PrimitiveEntry) entry).getAlias();
415
              aliasOrList = ((PrimitiveEntry) entry).getAlias();
445
            else if (Configuration.DEBUG)
416
            else if (Configuration.DEBUG)
446
              log.fine("Entry with no Alias. Ignored: " + entry);
417
              log.fine("Entry with no Alias. Ignored: " + entry);
447
448
            if (aliasOrList != null)
418
            if (aliasOrList != null)
449
              {
419
              {
450
                aliasOrList = aliasOrList.trim();
420
                aliasOrList = aliasOrList.trim();
451
                if (aliasOrList.trim().length() > 0)
421
                if (aliasOrList.trim().length() > 0)
452
                {
422
                  {
453
                  buf.append(aliasOrList);
423
                    buf.append(aliasOrList);
454
                  if (it.hasNext())
424
                    if (it.hasNext())
455
                    buf.append(';');
425
                      buf.append(';');
456
                }
426
                  }
457
              }
427
              }
458
          }
428
          }
459
        String aliasList = buf.toString();
429
        String aliasList = buf.toString();
(-)GnuPrivateKeyring.java (-33 / +9 lines)
Lines 56-85 Link Here
56
import java.util.logging.Logger;
56
import java.util.logging.Logger;
57
57
58
/**
58
/**
59
 * <p>.</p>
59
 * 
60
 */
60
 */
61
public class GnuPrivateKeyring extends BaseKeyring implements IPrivateKeyring
61
public class GnuPrivateKeyring
62
    extends BaseKeyring
63
    implements IPrivateKeyring
62
{
64
{
63
  // Constants and variables
64
  // -------------------------------------------------------------------------
65
66
  private static final Logger log = Logger.getLogger(GnuPrivateKeyring.class.getName());
65
  private static final Logger log = Logger.getLogger(GnuPrivateKeyring.class.getName());
67
  public static final int USAGE = Registry.GKR_PRIVATE_KEYS
66
  public static final int USAGE = Registry.GKR_PRIVATE_KEYS
68
                                  | Registry.GKR_PUBLIC_CREDENTIALS;
67
                                  | Registry.GKR_PUBLIC_CREDENTIALS;
69
70
  protected String mac;
68
  protected String mac;
71
72
  protected int maclen;
69
  protected int maclen;
73
74
  protected String cipher;
70
  protected String cipher;
75
76
  protected String mode;
71
  protected String mode;
77
78
  protected int keylen;
72
  protected int keylen;
79
73
80
  // Constructor(s)
81
  // -------------------------------------------------------------------------
82
83
  public GnuPrivateKeyring(String mac, int maclen, String cipher, String mode,
74
  public GnuPrivateKeyring(String mac, int maclen, String cipher, String mode,
84
                           int keylen)
75
                           int keylen)
85
  {
76
  {
Lines 98-109 Link Here
98
    this("HMAC-SHA-1", 20, "AES", "OFB", 16);
89
    this("HMAC-SHA-1", 20, "AES", "OFB", 16);
99
  }
90
  }
100
91
101
  // Class methods
102
  // -------------------------------------------------------------------------
103
104
  // Instance methods
105
  // -------------------------------------------------------------------------
106
107
  public boolean containsPrivateKey(String alias)
92
  public boolean containsPrivateKey(String alias)
108
  {
93
  {
109
    if (Configuration.DEBUG)
94
    if (Configuration.DEBUG)
Lines 156-162 Link Here
156
                  log.throwing(this.getClass().getName(), "getPrivateKey", e);
141
                  log.throwing(this.getClass().getName(), "getPrivateKey", e);
157
                throw new UnrecoverableKeyException("authentication failed");
142
                throw new UnrecoverableKeyException("authentication failed");
158
              }
143
              }
159
160
            PasswordEncryptedEntry e2 = null;
144
            PasswordEncryptedEntry e2 = null;
161
            for (Iterator it = e1.getEntries().iterator(); it.hasNext();)
145
            for (Iterator it = e1.getEntries().iterator(); it.hasNext();)
162
              {
146
              {
Lines 167-173 Link Here
167
                    break;
151
                    break;
168
                  }
152
                  }
169
              }
153
              }
170
171
            if (e2 != null)
154
            if (e2 != null)
172
              {
155
              {
173
                try
156
                try
Lines 179-185 Link Here
179
                    log.throwing(this.getClass().getName(), "getPrivateKey", e);
162
                    log.throwing(this.getClass().getName(), "getPrivateKey", e);
180
                    throw new UnrecoverableKeyException("decryption failed");
163
                    throw new UnrecoverableKeyException("decryption failed");
181
                  }
164
                  }
182
183
                for (Iterator it = e2.get(alias).iterator(); it.hasNext();)
165
                for (Iterator it = e2.get(alias).iterator(); it.hasNext();)
184
                  {
166
                  {
185
                    Entry e = (Entry) it.next();
167
                    Entry e = (Entry) it.next();
Lines 222-228 Link Here
222
          {
204
          {
223
            if (Configuration.DEBUG)
205
            if (Configuration.DEBUG)
224
              log.log(Level.FINE, "Exception while encrypting the key. "
206
              log.log(Level.FINE, "Exception while encrypting the key. "
225
                      + "Rethrow as IllegalArgumentException", x);
207
                                  + "Rethrow as IllegalArgumentException", x);
226
            throw new IllegalArgumentException(x.toString());
208
            throw new IllegalArgumentException(x.toString());
227
          }
209
          }
228
        if (Configuration.DEBUG)
210
        if (Configuration.DEBUG)
Lines 238-252 Link Here
238
          {
220
          {
239
            if (Configuration.DEBUG)
221
            if (Configuration.DEBUG)
240
              log.log(Level.FINE, "Exception while authenticating the encrypted "
222
              log.log(Level.FINE, "Exception while authenticating the encrypted "
241
                      + "key. Rethrow as IllegalArgumentException", x);
223
                                  + "key. Rethrow as IllegalArgumentException", x);
242
            throw new IllegalArgumentException(x.toString());
224
            throw new IllegalArgumentException(x.toString());
243
          }
225
          }
244
245
        keyring.add(auth);
226
        keyring.add(auth);
246
      }
227
      }
247
    else if (Configuration.DEBUG)
228
    else if (Configuration.DEBUG)
248
      log.fine("Keyring already contains alias: " + alias);
229
      log.fine("Keyring already contains alias: " + alias);
249
250
    if (Configuration.DEBUG)
230
    if (Configuration.DEBUG)
251
      log.exiting(this.getClass().getName(), "putPrivateKey");
231
      log.exiting(this.getClass().getName(), "putPrivateKey");
252
  }
232
  }
Lines 303-309 Link Here
303
      }
283
      }
304
    else if (Configuration.DEBUG)
284
    else if (Configuration.DEBUG)
305
      log.fine("Keyring already contains alias: " + alias);
285
      log.fine("Keyring already contains alias: " + alias);
306
307
    if (Configuration.DEBUG)
286
    if (Configuration.DEBUG)
308
      log.exiting(this.getClass().getName(), "putPublicKey");
287
      log.exiting(this.getClass().getName(), "putPublicKey");
309
  }
288
  }
Lines 359-365 Link Here
359
      }
338
      }
360
    else if (Configuration.DEBUG)
339
    else if (Configuration.DEBUG)
361
      log.fine("Keyring already contains alias: " + alias);
340
      log.fine("Keyring already contains alias: " + alias);
362
363
    if (Configuration.DEBUG)
341
    if (Configuration.DEBUG)
364
      log.exiting(this.getClass().getName(), "putCertPath");
342
      log.exiting(this.getClass().getName(), "putCertPath");
365
  }
343
  }
Lines 370-381 Link Here
370
      log.entering(this.getClass().getName(), "load");
348
      log.entering(this.getClass().getName(), "load");
371
    if (in.read() != USAGE)
349
    if (in.read() != USAGE)
372
      throw new MalformedKeyringException("incompatible keyring usage");
350
      throw new MalformedKeyringException("incompatible keyring usage");
373
374
    if (in.read() != PasswordAuthenticatedEntry.TYPE)
351
    if (in.read() != PasswordAuthenticatedEntry.TYPE)
375
      throw new MalformedKeyringException("expecting password-authenticated entry tag");
352
      throw new MalformedKeyringException(
376
353
          "expecting password-authenticated entry tag");
377
    keyring = PasswordAuthenticatedEntry.decode(new DataInputStream(in),
354
    keyring = PasswordAuthenticatedEntry.decode(new DataInputStream(in), password);
378
                                                password);
379
    if (Configuration.DEBUG)
355
    if (Configuration.DEBUG)
380
      log.exiting(this.getClass().getName(), "load");
356
      log.exiting(this.getClass().getName(), "load");
381
  }
357
  }
(-)GnuPublicKeyring.java (-14 / +5 lines)
Lines 51-67 Link Here
51
import java.util.Iterator;
51
import java.util.Iterator;
52
import java.util.logging.Logger;
52
import java.util.logging.Logger;
53
53
54
public class GnuPublicKeyring extends BaseKeyring implements IPublicKeyring
54
public class GnuPublicKeyring
55
    extends BaseKeyring
56
    implements IPublicKeyring
55
{
57
{
56
  // Fields.
57
  // ------------------------------------------------------------------------
58
59
  private static final Logger log = Logger.getLogger(GnuPublicKeyring.class.getName());
58
  private static final Logger log = Logger.getLogger(GnuPublicKeyring.class.getName());
60
  public static final int USAGE = Registry.GKR_CERTIFICATES;
59
  public static final int USAGE = Registry.GKR_CERTIFICATES;
61
60
62
  // Constructors.
63
  // ------------------------------------------------------------------------
64
65
  public GnuPublicKeyring(String mac, int macLen)
61
  public GnuPublicKeyring(String mac, int macLen)
66
  {
62
  {
67
    keyring = new PasswordAuthenticatedEntry(mac, macLen, new Properties());
63
    keyring = new PasswordAuthenticatedEntry(mac, macLen, new Properties());
Lines 73-81 Link Here
73
  {
69
  {
74
  }
70
  }
75
71
76
  // Instance methods.
77
  // ------------------------------------------------------------------------
78
79
  public boolean containsCertificate(String alias)
72
  public boolean containsCertificate(String alias)
80
  {
73
  {
81
    if (Configuration.DEBUG)
74
    if (Configuration.DEBUG)
Lines 127-133 Link Here
127
      }
120
      }
128
    else if (Configuration.DEBUG)
121
    else if (Configuration.DEBUG)
129
      log.fine("Keyring already contains alias: " + alias);
122
      log.fine("Keyring already contains alias: " + alias);
130
131
    if (Configuration.DEBUG)
123
    if (Configuration.DEBUG)
132
      log.exiting(this.getClass().getName(), "putCertificate");
124
      log.exiting(this.getClass().getName(), "putCertificate");
133
  }
125
  }
Lines 138-147 Link Here
138
      log.entering(this.getClass().getName(), "load");
130
      log.entering(this.getClass().getName(), "load");
139
    if (in.read() != USAGE)
131
    if (in.read() != USAGE)
140
      throw new MalformedKeyringException("incompatible keyring usage");
132
      throw new MalformedKeyringException("incompatible keyring usage");
141
142
    if (in.read() != PasswordAuthenticatedEntry.TYPE)
133
    if (in.read() != PasswordAuthenticatedEntry.TYPE)
143
      throw new MalformedKeyringException("expecting password-authenticated entry tag");
134
      throw new MalformedKeyringException(
144
135
          "expecting password-authenticated entry tag");
145
    DataInputStream dis = new DataInputStream(in);
136
    DataInputStream dis = new DataInputStream(in);
146
    keyring = PasswordAuthenticatedEntry.decode(dis, password);
137
    keyring = PasswordAuthenticatedEntry.decode(dis, password);
147
    if (Configuration.DEBUG)
138
    if (Configuration.DEBUG)
(-)IKeyring.java (-52 / +50 lines)
Lines 44-163 Link Here
44
import java.util.Map;
44
import java.util.Map;
45
45
46
/**
46
/**
47
 * <p>The top-level interface to a <i>keyring:</i> a file that is used to
47
 * The top-level interface to a <i>keyring:</i> a file that is used to store
48
 * store and protect public and private cryptographic keys.</p>
48
 * and protect public and private cryptographic keys.
49
 *
49
 * <p>
50
 * <p>A <i>keyring</i> is modelled as a mapping of one <i>alias</i> to one or
50
 * A <i>keyring</i> is modelled as a mapping of one <i>alias</i> to one or
51
 * more <i>entries</i> (optionally of different types).</p>
51
 * more <i>entries</i> (optionally of different types).
52
 *
52
 * <p>
53
 * <p>See also the sub-interfaces {@link IPublicKeyring} and
53
 * See also the sub-interfaces {@link IPublicKeyring} and
54
 * {@link IPrivateKeyring} for special types of <i>keyrings</i> --the difference
54
 * {@link IPrivateKeyring} for special types of <i>keyrings</i> --the
55
 * being in the type of entries they contain.</p>
55
 * difference being in the type of entries they contain.
56
 */
56
 */
57
public interface IKeyring
57
public interface IKeyring
58
{
58
{
59
60
  /**
59
  /**
61
   * <p>Property name for the source of data to load the keyring from. The
60
   * Property name for the source of data to load the keyring from. The value
62
   * value mapped must be a {@link java.io.InputStream}.</p>
61
   * mapped must be a {@link java.io.InputStream}.
63
   */
62
   */
64
  public static final String KEYRING_DATA_IN = "gnu.crypto.keyring.data.in";
63
  public static final String KEYRING_DATA_IN = "gnu.crypto.keyring.data.in";
65
64
66
  /**
65
  /**
67
   * <p>Property name for the data sink to store the keyring to. The value
66
   * Property name for the data sink to store the keyring to. The value mapped
68
   * mapped must be a {@link java.io.OutputStream}.</p>
67
   * must be a {@link java.io.OutputStream}.
69
   */
68
   */
70
  public static final String KEYRING_DATA_OUT = "gun.crypto.keyring.data.out";
69
  public static final String KEYRING_DATA_OUT = "gun.crypto.keyring.data.out";
71
70
72
  /**
71
  /**
73
   * <p>Property name for the keyring's top-level password, used to
72
   * Property name for the keyring's top-level password, used to authenticate
74
   * authenticate and/or transform the store itself. The mapped value must be a
73
   * and/or transform the store itself. The mapped value must be a char array.
75
   * char array.</p>
76
   */
74
   */
77
  public static final String KEYRING_PASSWORD = "gnu.crypto.keyring.password";
75
  public static final String KEYRING_PASSWORD = "gnu.crypto.keyring.password";
78
76
79
  /**
77
  /**
80
   * <p>Loads a keyring into memory.</p>
78
   * Loads a keyring into memory.
81
   *
79
   * <p>
82
   * <p>What happens to the current contents of this keyring? are the new ones
80
   * What happens to the current contents of this keyring? are the new ones
83
   * merged with the current ones or do they simply replace them?</p>
81
   * merged with the current ones or do they simply replace them?
84
   *
82
   * 
85
   * @param attributes The attributes that designate the source where the store
83
   * @param attributes The attributes that designate the source where the store
86
   * is to be loaded from. What happens
84
   *          is to be loaded from. What happens
87
   * @throws IllegalArgumentException If the attributes are inappropriate.
85
   * @throws IllegalArgumentException If the attributes are inappropriate.
88
   * @throws IOException If the keyring file cannot be read.
86
   * @throws IOException If the keyring file cannot be read.
89
   * @throws SecurityException If the given password is incorrect, or if the
87
   * @throws SecurityException If the given password is incorrect, or if the
90
   * top-level authentication or decryption fails.
88
   *           top-level authentication or decryption fails.
91
   */
89
   */
92
  void load(Map attributes) throws IOException;
90
  void load(Map attributes) throws IOException;
93
91
94
  /**
92
  /**
95
   * <p>Stores the contents of this keyring to persistent storage as specified
93
   * Stores the contents of this keyring to persistent storage as specified by
96
   * by the designated <code>attributes</code>.</p>
94
   * the designated <code>attributes</code>.
97
   *
95
   * 
98
   * @param attributes the attributes that define where the contents of this
96
   * @param attributes the attributes that define where the contents of this
99
   * keyring will be stored.
97
   *          keyring will be stored.
100
   * @throws IOException if an exception occurs during the process.
98
   * @throws IOException if an exception occurs during the process.
101
   */
99
   */
102
  void store(Map attributes) throws IOException;
100
  void store(Map attributes) throws IOException;
103
101
104
  /**
102
  /**
105
   * <p>Resets this keyring, clearing all sensitive data. This method always
103
   * Resets this keyring, clearing all sensitive data. This method always
106
   * suceeds.</p>
104
   * suceeds.
107
   */
105
   */
108
  void reset();
106
  void reset();
109
107
110
  /**
108
  /**
111
   * <p>Returns the number of entries in this keyring.</p>
109
   * Returns the number of entries in this keyring.
112
   *
110
   * 
113
   * @return The number of current entries in this keyring.
111
   * @return The number of current entries in this keyring.
114
   */
112
   */
115
  int size();
113
  int size();
116
114
117
  /**
115
  /**
118
   * <p>Returns an {@link Enumeration} of all aliases (instances of
116
   * Returns an {@link Enumeration} of all aliases (instances of {@link String})
119
   * {@link String}) in this keyring.</p>
117
   * in this keyring.
120
   *
118
   * 
121
   * @return The enumeration of {@link String}s each representing an
119
   * @return The enumeration of {@link String}s each representing an <i>alias</i>
122
   * <i>alias</i> found in this keyring.
120
   *         found in this keyring.
123
   */
121
   */
124
  Enumeration aliases();
122
  Enumeration aliases();
125
123
126
  /**
124
  /**
127
   * Tests whether or not this keyring contains the given alias.
125
   * Tests whether or not this keyring contains the given alias.
128
   *
126
   * 
129
   * @param alias The alias to check.
127
   * @param alias The alias to check.
130
   * @return true if this keyring contains the alias.
128
   * @return true if this keyring contains the alias.
131
   */
129
   */
132
  boolean containsAlias(String alias);
130
  boolean containsAlias(String alias);
133
131
134
  /**
132
  /**
135
   * <p>Returns a {@link List} of entries (instances of {@link Entry}) for the
133
   * Returns a {@link List} of entries (instances of {@link Entry}) for the
136
   * given <code>alias</code>, or <code>null</code> if there no such entry
134
   * given <code>alias</code>, or <code>null</code> if there no such entry
137
   * exists.</p>
135
   * exists.
138
   *
136
   * 
139
   * @param alias The alias of the entry(ies) to return.
137
   * @param alias The alias of the entry(ies) to return.
140
   * @return A list of all entries (instances of {@link Entry} that have the
138
   * @return A list of all entries (instances of {@link Entry} that have the
141
   * given <code>alias</code>, or <code>null</code> if no one {@link Entry} can
139
   *         given <code>alias</code>, or <code>null</code> if no one
142
   * be found with the designated <code>alias</code>.
140
   *         {@link Entry} can be found with the designated <code>alias</code>.
143
   */
141
   */
144
  List get(String alias);
142
  List get(String alias);
145
143
146
  /**
144
  /**
147
   * <p>Adds a designated {@link Entry} to this keyring.</p>
145
   * Adds a designated {@link Entry} to this keyring.
148
   *
146
   * <p>
149
   * <p>What happens if there is already an entry with the same alias?</p>
147
   * What happens if there is already an entry with the same alias?
150
   *
148
   * 
151
   * @param entry The entry to put in this keyring.
149
   * @param entry The entry to put in this keyring.
152
   */
150
   */
153
  void add(Entry entry);
151
  void add(Entry entry);
154
152
155
  /**
153
  /**
156
   * <p>Removes an entry with the designated <code>alias</code> from this
154
   * Removes an entry with the designated <code>alias</code> from this
157
   * keyring. Does nothing if there was no such entry.</p>
155
   * keyring. Does nothing if there was no such entry.
158
   *
156
   * <p>
159
   * <p>What happens if there are more than one?</p>
157
   * What happens if there are more than one?
160
   *
158
   * 
161
   * @param alias The alias of the entry to remove.
159
   * @param alias The alias of the entry to remove.
162
   */
160
   */
163
  void remove(String alias);
161
  void remove(String alias);
(-)IPrivateKeyring.java (-37 / +39 lines)
Lines 44-84 Link Here
44
import java.security.cert.Certificate;
44
import java.security.cert.Certificate;
45
45
46
/**
46
/**
47
 * <p>An interface to private, or "personal", keyrings, which contain private
47
 * An interface to private, or "personal", keyrings, which contain private
48
 * credentials. The contract is that each such entry is known by a unique
48
 * credentials. The contract is that each such entry is known by a unique
49
 * <i>alias</i>.</p>
49
 * <i>alias</i>.
50
 *
50
 * <p>
51
 * <p>What about public keys? and certificate-path?</p>
51
 * What about public keys? and certificate-path?
52
 */
52
 */
53
public interface IPrivateKeyring extends IKeyring
53
public interface IPrivateKeyring
54
    extends IKeyring
54
{
55
{
55
56
  /**
56
  /**
57
   * <p>Tests if this keyring contains a private key entry with the given
57
   * Tests if this keyring contains a private key entry with the given
58
   * <code>alias</code>.</p>
58
   * <code>alias</code>.
59
   *
59
   * 
60
   * @param alias The alias to check.
60
   * @param alias The alias to check.
61
   * @return <code>true</code> if this keyring contains a private key with the
61
   * @return <code>true</code> if this keyring contains a private key with the
62
   * given <code>alias</code>; <code>false</code> otherwise.</p>
62
   *         given <code>alias</code>; <code>false</code> otherwise.
63
   */
63
   */
64
  boolean containsPrivateKey(String alias);
64
  boolean containsPrivateKey(String alias);
65
65
66
  /**
66
  /**
67
   * <p>Returns the private key with the given <code>alias</code>.</p>
67
   * Returns the private key with the given <code>alias</code>.
68
   *
68
   * 
69
   * @param alias The alias of the private key to find.
69
   * @param alias The alias of the private key to find.
70
   * @param password The password of the private key.
70
   * @param password The password of the private key.
71
   * @return The private, or secret, key if one is found; <code>null</code> if
71
   * @return The private, or secret, key if one is found; <code>null</code> if
72
   * none were found.
72
   *         none were found.
73
   * @throws UnrecoverableKeyException If the private key could not be
73
   * @throws UnrecoverableKeyException If the private key could not be
74
   * recovered, possibly due to a bad password.
74
   *           recovered, possibly due to a bad password.
75
   */
75
   */
76
  Key getPrivateKey(String alias, char[] password)
76
  Key getPrivateKey(String alias, char[] password)
77
      throws UnrecoverableKeyException;
77
      throws UnrecoverableKeyException;
78
78
79
  /**
79
  /**
80
   * <p>Adds a private key to this keyring.</p>
80
   * Adds a private key to this keyring.
81
   *
81
   * 
82
   * @param alias The alias of the private key.
82
   * @param alias The alias of the private key.
83
   * @param key The private key.
83
   * @param key The private key.
84
   * @param password The password used to protect this private key.
84
   * @param password The password used to protect this private key.
Lines 86-140 Link Here
86
  void putPrivateKey(String alias, Key key, char[] password);
86
  void putPrivateKey(String alias, Key key, char[] password);
87
87
88
  /**
88
  /**
89
   * <p>Checks if this keyring contains a public key with the given
89
   * Checks if this keyring contains a public key with the given
90
   * <code>alias</code>.</p>
90
   * <code>alias</code>.
91
   *
91
   * 
92
   * @param alias The alias to test.
92
   * @param alias The alias to test.
93
   * @return <code>true</code> if this keyring contains a public key entry with
93
   * @return <code>true</code> if this keyring contains a public key entry
94
   * the given <code>alias</code>; <code>false</code> otherwise.
94
   *         with the given <code>alias</code>; <code>false</code>
95
   *         otherwise.
95
   */
96
   */
96
  boolean containsPublicKey(String alias);
97
  boolean containsPublicKey(String alias);
97
98
98
  /**
99
  /**
99
   * <p>Returns the public key with the given <code>alias</code>, or
100
   * Returns the public key with the given <code>alias</code>, or
100
   * <code>null</code> if there is no such entry.</p>
101
   * <code>null</code> if there is no such entry.
101
   *
102
   * 
102
   * @param alias The alias of the public key to find.
103
   * @param alias The alias of the public key to find.
103
   * @return The public key; or <code>null</code> if none were found.
104
   * @return The public key; or <code>null</code> if none were found.
104
   */
105
   */
105
  PublicKey getPublicKey(String alias);
106
  PublicKey getPublicKey(String alias);
106
107
107
  /**
108
  /**
108
   * <p>Sets a public key entry.</p>
109
   * Sets a public key entry.
109
   *
110
   * 
110
   * @param alias The alias for this public key.
111
   * @param alias The alias for this public key.
111
   * @param key The public key.
112
   * @param key The public key.
112
   */
113
   */
113
  void putPublicKey(String alias, PublicKey key);
114
  void putPublicKey(String alias, PublicKey key);
114
115
115
  /**
116
  /**
116
   * <p>Checks if this keyring contains a certificate path with the given
117
   * Checks if this keyring contains a certificate path with the given
117
   * <code>alias</code>.</p>
118
   * <code>alias</code>.
118
   *
119
   * 
119
   * @param alias The alias to check.
120
   * @param alias The alias to check.
120
   * @return <code>true</code> if this keyring contains a certificate path with
121
   * @return <code>true</code> if this keyring contains a certificate path
121
   * the given <code>alias</code>; <code>false</code> otherwise.
122
   *         with the given <code>alias</code>; <code>false</code>
123
   *         otherwise.
122
   */
124
   */
123
  boolean containsCertPath(String alias);
125
  boolean containsCertPath(String alias);
124
126
125
  /**
127
  /**
126
   * <p>Returns the certificate path with the given <code>alias</code>, or
128
   * Returns the certificate path with the given <code>alias</code>, or
127
   * <code>null</code> if there is no such entry.</p>
129
   * <code>null</code> if there is no such entry.
128
   *
130
   * 
129
   * @param alias The alias of the certificate path to find.
131
   * @param alias The alias of the certificate path to find.
130
   * @return The certificate path for the designated <code>alias</code>; or
132
   * @return The certificate path for the designated <code>alias</code>; or
131
   * <code>null</code> if none were found.
133
   *         <code>null</code> if none were found.
132
   */
134
   */
133
  Certificate[] getCertPath(String alias);
135
  Certificate[] getCertPath(String alias);
134
136
135
  /**
137
  /**
136
   * <p>Sets a certificate path entry.</p>
138
   * Sets a certificate path entry.
137
   *
139
   * 
138
   * @param alias The alias for this certificate path.
140
   * @param alias The alias for this certificate path.
139
   * @param path The certificate path.
141
   * @param path The certificate path.
140
   */
142
   */
(-)IPublicKeyring.java (-17 / +18 lines)
Lines 41-79 Link Here
41
import java.security.cert.Certificate;
41
import java.security.cert.Certificate;
42
42
43
/**
43
/**
44
 * <p>An interface for keyrings that contain trusted (by the owner) public
44
 * An interface for keyrings that contain trusted (by the owner) public
45
 * credentials (incl. certificates).</p>
45
 * credentials (incl. certificates).
46
 *
46
 * 
47
 * @see IKeyring
47
 * @see IKeyring
48
 */
48
 */
49
public interface IPublicKeyring extends IKeyring
49
public interface IPublicKeyring
50
    extends IKeyring
50
{
51
{
51
52
  /**
52
  /**
53
   * <p>Tests if this keyring contains a certificate entry with the specified
53
   * Tests if this keyring contains a certificate entry with the specified
54
   * <code>alias</code>.</p>
54
   * <code>alias</code>.
55
   *
55
   * 
56
   * @param alias The alias of the certificate to check.
56
   * @param alias The alias of the certificate to check.
57
   * @return <code>true</code> if this keyring contains a certificate entry
57
   * @return <code>true</code> if this keyring contains a certificate entry
58
   * that has the given <code>alias</code>; <code>false</code> otherwise.
58
   *         that has the given <code>alias</code>; <code>false</code>
59
   *         otherwise.
59
   */
60
   */
60
  boolean containsCertificate(String alias);
61
  boolean containsCertificate(String alias);
61
62
62
  /**
63
  /**
63
   * <p>Returns a certificate that has the given <code>alias</code>, or
64
   * Returns a certificate that has the given <code>alias</code>, or
64
   * <code>null</code> if this keyring has no such entry.</p>
65
   * <code>null</code> if this keyring has no such entry.
65
   *
66
   * 
66
   * @param alias The alias of the certificate to find.
67
   * @param alias The alias of the certificate to find.
67
   * @return The certificate with the designated <code>alias</code>, or
68
   * @return The certificate with the designated <code>alias</code>, or
68
   * <code>null</code> if none found.
69
   *         <code>null</code> if none found.
69
   */
70
   */
70
  Certificate getCertificate(String alias);
71
  Certificate getCertificate(String alias);
71
72
72
  /**
73
  /**
73
   * <p>Adds a certificate in this keyring, with the given <code>alias</code>.</p>
74
   * Adds a certificate in this keyring, with the given <code>alias</code>.
74
   *
75
   * <p>
75
   * <p>What happens if there is already a certificate entry with this alias?</p>
76
   * What happens if there is already a certificate entry with this alias?
76
   *
77
   * 
77
   * @param alias The alias of this certificate entry.
78
   * @param alias The alias of this certificate entry.
78
   * @param cert The certificate.
79
   * @param cert The certificate.
79
   */
80
   */
(-)MalformedKeyringException.java (-5 / +2 lines)
Lines 40-51 Link Here
40
40
41
import java.io.IOException;
41
import java.io.IOException;
42
42
43
public class MalformedKeyringException extends IOException
43
public class MalformedKeyringException
44
    extends IOException
44
{
45
{
45
46
  // Constructors.
47
  // ------------------------------------------------------------------------
48
49
  public MalformedKeyringException()
46
  public MalformedKeyringException()
50
  {
47
  {
51
    super();
48
    super();
(-)MaskableEnvelopeEntry.java (-30 / +11 lines)
Lines 43-62 Link Here
43
43
44
/**
44
/**
45
 * An envelope entry that can be "masked" -- placed in a state where the
45
 * An envelope entry that can be "masked" -- placed in a state where the
46
 * envelope's contents cannot be accessed, due to the envelope not being
46
 * envelope's contents cannot be accessed, due to the envelope not being fully
47
 * fully decoded, for example.
47
 * decoded, for example.
48
 */
48
 */
49
public abstract class MaskableEnvelopeEntry extends EnvelopeEntry
49
public abstract class MaskableEnvelopeEntry
50
    extends EnvelopeEntry
50
{
51
{
51
  // Fields.
52
  // ------------------------------------------------------------------------
53
54
  /** The masked state. */
52
  /** The masked state. */
55
  protected boolean masked;
53
  protected boolean masked;
56
54
57
  // Constructors.
58
  // ------------------------------------------------------------------------
59
60
  public MaskableEnvelopeEntry(int type, Properties properties)
55
  public MaskableEnvelopeEntry(int type, Properties properties)
61
  {
56
  {
62
    super(type, properties);
57
    super(type, properties);
Lines 67-78 Link Here
67
    super(type);
62
    super(type);
68
  }
63
  }
69
64
70
  // Instance methods.
71
  // ------------------------------------------------------------------------
72
73
  /**
65
  /**
74
   * Sets the masked state to the specified value.
66
   * Sets the masked state to the specified value.
75
   *
67
   * 
76
   * @param masked The new masked state.
68
   * @param masked The new masked state.
77
   */
69
   */
78
  protected final void setMasked(boolean masked)
70
  protected final void setMasked(boolean masked)
Lines 83-89 Link Here
83
  /**
75
  /**
84
   * Gets the masked state of this object. Certain operations on this object
76
   * Gets the masked state of this object. Certain operations on this object
85
   * will fail if it is masked.
77
   * will fail if it is masked.
86
   *
78
   * 
87
   * @return The current masked state.
79
   * @return The current masked state.
88
   */
80
   */
89
  public boolean isMasked()
81
  public boolean isMasked()
Lines 94-138 Link Here
94
  public void add(Entry entry)
86
  public void add(Entry entry)
95
  {
87
  {
96
    if (isMasked())
88
    if (isMasked())
97
      {
89
      throw new IllegalStateException("masked envelope");
98
        throw new IllegalStateException("masked envelope");
99
      }
100
    super.add(entry);
90
    super.add(entry);
101
  }
91
  }
102
92
103
  public boolean containsEntry(Entry entry)
93
  public boolean containsEntry(Entry entry)
104
  {
94
  {
105
    if (isMasked())
95
    if (isMasked())
106
      {
96
      throw new IllegalStateException("masked envelope");
107
        throw new IllegalStateException("masked envelope");
108
      }
109
    return super.containsEntry(entry);
97
    return super.containsEntry(entry);
110
  }
98
  }
111
99
112
  public List getEntries()
100
  public List getEntries()
113
  {
101
  {
114
    if (isMasked())
102
    if (isMasked())
115
      {
103
      throw new IllegalStateException("masked envelope");
116
        throw new IllegalStateException("masked envelope");
117
      }
118
    return new ArrayList(entries);
104
    return new ArrayList(entries);
119
  }
105
  }
120
106
121
  public List get(String alias)
107
  public List get(String alias)
122
  {
108
  {
123
    if (isMasked())
109
    if (isMasked())
124
      {
110
      throw new IllegalStateException("masked envelope");
125
        throw new IllegalStateException("masked envelope");
126
      }
127
    return super.get(alias);
111
    return super.get(alias);
128
  }
112
  }
129
113
130
  public boolean remove(Entry entry)
114
  public boolean remove(Entry entry)
131
  {
115
  {
132
    if (isMasked())
116
    if (isMasked())
133
      {
117
      throw new IllegalStateException("masked envelope");
134
        throw new IllegalStateException("masked envelope");
135
      }
136
    return super.remove(entry);
118
    return super.remove(entry);
137
  }
119
  }
138
120
Lines 140-146 Link Here
140
  {
122
  {
141
    if (isMasked())
123
    if (isMasked())
142
      throw new IllegalStateException("masked envelope");
124
      throw new IllegalStateException("masked envelope");
143
144
    return super.remove(alias);
125
    return super.remove(alias);
145
  }
126
  }
146
127
(-)MeteredInputStream.java (-14 / +4 lines)
Lines 39-60 Link Here
39
package gnu.javax.crypto.keyring;
39
package gnu.javax.crypto.keyring;
40
40
41
import java.io.FilterInputStream;
41
import java.io.FilterInputStream;
42
import java.io.InputStream;
43
import java.io.IOException;
42
import java.io.IOException;
43
import java.io.InputStream;
44
44
45
final class MeteredInputStream extends FilterInputStream
45
final class MeteredInputStream
46
    extends FilterInputStream
46
{
47
{
47
48
  // Fields.
49
  // ------------------------------------------------------------------------
50
51
  private int count;
48
  private int count;
52
53
  private final int limit;
49
  private final int limit;
54
50
55
  // Constructor.
56
  // ------------------------------------------------------------------------
57
58
  MeteredInputStream(InputStream in, int limit)
51
  MeteredInputStream(InputStream in, int limit)
59
  {
52
  {
60
    super(in);
53
    super(in);
Lines 64-75 Link Here
64
    count = 0;
57
    count = 0;
65
  }
58
  }
66
59
67
  // Instance methods.
68
  // ------------------------------------------------------------------------
69
70
  /**
60
  /**
71
   * Tests if the number of bytes read has reached the limit.
61
   * Tests if the number of bytes read has reached the limit.
72
   *
62
   * 
73
   * @return True if the limit has been reached.
63
   * @return True if the limit has been reached.
74
   */
64
   */
75
  public boolean limitReached()
65
  public boolean limitReached()
(-)PasswordAuthenticatedEntry.java (-59 / +20 lines)
Lines 63-91 Link Here
63
import java.util.logging.Logger;
63
import java.util.logging.Logger;
64
64
65
/**
65
/**
66
 * <p>An entry authenticated with a password-based MAC.</p>
66
 * An entry authenticated with a password-based MAC.
67
 */
67
 */
68
public final class PasswordAuthenticatedEntry extends MaskableEnvelopeEntry
68
public final class PasswordAuthenticatedEntry
69
    extends MaskableEnvelopeEntry
69
    implements PasswordProtectedEntry, Registry
70
    implements PasswordProtectedEntry, Registry
70
{
71
{
71
  // Constants and variables
72
  // -------------------------------------------------------------------------
73
74
  private static final Logger log = Logger.getLogger(PasswordAuthenticatedEntry.class.getName());
72
  private static final Logger log = Logger.getLogger(PasswordAuthenticatedEntry.class.getName());
75
  public static final int TYPE = 3;
73
  public static final int TYPE = 3;
76
74
77
  // Constructor(s)
78
  // -------------------------------------------------------------------------
79
80
  public PasswordAuthenticatedEntry(String mac, int maclen,
75
  public PasswordAuthenticatedEntry(String mac, int maclen,
81
                                    Properties properties)
76
                                    Properties properties)
82
  {
77
  {
83
    super(TYPE, properties);
78
    super(TYPE, properties);
84
85
    if (mac == null || mac.length() == 0)
79
    if (mac == null || mac.length() == 0)
86
      {
80
      throw new IllegalArgumentException("no MAC specified");
87
        throw new IllegalArgumentException("no MAC specified");
88
      }
89
    this.properties.put("mac", mac);
81
    this.properties.put("mac", mac);
90
    this.properties.put("maclen", String.valueOf(maclen));
82
    this.properties.put("maclen", String.valueOf(maclen));
91
    setMasked(false);
83
    setMasked(false);
Lines 97-105 Link Here
97
    setMasked(true);
89
    setMasked(true);
98
  }
90
  }
99
91
100
  // Class methods
101
  // -------------------------------------------------------------------------
102
103
  public static PasswordAuthenticatedEntry decode(DataInputStream in,
92
  public static PasswordAuthenticatedEntry decode(DataInputStream in,
104
                                                  char[] password)
93
                                                  char[] password)
105
      throws IOException
94
      throws IOException
Lines 115-124 Link Here
115
    entry.decodeEnvelope(in2);
104
    entry.decodeEnvelope(in2);
116
    byte[] macValue = new byte[mac.macSize()];
105
    byte[] macValue = new byte[mac.macSize()];
117
    in.readFully(macValue);
106
    in.readFully(macValue);
118
    if (!Arrays.equals(macValue, mac.digest()))
107
    if (! Arrays.equals(macValue, mac.digest()))
119
      {
108
      throw new MalformedKeyringException("MAC verification failed");
120
        throw new MalformedKeyringException("MAC verification failed");
121
      }
122
    return entry;
109
    return entry;
123
  }
110
  }
124
111
Lines 127-150 Link Here
127
  {
114
  {
128
    PasswordAuthenticatedEntry entry = new PasswordAuthenticatedEntry();
115
    PasswordAuthenticatedEntry entry = new PasswordAuthenticatedEntry();
129
    entry.defaultDecode(in);
116
    entry.defaultDecode(in);
130
    if (!entry.properties.containsKey("mac"))
117
    if (! entry.properties.containsKey("mac"))
131
      {
118
      throw new MalformedKeyringException("no MAC");
132
        throw new MalformedKeyringException("no MAC");
119
    if (! entry.properties.containsKey("maclen"))
133
      }
120
      throw new MalformedKeyringException("no MAC length");
134
    if (!entry.properties.containsKey("maclen"))
121
    if (! entry.properties.containsKey("salt"))
135
      {
122
      throw new MalformedKeyringException("no salt");
136
        throw new MalformedKeyringException("no MAC length");
137
      }
138
    if (!entry.properties.containsKey("salt"))
139
      {
140
        throw new MalformedKeyringException("no salt");
141
      }
142
    return entry;
123
    return entry;
143
  }
124
  }
144
125
145
  // Instance methods
146
  // -------------------------------------------------------------------------
147
148
  public void verify(char[] password)
126
  public void verify(char[] password)
149
  {
127
  {
150
    if (Configuration.DEBUG)
128
    if (Configuration.DEBUG)
Lines 153-159 Link Here
153
      {
131
      {
154
        if (Configuration.DEBUG)
132
        if (Configuration.DEBUG)
155
          log.fine("payload to verify: " + Util.dumpString(payload));
133
          log.fine("payload to verify: " + Util.dumpString(payload));
156
        long tt = - System.currentTimeMillis();
134
        long tt = -System.currentTimeMillis();
157
        IMac m = null;
135
        IMac m = null;
158
        try
136
        try
159
          {
137
          {
Lines 163-179 Link Here
163
          {
141
          {
164
            throw new IllegalArgumentException(x.toString(), x);
142
            throw new IllegalArgumentException(x.toString(), x);
165
          }
143
          }
166
167
        int limit = payload.length - m.macSize();
144
        int limit = payload.length - m.macSize();
168
        m.update(payload, 0, limit);
145
        m.update(payload, 0, limit);
169
        byte[] macValue = new byte[m.macSize()];
146
        byte[] macValue = new byte[m.macSize()];
170
        System.arraycopy(payload, payload.length - macValue.length, macValue, 0,
147
        System.arraycopy(payload, payload.length - macValue.length, macValue,
171
                         macValue.length);
148
                         0, macValue.length);
172
        if (! Arrays.equals(macValue, m.digest()))
149
        if (! Arrays.equals(macValue, m.digest()))
173
          throw new IllegalArgumentException("MAC verification failed");
150
          throw new IllegalArgumentException("MAC verification failed");
174
175
        setMasked(false);
151
        setMasked(false);
176
177
        ByteArrayInputStream bais;
152
        ByteArrayInputStream bais;
178
        try
153
        try
179
          {
154
          {
Lines 185-198 Link Here
185
          {
160
          {
186
            throw new IllegalArgumentException("malformed keyring fragment");
161
            throw new IllegalArgumentException("malformed keyring fragment");
187
          }
162
          }
188
189
        tt += System.currentTimeMillis();
163
        tt += System.currentTimeMillis();
190
        if (Configuration.DEBUG)
164
        if (Configuration.DEBUG)
191
          log.fine("Verified in " + tt + "ms.");
165
          log.fine("Verified in " + tt + "ms.");
192
      }
166
      }
193
    else if (Configuration.DEBUG)
167
    else if (Configuration.DEBUG)
194
      log.fine("Skip verification; " + (isMasked() ? "null payload" : "unmasked"));
168
      log.fine("Skip verification; "
195
169
               + (isMasked() ? "null payload" : "unmasked"));
196
    if (Configuration.DEBUG)
170
    if (Configuration.DEBUG)
197
      log.exiting(this.getClass().getName(), "verify");
171
      log.exiting(this.getClass().getName(), "verify");
198
  }
172
  }
Lines 201-212 Link Here
201
  {
175
  {
202
    if (Configuration.DEBUG)
176
    if (Configuration.DEBUG)
203
      log.entering(this.getClass().getName(), "authenticate");
177
      log.entering(this.getClass().getName(), "authenticate");
204
    long tt = - System.currentTimeMillis();
178
    long tt = -System.currentTimeMillis();
205
    long t1 = - System.currentTimeMillis();
179
    long t1 = -System.currentTimeMillis();
206
207
    if (isMasked())
180
    if (isMasked())
208
      throw new IllegalStateException("entry is masked");
181
      throw new IllegalStateException("entry is masked");
209
210
    byte[] salt = new byte[8];
182
    byte[] salt = new byte[8];
211
    PRNG.getInstance().nextBytes(salt);
183
    PRNG.getInstance().nextBytes(salt);
212
    t1 += System.currentTimeMillis();
184
    t1 += System.currentTimeMillis();
Lines 222-240 Link Here
222
        Entry entry = (Entry) it.next();
194
        Entry entry = (Entry) it.next();
223
        if (Configuration.DEBUG)
195
        if (Configuration.DEBUG)
224
          log.fine("-- About to authenticate one " + entry);
196
          log.fine("-- About to authenticate one " + entry);
225
        t1 = - System.currentTimeMillis();
197
        t1 = -System.currentTimeMillis();
226
        entry.encode(out2);
198
        entry.encode(out2);
227
        t1 += System.currentTimeMillis();
199
        t1 += System.currentTimeMillis();
228
        if (Configuration.DEBUG)
200
        if (Configuration.DEBUG)
229
          log.fine("-- Authenticated an Entry in " + t1 + "ms.");
201
          log.fine("-- Authenticated an Entry in " + t1 + "ms.");
230
      }
202
      }
231
    bout.write(m.digest());
203
    bout.write(m.digest());
232
233
    payload = bout.toByteArray();
204
    payload = bout.toByteArray();
234
    if (Configuration.DEBUG)
205
    if (Configuration.DEBUG)
235
      log.fine("authenticated payload: " + Util.dumpString(payload));
206
      log.fine("authenticated payload: " + Util.dumpString(payload));
236
    setMasked(true);
207
    setMasked(true);
237
238
    tt += System.currentTimeMillis();
208
    tt += System.currentTimeMillis();
239
    if (Configuration.DEBUG)
209
    if (Configuration.DEBUG)
240
      {
210
      {
Lines 258-266 Link Here
258
      }
228
      }
259
  }
229
  }
260
230
261
  // Own methods.
262
  // ------------------------------------------------------------------------
263
264
  private IMac getMac(char[] password) throws MalformedKeyringException
231
  private IMac getMac(char[] password) throws MalformedKeyringException
265
  {
232
  {
266
    if (Configuration.DEBUG)
233
    if (Configuration.DEBUG)
Lines 268-284 Link Here
268
    String saltString = properties.get("salt");
235
    String saltString = properties.get("salt");
269
    if (saltString == null)
236
    if (saltString == null)
270
      throw new MalformedKeyringException("no salt");
237
      throw new MalformedKeyringException("no salt");
271
272
    byte[] salt = Util.toBytesFromString(saltString);
238
    byte[] salt = Util.toBytesFromString(saltString);
273
    String macAlgorithm = properties.get("mac");
239
    String macAlgorithm = properties.get("mac");
274
    IMac mac = MacFactory.getInstance(macAlgorithm);
240
    IMac mac = MacFactory.getInstance(macAlgorithm);
275
    if (mac == null)
241
    if (mac == null)
276
      throw new MalformedKeyringException("no such mac: " + macAlgorithm);
242
      throw new MalformedKeyringException("no such mac: " + macAlgorithm);
277
278
    String macLenString = properties.get("maclen");
243
    String macLenString = properties.get("maclen");
279
    if (macLenString == null)
244
    if (macLenString == null)
280
      throw new MalformedKeyringException("no MAC length");
245
      throw new MalformedKeyringException("no MAC length");
281
282
    int maclen;
246
    int maclen;
283
    try
247
    try
284
      {
248
      {
Lines 288-301 Link Here
288
      {
252
      {
289
        throw new MalformedKeyringException("bad MAC length");
253
        throw new MalformedKeyringException("bad MAC length");
290
      }
254
      }
291
292
    HashMap pbAttr = new HashMap();
255
    HashMap pbAttr = new HashMap();
293
    pbAttr.put(IPBE.PASSWORD, password);
256
    pbAttr.put(IPBE.PASSWORD, password);
294
    pbAttr.put(IPBE.SALT, salt);
257
    pbAttr.put(IPBE.SALT, salt);
295
    pbAttr.put(IPBE.ITERATION_COUNT, ITERATION_COUNT);
258
    pbAttr.put(IPBE.ITERATION_COUNT, ITERATION_COUNT);
296
    IRandom kdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA");
259
    IRandom kdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA");
297
    kdf.init(pbAttr);
260
    kdf.init(pbAttr);
298
299
    int keylen = mac.macSize();
261
    int keylen = mac.macSize();
300
    byte[] dk = new byte[keylen];
262
    byte[] dk = new byte[keylen];
301
    try
263
    try
Lines 306-312 Link Here
306
      {
268
      {
307
        throw new Error(shouldNotHappen.toString());
269
        throw new Error(shouldNotHappen.toString());
308
      }
270
      }
309
310
    HashMap macAttr = new HashMap();
271
    HashMap macAttr = new HashMap();
311
    macAttr.put(IMac.MAC_KEY_MATERIAL, dk);
272
    macAttr.put(IMac.MAC_KEY_MATERIAL, dk);
312
    macAttr.put(IMac.TRUNCATED_SIZE, Integer.valueOf(maclen));
273
    macAttr.put(IMac.TRUNCATED_SIZE, Integer.valueOf(maclen));
(-)PasswordEncryptedEntry.java (-62 / +27 lines)
Lines 67-93 Link Here
67
/**
67
/**
68
 * An envelope that is encrypted with a password-derived key.
68
 * An envelope that is encrypted with a password-derived key.
69
 */
69
 */
70
public class PasswordEncryptedEntry extends MaskableEnvelopeEntry implements
70
public class PasswordEncryptedEntry
71
    PasswordProtectedEntry, Registry
71
    extends MaskableEnvelopeEntry
72
    implements PasswordProtectedEntry, Registry
72
{
73
{
73
  // Constants and fields.
74
  // ------------------------------------------------------------------------
75
76
  private static final Logger log = Logger.getLogger(PasswordEncryptedEntry.class.getName());
74
  private static final Logger log = Logger.getLogger(PasswordEncryptedEntry.class.getName());
77
  public static final int TYPE = 1;
75
  public static final int TYPE = 1;
78
76
79
  // Constructors.
80
  // ------------------------------------------------------------------------
81
82
  public PasswordEncryptedEntry(String cipher, String mode, int keylen,
77
  public PasswordEncryptedEntry(String cipher, String mode, int keylen,
83
                                Properties properties)
78
                                Properties properties)
84
  {
79
  {
85
    super(TYPE, properties);
80
    super(TYPE, properties);
86
    if ((cipher == null || cipher.length() == 0)
81
    if ((cipher == null || cipher.length() == 0)
87
        || (mode == null || mode.length() == 0))
82
        || (mode == null || mode.length() == 0))
88
      {
83
      throw new IllegalArgumentException("cipher nor mode can be empty");
89
        throw new IllegalArgumentException("cipher nor mode can be empty");
90
      }
91
    this.properties.put("cipher", cipher);
84
    this.properties.put("cipher", cipher);
92
    this.properties.put("mode", mode);
85
    this.properties.put("mode", mode);
93
    this.properties.put("keylen", String.valueOf(keylen));
86
    this.properties.put("keylen", String.valueOf(keylen));
Lines 100-108 Link Here
100
    setMasked(true);
93
    setMasked(true);
101
  }
94
  }
102
95
103
  // Class methods.
104
  // ------------------------------------------------------------------------
105
106
  public static PasswordEncryptedEntry decode(DataInputStream in,
96
  public static PasswordEncryptedEntry decode(DataInputStream in,
107
                                              char[] password)
97
                                              char[] password)
108
      throws IOException
98
      throws IOException
Lines 127-135 Link Here
127
    return entry;
117
    return entry;
128
  }
118
  }
129
119
130
  // Instance methods.
131
  // ------------------------------------------------------------------------
132
133
  public void decrypt(char[] password) throws IllegalArgumentException,
120
  public void decrypt(char[] password) throws IllegalArgumentException,
134
      WrongPaddingException
121
      WrongPaddingException
135
  {
122
  {
Lines 137-143 Link Here
137
      log.entering(this.getClass().getName(), "decrypt");
124
      log.entering(this.getClass().getName(), "decrypt");
138
    if (isMasked() && payload != null)
125
    if (isMasked() && payload != null)
139
      {
126
      {
140
        long tt = - System.currentTimeMillis();
127
        long tt = -System.currentTimeMillis();
141
        IMode mode = getMode(password, IMode.DECRYPTION);
128
        IMode mode = getMode(password, IMode.DECRYPTION);
142
        IPad padding = PadFactory.getInstance("PKCS7");
129
        IPad padding = PadFactory.getInstance("PKCS7");
143
        padding.init(mode.currentBlockSize());
130
        padding.init(mode.currentBlockSize());
Lines 149-159 Link Here
149
            count += mode.currentBlockSize();
136
            count += mode.currentBlockSize();
150
          }
137
          }
151
        int padlen = padding.unpad(buf, 0, buf.length);
138
        int padlen = padding.unpad(buf, 0, buf.length);
152
153
        setMasked(false);
139
        setMasked(false);
154
140
        int len = buf.length - padlen;
155
        ByteArrayInputStream baos = new ByteArrayInputStream(buf, 0,
141
        ByteArrayInputStream baos = new ByteArrayInputStream(buf, 0, len);
156
                                                             buf.length - padlen);
157
        DataInputStream in = new DataInputStream(baos);
142
        DataInputStream in = new DataInputStream(baos);
158
        try
143
        try
159
          {
144
          {
Lines 168-174 Link Here
168
      }
153
      }
169
    else if (Configuration.DEBUG)
154
    else if (Configuration.DEBUG)
170
      log.fine("Skip decryption; " + (isMasked() ? "null payload" : "unmasked"));
155
      log.fine("Skip decryption; " + (isMasked() ? "null payload" : "unmasked"));
171
172
    if (Configuration.DEBUG)
156
    if (Configuration.DEBUG)
173
      log.exiting(this.getClass().getName(), "decrypt");
157
      log.exiting(this.getClass().getName(), "decrypt");
174
  }
158
  }
Lines 177-185 Link Here
177
  {
161
  {
178
    if (Configuration.DEBUG)
162
    if (Configuration.DEBUG)
179
      log.entering(this.getClass().getName(), "encrypt", String.valueOf(password));
163
      log.entering(this.getClass().getName(), "encrypt", String.valueOf(password));
180
    long tt = - System.currentTimeMillis();
164
    long tt = -System.currentTimeMillis();
181
    long t1 = - System.currentTimeMillis();
165
    long t1 = -System.currentTimeMillis();
182
183
    byte[] salt = new byte[8];
166
    byte[] salt = new byte[8];
184
    PRNG.getInstance().nextBytes(salt);
167
    PRNG.getInstance().nextBytes(salt);
185
    t1 += System.currentTimeMillis();
168
    t1 += System.currentTimeMillis();
Lines 196-202 Link Here
196
        Entry entry = (Entry) it.next();
179
        Entry entry = (Entry) it.next();
197
        if (Configuration.DEBUG)
180
        if (Configuration.DEBUG)
198
          log.fine("-- About to encode one " + entry);
181
          log.fine("-- About to encode one " + entry);
199
        t1 = - System.currentTimeMillis();
182
        t1 = -System.currentTimeMillis();
200
        entry.encode(out2);
183
        entry.encode(out2);
201
        t1 += System.currentTimeMillis();
184
        t1 += System.currentTimeMillis();
202
        if (Configuration.DEBUG)
185
        if (Configuration.DEBUG)
Lines 216-224 Link Here
216
        count += mode.currentBlockSize();
199
        count += mode.currentBlockSize();
217
      }
200
      }
218
    mode.update(lastBlock, 0, payload, count);
201
    mode.update(lastBlock, 0, payload, count);
219
220
    setMasked(true);
202
    setMasked(true);
221
222
    tt += System.currentTimeMillis();
203
    tt += System.currentTimeMillis();
223
    if (Configuration.DEBUG)
204
    if (Configuration.DEBUG)
224
      {
205
      {
Lines 243-298 Link Here
243
      }
224
      }
244
  }
225
  }
245
226
246
  // Own methods.
247
  // ------------------------------------------------------------------------
248
249
  private IMode getMode(char[] password, int state)
227
  private IMode getMode(char[] password, int state)
250
  {
228
  {
251
    String s = properties.get("salt");
229
    String s = properties.get("salt");
252
    if (s == null)
230
    if (s == null)
253
      {
231
      throw new IllegalArgumentException("no salt");
254
        throw new IllegalArgumentException("no salt");
255
      }
256
    byte[] salt = Util.toBytesFromString(s);
232
    byte[] salt = Util.toBytesFromString(s);
257
    IBlockCipher cipher = CipherFactory.getInstance(properties.get("cipher"));
233
    IBlockCipher cipher = CipherFactory.getInstance(properties.get("cipher"));
258
    if (cipher == null)
234
    if (cipher == null)
259
      {
235
      throw new IllegalArgumentException("no such cipher: "
260
        throw new IllegalArgumentException("no such cipher: "
236
                                         + properties.get("cipher"));
261
                                           + properties.get("cipher"));
262
      }
263
    int blockSize = cipher.defaultBlockSize();
237
    int blockSize = cipher.defaultBlockSize();
264
    if (properties.containsKey("block-size"))
238
    if (properties.containsKey("block-size"))
265
      {
239
      try
266
        try
240
        {
267
          {
241
          blockSize = Integer.parseInt(properties.get("block-size"));
268
            blockSize = Integer.parseInt(properties.get("block-size"));
242
        }
269
          }
243
      catch (NumberFormatException nfe)
270
        catch (NumberFormatException nfe)
244
        {
271
          {
245
          throw new IllegalArgumentException("bad block size: "
272
            throw new IllegalArgumentException("bad block size: "
246
                                             + nfe.getMessage());
273
                                               + nfe.getMessage());
247
        }
274
          }
248
    String modeName = properties.get("mode");
275
      }
249
    IMode mode = ModeFactory.getInstance(modeName, cipher, blockSize);
276
    IMode mode = ModeFactory.getInstance(properties.get("mode"), cipher,
277
                                         blockSize);
278
    if (mode == null)
250
    if (mode == null)
279
      {
251
      throw new IllegalArgumentException("no such mode: " + modeName);
280
        throw new IllegalArgumentException("no such mode: "
281
                                           + properties.get("mode"));
282
      }
283
284
    HashMap pbAttr = new HashMap();
252
    HashMap pbAttr = new HashMap();
285
    pbAttr.put(IPBE.PASSWORD, password);
253
    pbAttr.put(IPBE.PASSWORD, password);
286
    pbAttr.put(IPBE.SALT, salt);
254
    pbAttr.put(IPBE.SALT, salt);
287
    pbAttr.put(IPBE.ITERATION_COUNT, ITERATION_COUNT);
255
    pbAttr.put(IPBE.ITERATION_COUNT, ITERATION_COUNT);
288
    IRandom kdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA");
256
    IRandom kdf = PRNGFactory.getInstance("PBKDF2-HMAC-SHA");
289
    kdf.init(pbAttr);
257
    kdf.init(pbAttr);
290
291
    int keylen = 0;
258
    int keylen = 0;
292
    if (!properties.containsKey("keylen"))
259
    if (! properties.containsKey("keylen"))
293
      {
260
      throw new IllegalArgumentException("no key length");
294
        throw new IllegalArgumentException("no key length");
295
      }
296
    try
261
    try
297
      {
262
      {
298
        keylen = Integer.parseInt(properties.get("keylen"));
263
        keylen = Integer.parseInt(properties.get("keylen"));
(-)PasswordProtectedEntry.java (-11 / +2 lines)
Lines 43-63 Link Here
43
43
44
public interface PasswordProtectedEntry
44
public interface PasswordProtectedEntry
45
{
45
{
46
46
  /** The iteration count for password-based KDFs. */
47
  // Constant.
48
  // ------------------------------------------------------------------------
49
50
  /**
51
   * The iteration count for password-based KDFs.
52
   */
53
  Integer ITERATION_COUNT = Integer.valueOf(1000);
47
  Integer ITERATION_COUNT = Integer.valueOf(1000);
54
48
55
  // Method.
56
  // ------------------------------------------------------------------------
57
58
  /**
49
  /**
59
   * Encodes this entry, protected by a password.
50
   * Encodes this entry, protected by a password.
60
   *
51
   * 
61
   * @param out The output stream to encode to.
52
   * @param out The output stream to encode to.
62
   * @param password The password.
53
   * @param password The password.
63
   * @throws IOException If an I/O error occurs.
54
   * @throws IOException If an I/O error occurs.
(-)PrimitiveEntry.java (-28 / +12 lines)
Lines 43-77 Link Here
43
/**
43
/**
44
 * A primitive entry is an entry that contains a single cryptographic entity.
44
 * A primitive entry is an entry that contains a single cryptographic entity.
45
 */
45
 */
46
public abstract class PrimitiveEntry extends Entry
46
public abstract class PrimitiveEntry
47
    extends Entry
47
{
48
{
48
49
  // Fields.
50
  // ------------------------------------------------------------------------
51
52
  /** The creation date. */
49
  /** The creation date. */
53
  protected Date creationDate;
50
  protected Date creationDate;
54
51
55
  // Constructor.
56
  // ------------------------------------------------------------------------
57
58
  protected PrimitiveEntry(int type, Date creationDate, Properties properties)
52
  protected PrimitiveEntry(int type, Date creationDate, Properties properties)
59
  {
53
  {
60
    super(type, properties);
54
    super(type, properties);
61
    if (creationDate == null)
55
    if (creationDate == null)
62
      {
56
      this.creationDate = new Date();
63
        this.creationDate = new Date();
64
      }
65
    else
57
    else
66
      {
58
      this.creationDate = (Date) creationDate.clone();
67
        this.creationDate = (Date) creationDate.clone();
59
    if (! this.properties.containsKey("alias")
68
      }
69
    if (!this.properties.containsKey("alias")
70
        || this.properties.get("alias").length() == 0)
60
        || this.properties.get("alias").length() == 0)
71
      {
61
      throw new IllegalArgumentException("primitive entries MUST have an alias");
72
        throw new IllegalArgumentException("primitive entries MUST have an alias");
62
    this.properties.put("creation-date",
73
      }
63
                        String.valueOf(this.creationDate.getTime()));
74
    this.properties.put("creation-date", String.valueOf(this.creationDate.getTime()));
75
  }
64
  }
76
65
77
  protected PrimitiveEntry(int type)
66
  protected PrimitiveEntry(int type)
Lines 79-90 Link Here
79
    super(type);
68
    super(type);
80
  }
69
  }
81
70
82
  // Instance method.
83
  // ------------------------------------------------------------------------
84
85
  /**
71
  /**
86
   * Returns the alias of this primitive entry.
72
   * Returns the alias of this primitive entry.
87
   *
73
   * 
88
   * @return The alias.
74
   * @return The alias.
89
   */
75
   */
90
  public String getAlias()
76
  public String getAlias()
Lines 94-100 Link Here
94
80
95
  /**
81
  /**
96
   * Returns the creation date of this primitive entry.
82
   * Returns the creation date of this primitive entry.
97
   *
83
   * 
98
   * @return The creation date.
84
   * @return The creation date.
99
   */
85
   */
100
  public Date getCreationDate()
86
  public Date getCreationDate()
Lines 104-110 Link Here
104
90
105
  public boolean equals(Object object)
91
  public boolean equals(Object object)
106
  {
92
  {
107
    if (!getClass().equals(object.getClass()))
93
    if (! getClass().equals(object.getClass()))
108
      return false;
94
      return false;
109
    return getAlias().equals(((PrimitiveEntry) object).getAlias());
95
    return getAlias().equals(((PrimitiveEntry) object).getAlias());
110
  }
96
  }
Lines 113-121 Link Here
113
  {
99
  {
114
    String s = properties.get("creation-date");
100
    String s = properties.get("creation-date");
115
    if (s == null)
101
    if (s == null)
116
      {
102
      throw new MalformedKeyringException("no creation date");
117
        throw new MalformedKeyringException("no creation date");
118
      }
119
    try
103
    try
120
      {
104
      {
121
        creationDate = new Date(Long.parseLong(s));
105
        creationDate = new Date(Long.parseLong(s));
(-)PrivateKeyEntry.java (-23 / +3 lines)
Lines 59-78 Link Here
59
public final class PrivateKeyEntry
59
public final class PrivateKeyEntry
60
    extends PrimitiveEntry
60
    extends PrimitiveEntry
61
{
61
{
62
  // Constants and variables
63
  // -------------------------------------------------------------------------
64
65
  public static final int TYPE = 7;
62
  public static final int TYPE = 7;
66
67
  /** The key. */
63
  /** The key. */
68
  private Key key;
64
  private Key key;
69
65
70
  // Constructor(s)
71
  // -------------------------------------------------------------------------
72
73
  /**
66
  /**
74
   * Creates a new key entry.
67
   * Creates a new key entry.
75
   *
68
   * 
76
   * @param key The key.
69
   * @param key The key.
77
   * @param creationDate The entry creation date.
70
   * @param creationDate The entry creation date.
78
   * @param properties The entry properties.
71
   * @param properties The entry properties.
Lines 81-93 Link Here
81
  public PrivateKeyEntry(Key key, Date creationDate, Properties properties)
74
  public PrivateKeyEntry(Key key, Date creationDate, Properties properties)
82
  {
75
  {
83
    super(TYPE, creationDate, properties);
76
    super(TYPE, creationDate, properties);
84
85
    if (key == null)
77
    if (key == null)
86
      throw new IllegalArgumentException("no private key");
78
      throw new IllegalArgumentException("no private key");
87
88
    if (! (key instanceof PrivateKey) && ! (key instanceof GnuSecretKey))
79
    if (! (key instanceof PrivateKey) && ! (key instanceof GnuSecretKey))
89
      throw new IllegalArgumentException("not a private or secret key");
80
      throw new IllegalArgumentException("not a private or secret key");
90
91
    this.key = key;
81
    this.key = key;
92
  }
82
  }
93
83
Lines 96-104 Link Here
96
    super(TYPE);
86
    super(TYPE);
97
  }
87
  }
98
88
99
  // Class methods
100
  // -------------------------------------------------------------------------
101
102
  public static PrivateKeyEntry decode(DataInputStream in) throws IOException
89
  public static PrivateKeyEntry decode(DataInputStream in) throws IOException
103
  {
90
  {
104
    PrivateKeyEntry entry = new PrivateKeyEntry();
91
    PrivateKeyEntry entry = new PrivateKeyEntry();
Lines 106-112 Link Here
106
    String type = entry.properties.get("type");
93
    String type = entry.properties.get("type");
107
    if (type == null)
94
    if (type == null)
108
      throw new MalformedKeyringException("no key type");
95
      throw new MalformedKeyringException("no key type");
109
110
    if (type.equalsIgnoreCase("RAW-DSS"))
96
    if (type.equalsIgnoreCase("RAW-DSS"))
111
      {
97
      {
112
        IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
98
        IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
Lines 135-141 Link Here
135
        catch (Exception ignored)
121
        catch (Exception ignored)
136
          {
122
          {
137
          }
123
          }
138
139
        if (entry.key == null)
124
        if (entry.key == null)
140
          {
125
          {
141
            try
126
            try
Lines 147-169 Link Here
147
            catch (Exception ignored)
132
            catch (Exception ignored)
148
              {
133
              {
149
              }
134
              }
150
151
            if (entry.key == null)
135
            if (entry.key == null)
152
              throw new MalformedKeyringException("could not decode PKCS#8 key");
136
              throw new MalformedKeyringException("could not decode PKCS#8 key");
153
          }
137
          }
154
      }
138
      }
155
    else
139
    else
156
      throw new MalformedKeyringException("unsupported key type " + type);
140
      throw new MalformedKeyringException("unsupported key type " + type);
157
158
    return entry;
141
    return entry;
159
  }
142
  }
160
143
161
  // Instance methods
162
  // -------------------------------------------------------------------------
163
164
  /**
144
  /**
165
   * Returns this entry's key.
145
   * Returns this entry's key.
166
   *
146
   * 
167
   * @return The key.
147
   * @return The key.
168
   */
148
   */
169
  public Key getKey()
149
  public Key getKey()
Lines 209-214 Link Here
209
  public String toString()
189
  public String toString()
210
  {
190
  {
211
    return "PrivateKeyEntry{key="
191
    return "PrivateKeyEntry{key="
212
        + (key == null ? "-" : key.getClass().getName()) + "}";
192
           + (key == null ? "-" : key.getClass().getName()) + "}";
213
  }
193
  }
214
}
194
}
(-)Properties.java (-46 / +22 lines)
Lines 42-68 Link Here
42
import java.io.DataInputStream;
42
import java.io.DataInputStream;
43
import java.io.DataOutputStream;
43
import java.io.DataOutputStream;
44
import java.io.IOException;
44
import java.io.IOException;
45
46
import java.util.HashMap;
45
import java.util.HashMap;
47
import java.util.Iterator;
46
import java.util.Iterator;
48
import java.util.Map;
47
import java.util.Map;
49
48
50
/**
49
/**
51
 * A set of <code>(name =&gt; value)</code> pairs used in keyring entries.
50
 * A set of <code>(name =&gt; value)</code> pairs used in keyring entries.
52
 * Keys and values are simple strings, with the key never being empty and
51
 * Keys and values are simple strings, with the key never being empty and always
53
 * always treated case-insensitively.
52
 * treated case-insensitively.
54
 */
53
 */
55
public class Properties implements Cloneable
54
public class Properties
55
    implements Cloneable
56
{
56
{
57
58
  // Field.
59
  // ------------------------------------------------------------------------
60
61
  private HashMap props;
57
  private HashMap props;
62
58
63
  // Constructor.
64
  // ------------------------------------------------------------------------
65
66
  /**
59
  /**
67
   * Creates a new properties object.
60
   * Creates a new properties object.
68
   */
61
   */
Lines 71-79 Link Here
71
    props = new HashMap();
64
    props = new HashMap();
72
  }
65
  }
73
66
74
  // Instance methods.
75
  // ------------------------------------------------------------------------
76
77
  /**
67
  /**
78
   * Removes all properties from this object.
68
   * Removes all properties from this object.
79
   */
69
   */
Lines 84-90 Link Here
84
74
85
  /**
75
  /**
86
   * Creates a copy of this properties object.
76
   * Creates a copy of this properties object.
87
   *
77
   * 
88
   * @return The copy.
78
   * @return The copy.
89
   */
79
   */
90
  public Object clone()
80
  public Object clone()
Lines 96-181 Link Here
96
86
97
  /**
87
  /**
98
   * Tests if this object contains a given property name.
88
   * Tests if this object contains a given property name.
99
   *
89
   * 
100
   * @param key The key to test.
90
   * @param key The key to test.
101
   * @return True if this object contains the given key.
91
   * @return True if this object contains the given key.
102
   */
92
   */
103
  public boolean containsKey(String key)
93
  public boolean containsKey(String key)
104
  {
94
  {
105
    if (key == null || key.length() == 0)
95
    if (key == null || key.length() == 0)
106
      {
96
      return false;
107
        return false;
108
      }
109
    return props.containsKey(canonicalize(key));
97
    return props.containsKey(canonicalize(key));
110
  }
98
  }
111
99
112
  /**
100
  /**
113
   * Tests if this object contains a given property value.
101
   * Tests if this object contains a given property value.
114
   *
102
   * 
115
   * @param value The value to test.
103
   * @param value The value to test.
116
   * @return True if this object contains the given value.
104
   * @return True if this object contains the given value.
117
   */
105
   */
118
  public boolean containsValue(String value)
106
  public boolean containsValue(String value)
119
  {
107
  {
120
    if (value == null)
108
    if (value == null)
121
      {
109
      return false;
122
        return false;
123
      }
124
    return props.containsValue(value);
110
    return props.containsValue(value);
125
  }
111
  }
126
112
127
  /**
113
  /**
128
   * Adds a new property to this object.
114
   * Adds a new property to this object.
129
   *
115
   * 
130
   * @param key The key, which can neither be null nor empty.
116
   * @param key The key, which can neither be null nor empty.
131
   * @param value The value, which cannot be null.
117
   * @param value The value, which cannot be null.
132
   * @return The old value mapped by the key, if any.
118
   * @return The old value mapped by the key, if any.
133
   * @throws IllegalArgumentException If either the key or value parameter
119
   * @throws IllegalArgumentException If either the key or value parameter is
134
120
   *           null, or if the key is empty.
135
   *   is null, or if the key is empty.
136
   */
121
   */
137
  public String put(String key, String value)
122
  public String put(String key, String value)
138
  {
123
  {
139
    if (key == null || value == null || key.length() == 0)
124
    if (key == null || value == null || key.length() == 0)
140
      {
125
      throw new IllegalArgumentException("key nor value can be null");
141
        throw new IllegalArgumentException("key nor value can be null");
142
      }
143
    return (String) props.put(canonicalize(key), value);
126
    return (String) props.put(canonicalize(key), value);
144
  }
127
  }
145
128
146
  /**
129
  /**
147
   * Returns the value mapped by the given key, or null if there is no
130
   * Returns the value mapped by the given key, or null if there is no such
148
   * such mapping.
131
   * mapping.
149
   *
132
   * 
150
   * @param key
133
   * @param key
151
   */
134
   */
152
  public String get(String key)
135
  public String get(String key)
153
  {
136
  {
154
    if (key == null || key.length() == 0)
137
    if (key == null || key.length() == 0)
155
      {
138
      return null;
156
        return null;
157
      }
158
    return (String) props.get(canonicalize(key));
139
    return (String) props.get(canonicalize(key));
159
  }
140
  }
160
141
161
  /**
142
  /**
162
   * Removes a key and its value from this object.
143
   * Removes a key and its value from this object.
163
   *
144
   * 
164
   * @param key The key of the property to remove.
145
   * @param key The key of the property to remove.
165
   * @return The old value mapped by the key, if any.
146
   * @return The old value mapped by the key, if any.
166
   */
147
   */
167
  public String remove(String key)
148
  public String remove(String key)
168
  {
149
  {
169
    if (key == null || key.length() == 0)
150
    if (key == null || key.length() == 0)
170
      {
151
      return null;
171
        return null;
172
      }
173
    return (String) props.remove(canonicalize(key));
152
    return (String) props.remove(canonicalize(key));
174
  }
153
  }
175
154
176
  /**
155
  /**
177
   * Decodes a set of properties from the given input stream.
156
   * Decodes a set of properties from the given input stream.
178
   *
157
   * 
179
   * @param in The input stream.
158
   * @param in The input stream.
180
   * @throws IOException If an I/O error occurs.
159
   * @throws IOException If an I/O error occurs.
181
   */
160
   */
Lines 184-190 Link Here
184
    int len = in.readInt();
163
    int len = in.readInt();
185
    MeteredInputStream min = new MeteredInputStream(in, len);
164
    MeteredInputStream min = new MeteredInputStream(in, len);
186
    DataInputStream in2 = new DataInputStream(min);
165
    DataInputStream in2 = new DataInputStream(min);
187
    while (!min.limitReached())
166
    while (! min.limitReached())
188
      {
167
      {
189
        String name = in2.readUTF();
168
        String name = in2.readUTF();
190
        String value = in2.readUTF();
169
        String value = in2.readUTF();
Lines 194-200 Link Here
194
173
195
  /**
174
  /**
196
   * Encodes this set of properties to the given output stream.
175
   * Encodes this set of properties to the given output stream.
197
   *
176
   * 
198
   * @param out The output stream to encode to.
177
   * @param out The output stream to encode to.
199
   * @throws IOException If an I/O error occurs.
178
   * @throws IOException If an I/O error occurs.
200
   */
179
   */
Lines 217-225 Link Here
217
    return props.toString();
196
    return props.toString();
218
  }
197
  }
219
198
220
  // Own methods.
221
  // ------------------------------------------------------------------------
222
223
  private String canonicalize(String key)
199
  private String canonicalize(String key)
224
  {
200
  {
225
    return key.toLowerCase();
201
    return key.toLowerCase();
(-)PublicKeyEntry.java (-36 / +9 lines)
Lines 51-77 Link Here
51
import java.security.spec.X509EncodedKeySpec;
51
import java.security.spec.X509EncodedKeySpec;
52
import java.util.Date;
52
import java.util.Date;
53
53
54
public final class PublicKeyEntry extends PrimitiveEntry
54
public final class PublicKeyEntry
55
    extends PrimitiveEntry
55
{
56
{
56
57
  // Constants and fields.
58
  // ------------------------------------------------------------------------
59
60
  public static final int TYPE = 6;
57
  public static final int TYPE = 6;
61
62
  private PublicKey key;
58
  private PublicKey key;
63
59
64
  // Constructor.
65
  // ------------------------------------------------------------------------
66
67
  public PublicKeyEntry(PublicKey key, Date creationDate, Properties properties)
60
  public PublicKeyEntry(PublicKey key, Date creationDate, Properties properties)
68
  {
61
  {
69
    super(TYPE, creationDate, properties);
62
    super(TYPE, creationDate, properties);
70
71
    if (key == null)
63
    if (key == null)
72
      {
64
      throw new IllegalArgumentException("no key specified");
73
        throw new IllegalArgumentException("no key specified");
74
      }
75
    this.key = key;
65
    this.key = key;
76
  }
66
  }
77
67
Lines 80-97 Link Here
80
    super(TYPE);
70
    super(TYPE);
81
  }
71
  }
82
72
83
  // Class method.
84
  // ------------------------------------------------------------------------
85
86
  public static PublicKeyEntry decode(DataInputStream in) throws IOException
73
  public static PublicKeyEntry decode(DataInputStream in) throws IOException
87
  {
74
  {
88
    PublicKeyEntry entry = new PublicKeyEntry();
75
    PublicKeyEntry entry = new PublicKeyEntry();
89
    entry.defaultDecode(in);
76
    entry.defaultDecode(in);
90
    String type = entry.properties.get("type");
77
    String type = entry.properties.get("type");
91
    if (type == null)
78
    if (type == null)
92
      {
79
      throw new MalformedKeyringException("no key type");
93
        throw new MalformedKeyringException("no key type");
94
      }
95
    if (type.equalsIgnoreCase("RAW-DSS"))
80
    if (type.equalsIgnoreCase("RAW-DSS"))
96
      {
81
      {
97
        IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
82
        IKeyPairCodec coder = KeyPairCodecFactory.getInstance("dss");
Lines 122-154 Link Here
122
            try
107
            try
123
              {
108
              {
124
                KeyFactory kf = KeyFactory.getInstance("DSA");
109
                KeyFactory kf = KeyFactory.getInstance("DSA");
125
                entry.key = kf.generatePublic(new X509EncodedKeySpec(
110
                entry.key = kf.generatePublic(new X509EncodedKeySpec(entry.payload));
126
                                                                     entry.payload));
127
              }
111
              }
128
            catch (Exception x)
112
            catch (Exception x)
129
              {
113
              {
130
              }
114
              }
131
            if (entry.key == null)
115
            if (entry.key == null)
132
              {
116
              throw new MalformedKeyringException("could not decode X.509 key");
133
                throw new MalformedKeyringException(
134
                                                    "could not decode X.509 key");
135
              }
136
          }
117
          }
137
      }
118
      }
138
    else
119
    else
139
      {
120
      throw new MalformedKeyringException("unsupported public key type: " + type);
140
        throw new MalformedKeyringException("unsupported public key type: "
141
                                            + type);
142
      }
143
    return entry;
121
    return entry;
144
  }
122
  }
145
123
146
  // Instance methods.
147
  // ------------------------------------------------------------------------
148
149
  /**
124
  /**
150
   * Returns the public key.
125
   * Returns the public key.
151
   *
126
   * 
152
   * @return The public key.
127
   * @return The public key.
153
   */
128
   */
154
  public PublicKey getKey()
129
  public PublicKey getKey()
Lines 182-189 Link Here
182
        payload = key.getEncoded();
157
        payload = key.getEncoded();
183
      }
158
      }
184
    else
159
    else
185
      {
160
      throw new IllegalArgumentException("cannot encode public key");
186
        throw new IllegalArgumentException("cannot encode public key");
187
      }
188
  }
161
  }
189
}
162
}

Return to bug 26067