OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [net/] [ssl/] [PrivateCredentials.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* PrivateCredentials.java -- private key/certificate pairs.
2
   Copyright (C) 2006, 2007  Free Software Foundation, Inc.
3
 
4
This file is a part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or (at
9
your option) any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19
USA
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version.  */
37
 
38
 
39
package gnu.javax.net.ssl;
40
 
41
import gnu.java.lang.CPStringBuilder;
42
 
43
import java.io.EOFException;
44
import java.io.InputStream;
45
import java.io.IOException;
46
 
47
import java.math.BigInteger;
48
 
49
import java.security.InvalidKeyException;
50
import java.security.KeyFactory;
51
import java.security.NoSuchAlgorithmException;
52
import java.security.PrivateKey;
53
import java.security.Security;
54
import java.security.cert.Certificate;
55
import java.security.cert.CertificateException;
56
import java.security.cert.CertificateFactory;
57
import java.security.cert.X509Certificate;
58
import java.security.spec.DSAPrivateKeySpec;
59
import java.security.spec.InvalidKeySpecException;
60
import java.security.spec.KeySpec;
61
import java.security.spec.RSAPrivateCrtKeySpec;
62
 
63
import java.util.Collection;
64
import java.util.HashMap;
65
import java.util.LinkedList;
66
import java.util.List;
67
 
68
import javax.net.ssl.ManagerFactoryParameters;
69
import javax.security.auth.callback.Callback;
70
import javax.security.auth.callback.CallbackHandler;
71
import javax.security.auth.callback.PasswordCallback;
72
import javax.security.auth.callback.UnsupportedCallbackException;
73
 
74
import gnu.javax.security.auth.callback.ConsoleCallbackHandler;
75
import gnu.java.security.hash.HashFactory;
76
import gnu.java.security.hash.IMessageDigest;
77
import gnu.javax.crypto.mode.IMode;
78
import gnu.javax.crypto.mode.ModeFactory;
79
import gnu.javax.crypto.pad.WrongPaddingException;
80
 
81
import gnu.java.security.der.DER;
82
import gnu.java.security.der.DERReader;
83
import gnu.java.util.Base64;
84
 
85
/**
86
 * An instance of a manager factory parameters for holding a single
87
 * certificate/private key pair, encoded in PEM format.
88
 */
89
public class PrivateCredentials implements ManagerFactoryParameters
90
{
91
 
92
  // Fields.
93
  // -------------------------------------------------------------------------
94
 
95
  public static final String BEGIN_DSA = "-----BEGIN DSA PRIVATE KEY";
96
  public static final String END_DSA   = "-----END DSA PRIVATE KEY";
97
  public static final String BEGIN_RSA = "-----BEGIN RSA PRIVATE KEY";
98
  public static final String END_RSA   = "-----END RSA PRIVATE KEY";
99
 
100
  private List<PrivateKey> privateKeys;
101
  private List<X509Certificate[]> certChains;
102
 
103
  // Constructor.
104
  // -------------------------------------------------------------------------
105
 
106
  public PrivateCredentials()
107
  {
108
    privateKeys = new LinkedList<PrivateKey>();
109
    certChains = new LinkedList<X509Certificate[]>();
110
  }
111
 
112
  // Instance methods.
113
  // -------------------------------------------------------------------------
114
 
115
  public void add(InputStream certChain, InputStream privateKey)
116
    throws CertificateException, InvalidKeyException, InvalidKeySpecException,
117
           IOException, NoSuchAlgorithmException, WrongPaddingException
118
  {
119
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
120
    Collection<? extends Certificate> certs = cf.generateCertificates(certChain);
121
    X509Certificate[] chain = (X509Certificate[]) certs.toArray(new X509Certificate[0]);
122
 
123
    String alg = null;
124
    String line = readLine(privateKey);
125
    String finalLine = null;
126
    if (line.startsWith(BEGIN_DSA))
127
      {
128
        alg = "DSA";
129
        finalLine = END_DSA;
130
      }
131
    else if (line.startsWith(BEGIN_RSA))
132
      {
133
        alg = "RSA";
134
        finalLine = END_RSA;
135
      }
136
    else
137
      throw new IOException("Unknown private key type.");
138
 
139
    boolean encrypted = false;
140
    String cipher = null;
141
    String salt = null;
142
    CPStringBuilder base64 = new CPStringBuilder();
143
    while (true)
144
      {
145
        line = readLine(privateKey);
146
        if (line == null)
147
          throw new EOFException("premature end-of-file");
148
        else if (line.startsWith("Proc-Type: 4,ENCRYPTED"))
149
          encrypted = true;
150
        else if (line.startsWith("DEK-Info: "))
151
          {
152
            int i = line.indexOf(',');
153
            if (i < 0)
154
              cipher = line.substring(10).trim();
155
            else
156
              {
157
                cipher = line.substring(10, i).trim();
158
                salt = line.substring(i + 1).trim();
159
              }
160
          }
161
        else if (line.startsWith(finalLine))
162
          break;
163
        else if (line.length() > 0)
164
          {
165
            base64.append(line);
166
            base64.append(System.getProperty("line.separator"));
167
          }
168
      }
169
 
170
    byte[] enckey = Base64.decode(base64.toString());
171
    if (encrypted)
172
      {
173
        enckey = decryptKey(enckey, cipher, toByteArray(salt));
174
      }
175
 
176
    DERReader der = new DERReader(enckey);
177
    if (der.read().getTag() != DER.SEQUENCE)
178
      throw new IOException("malformed DER sequence");
179
    der.read(); // version
180
 
181
    KeyFactory kf = KeyFactory.getInstance(alg);
182
    KeySpec spec = null;
183
    if (alg.equals("DSA"))
184
      {
185
        BigInteger p = (BigInteger) der.read().getValue();
186
        BigInteger q = (BigInteger) der.read().getValue();
187
        BigInteger g = (BigInteger) der.read().getValue();
188
        der.read(); // y
189
        BigInteger x = (BigInteger) der.read().getValue();
190
        spec = new DSAPrivateKeySpec(x, p, q, g);
191
      }
192
    else
193
      {
194
        spec = new RSAPrivateCrtKeySpec(
195
          (BigInteger) der.read().getValue(),  // modulus
196
          (BigInteger) der.read().getValue(),  // pub exponent
197
          (BigInteger) der.read().getValue(),  // priv expenent
198
          (BigInteger) der.read().getValue(),  // prime p
199
          (BigInteger) der.read().getValue(),  // prime q
200
          (BigInteger) der.read().getValue(),  // d mod (p-1)
201
          (BigInteger) der.read().getValue(),  // d mod (q-1)
202
          (BigInteger) der.read().getValue()); // coefficient
203
      }
204
 
205
    privateKeys.add(kf.generatePrivate(spec));
206
    certChains.add(chain);
207
  }
208
 
209
  public List<PrivateKey> getPrivateKeys()
210
  {
211
    if (isDestroyed())
212
      {
213
        throw new IllegalStateException("this object is destroyed");
214
      }
215
    return privateKeys;
216
  }
217
 
218
  public List<X509Certificate[]> getCertChains()
219
  {
220
    return certChains;
221
  }
222
 
223
  public void destroy()
224
  {
225
    privateKeys.clear();
226
    privateKeys = null;
227
  }
228
 
229
  public boolean isDestroyed()
230
  {
231
    return (privateKeys == null);
232
  }
233
 
234
  // Own methods.
235
  // -------------------------------------------------------------------------
236
 
237
  private String readLine(InputStream in) throws IOException
238
  {
239
    boolean eol_is_cr = System.getProperty("line.separator").equals("\r");
240
    CPStringBuilder str = new CPStringBuilder();
241
    while (true)
242
      {
243
        int i = in.read();
244
        if (i == -1)
245
          {
246
            if (str.length() > 0)
247
              break;
248
            else
249
              return null;
250
          }
251
        else if (i == '\r')
252
          {
253
            if (eol_is_cr)
254
              break;
255
          }
256
        else if (i == '\n')
257
          break;
258
        else
259
          str.append((char) i);
260
      }
261
    return str.toString();
262
  }
263
 
264
  private byte[] decryptKey(byte[] ct, String cipher, byte[] salt)
265
    throws IOException, InvalidKeyException, WrongPaddingException
266
  {
267
    byte[] pt = new byte[ct.length];
268
    IMode mode = null;
269
    if (cipher.equals("DES-EDE3-CBC"))
270
      {
271
        mode = ModeFactory.getInstance("CBC", "TripleDES", 8);
272
        HashMap attr = new HashMap();
273
        attr.put(IMode.KEY_MATERIAL, deriveKey(salt, 24));
274
        attr.put(IMode.IV, salt);
275
        attr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
276
        mode.init(attr);
277
      }
278
    else if (cipher.equals("DES-CBC"))
279
      {
280
        mode = ModeFactory.getInstance("CBC", "DES", 8);
281
        HashMap attr = new HashMap();
282
        attr.put(IMode.KEY_MATERIAL, deriveKey(salt, 8));
283
        attr.put(IMode.IV, salt);
284
        attr.put(IMode.STATE, new Integer(IMode.DECRYPTION));
285
        mode.init(attr);
286
      }
287
    else
288
      throw new IllegalArgumentException("unknown cipher: " + cipher);
289
 
290
    for (int i = 0; i < ct.length; i += 8)
291
      mode.update(ct, i, pt, i);
292
 
293
    int pad = pt[pt.length-1];
294
    if (pad < 1 || pad > 8)
295
      throw new WrongPaddingException();
296
    for (int i = pt.length - pad; i < pt.length; i++)
297
      {
298
        if (pt[i] != pad)
299
          throw new WrongPaddingException();
300
      }
301
 
302
    byte[] result = new byte[pt.length - pad];
303
    System.arraycopy(pt, 0, result, 0, result.length);
304
    return result;
305
  }
306
 
307
  private byte[] deriveKey(byte[] salt, int keylen)
308
    throws IOException
309
  {
310
    CallbackHandler passwordHandler = new ConsoleCallbackHandler();
311
    try
312
      {
313
        Class c = Class.forName(Security.getProperty("jessie.password.handler"));
314
        passwordHandler = (CallbackHandler) c.newInstance();
315
      }
316
    catch (Exception x) { }
317
 
318
    PasswordCallback passwdCallback =
319
      new PasswordCallback("Enter PEM passphrase: ", false);
320
    try
321
      {
322
        passwordHandler.handle(new Callback[] { passwdCallback });
323
      }
324
    catch (UnsupportedCallbackException uce)
325
      {
326
        throw new IOException("specified handler cannot handle passwords");
327
      }
328
    char[] passwd = passwdCallback.getPassword();
329
 
330
    IMessageDigest md5 = HashFactory.getInstance("MD5");
331
    byte[] key = new byte[keylen];
332
    int count = 0;
333
    while (count < keylen)
334
      {
335
        for (int i = 0; i < passwd.length; i++)
336
          md5.update((byte) passwd[i]);
337
        md5.update(salt, 0, salt.length);
338
        byte[] digest = md5.digest();
339
        int len = Math.min(digest.length, keylen - count);
340
        System.arraycopy(digest, 0, key, count, len);
341
        count += len;
342
        if (count >= keylen)
343
          break;
344
        md5.reset();
345
        md5.update(digest, 0, digest.length);
346
      }
347
    passwdCallback.clearPassword();
348
    return key;
349
  }
350
 
351
  private byte[] toByteArray(String hex)
352
  {
353
    hex = hex.toLowerCase();
354
    byte[] buf = new byte[hex.length() / 2];
355
    int j = 0;
356
    for (int i = 0; i < buf.length; i++)
357
      {
358
        buf[i] = (byte) ((Character.digit(hex.charAt(j++), 16) << 4) |
359
                          Character.digit(hex.charAt(j++), 16));
360
      }
361
    return buf;
362
  }
363
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.