Source for gnu.java.security.provider.EncodedKeyFactory

   1: /* EncodedKeyFactory.java -- encoded key factory.
   2:    Copyright (C) 2004  Free Software Foundation, Inc.
   3: 
   4: This file is 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, or (at your option)
   9: 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; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 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.java.security.provider;
  40: 
  41: import gnu.java.security.OID;
  42: import gnu.java.security.der.BitString;
  43: import gnu.java.security.der.DERReader;
  44: import gnu.java.security.der.DERValue;
  45: 
  46: import java.io.IOException;
  47: import java.math.BigInteger;
  48: import java.security.AlgorithmParameters;
  49: import java.security.InvalidKeyException;
  50: import java.security.Key;
  51: import java.security.KeyFactorySpi;
  52: import java.security.NoSuchAlgorithmException;
  53: import java.security.PrivateKey;
  54: import java.security.PublicKey;
  55: import java.security.spec.DSAParameterSpec;
  56: import java.security.spec.InvalidKeySpecException;
  57: import java.security.spec.InvalidParameterSpecException;
  58: import java.security.spec.KeySpec;
  59: import java.security.spec.PKCS8EncodedKeySpec;
  60: import java.security.spec.RSAPrivateCrtKeySpec;
  61: import java.security.spec.RSAPublicKeySpec;
  62: import java.security.spec.X509EncodedKeySpec;
  63: 
  64: import javax.crypto.spec.DHParameterSpec;
  65: 
  66: /**
  67:  * A factory for keys encoded in either the X.509 format (for public
  68:  * keys) or the PKCS#8 format (for private keys).
  69:  *
  70:  * @author Casey Marshall (rsdio@metastatic.org)
  71:  */
  72: public class EncodedKeyFactory extends KeyFactorySpi
  73: {
  74: 
  75:   // Constants.
  76:   // ------------------------------------------------------------------------
  77: 
  78:   private static final OID ID_DSA = new OID("1.2.840.10040.4.1");
  79:   private static final OID ID_RSA = new OID("1.2.840.113549.1.1.1");
  80:   private static final OID ID_DH  = new OID("1.2.840.10046.2.1");
  81: 
  82:   // Instance methods.
  83:   // ------------------------------------------------------------------------
  84: 
  85:   public PublicKey engineGeneratePublic(KeySpec spec)
  86:     throws InvalidKeySpecException
  87:   {
  88:     if (!(spec instanceof X509EncodedKeySpec))
  89:       throw new InvalidKeySpecException("only supports X.509 key specs");
  90:     DERReader der = new DERReader(((X509EncodedKeySpec) spec).getEncoded());
  91:     try
  92:       {
  93:         DERValue spki = der.read();
  94:         if (!spki.isConstructed())
  95:           {
  96:             throw new InvalidKeySpecException("malformed encoded key");
  97:           }
  98:         DERValue alg = der.read();
  99:         if (!alg.isConstructed())
 100:           {
 101:             throw new InvalidKeySpecException("malformed encoded key");
 102:           }
 103:         DERValue val = der.read();
 104:         if (!(val.getValue() instanceof OID))
 105:           {
 106:             throw new InvalidKeySpecException("malformed encoded key");
 107:           }
 108:         OID algId = (OID) val.getValue();
 109:         byte[] algParams = null;
 110:         if (alg.getLength() > val.getEncodedLength())
 111:           {
 112:             val = der.read();
 113:             algParams = val.getEncoded();
 114:             if (val.isConstructed())
 115:               der.skip(val.getLength());
 116:           }
 117:         val = der.read();
 118:         if (!(val.getValue() instanceof BitString))
 119:           {
 120:             throw new InvalidKeySpecException("malformed encoded key");
 121:           }
 122:         byte[] publicKey = ((BitString) val.getValue()).toByteArray();
 123:         if (algId.equals(ID_DSA))
 124:           {
 125:             BigInteger p = null, g = null, q = null, Y;
 126:             if (algParams != null)
 127:               {
 128:                 DERReader dsaParams = new DERReader(algParams);
 129:                 val = dsaParams.read();
 130:                 if (!val.isConstructed())
 131:                   throw new InvalidKeySpecException("malformed DSA parameters");
 132:                 val = dsaParams.read();
 133:                 if (!(val.getValue() instanceof BigInteger))
 134:                   throw new InvalidKeySpecException("malformed DSA parameters");
 135:                 p = (BigInteger) val.getValue();
 136:                 val = dsaParams.read();
 137:                 if (!(val.getValue() instanceof BigInteger))
 138:                   throw new InvalidKeySpecException("malformed DSA parameters");
 139:                 q = (BigInteger) val.getValue();
 140:                 val = dsaParams.read();
 141:                 if (!(val.getValue() instanceof BigInteger))
 142:                   throw new InvalidKeySpecException("malformed DSA parameters");
 143:                 g = (BigInteger) val.getValue();
 144:               }
 145:             DERReader dsaPub = new DERReader(publicKey);
 146:             val = dsaPub.read();
 147:             if (!(val.getValue() instanceof BigInteger))
 148:               throw new InvalidKeySpecException("malformed DSA parameters");
 149:             Y = (BigInteger) val.getValue();
 150:             return new GnuDSAPublicKey(Y, p, q, g);
 151:           }
 152:         else if (algId.equals(ID_RSA))
 153:           {
 154:             DERReader rsaParams = new DERReader(publicKey);
 155:             if (!rsaParams.read().isConstructed())
 156:               {
 157:                 throw new InvalidKeySpecException("malformed encoded key");
 158:               }
 159:             return new GnuRSAPublicKey(new RSAPublicKeySpec(
 160:               (BigInteger) rsaParams.read().getValue(),
 161:               (BigInteger) rsaParams.read().getValue()));
 162:           }
 163:         else if (algId.equals(ID_DH))
 164:           {
 165:             if (algParams == null)
 166:               throw new InvalidKeySpecException("missing DH parameters");
 167:             DERReader dhParams = new DERReader(algParams);
 168:             val = dhParams.read();
 169:             BigInteger p, g, q, Y;
 170:             if (!val.isConstructed())
 171:               throw new InvalidKeySpecException("malformed DH parameters");
 172:             val = dhParams.read();
 173:             if (!(val.getValue() instanceof BigInteger))
 174:               throw new InvalidKeySpecException("malformed DH parameters");
 175:             p = (BigInteger) val.getValue();
 176:             val = dhParams.read();
 177:             if (!(val.getValue() instanceof BigInteger))
 178:               throw new InvalidKeySpecException("malformed DH parameters");
 179:             g = (BigInteger) val.getValue();
 180:             val = dhParams.read();
 181:             if (!(val.getValue() instanceof BigInteger))
 182:               throw new InvalidKeySpecException("malformed DH parameters");
 183:             q = (BigInteger) val.getValue();
 184:             DERReader dhPub = new DERReader(publicKey);
 185:             val = dhPub.read();
 186:             if (!(val.getValue() instanceof BigInteger))
 187:               throw new InvalidKeySpecException("malformed DH parameters");
 188:             Y = (BigInteger) val.getValue();
 189:             return (PublicKey) new GnuDHPublicKey(new DHParameterSpec(p, g), Y, q);
 190:           }
 191:         else
 192:           throw new InvalidKeySpecException("unknown algorithm: " + algId);
 193:       }
 194:     catch (IOException ioe)
 195:       {
 196:         throw new InvalidKeySpecException(ioe.getMessage());
 197:       }
 198:   }
 199: 
 200:   public PrivateKey engineGeneratePrivate(KeySpec spec)
 201:     throws InvalidKeySpecException
 202:   {
 203:     if (!(spec instanceof PKCS8EncodedKeySpec))
 204:       {
 205:         throw new InvalidKeySpecException("only supports PKCS8 key specs");
 206:       }
 207:     DERReader der = new DERReader(((PKCS8EncodedKeySpec) spec).getEncoded());
 208:     try
 209:       {
 210:         DERValue pki = der.read();
 211:         if (!pki.isConstructed())
 212:           {
 213:             throw new InvalidKeySpecException("malformed encoded key");
 214:           }
 215:         DERValue val = der.read();
 216:         if (!(val.getValue() instanceof BigInteger))
 217:           {
 218:             throw new InvalidKeySpecException("malformed encoded key");
 219:           }
 220:         DERValue alg = der.read();
 221:         if (!alg.isConstructed())
 222:           {
 223:             throw new InvalidKeySpecException("malformed encoded key");
 224:           }
 225:         val = der.read();
 226:         if (!(val.getValue() instanceof OID))
 227:           {
 228:             throw new InvalidKeySpecException("malformed encoded key");
 229:           }
 230:         OID algId = (OID) val.getValue();
 231:         byte[] algParams = null;
 232:         if (alg.getLength() > val.getEncodedLength())
 233:           {
 234:             val = der.read();
 235:             algParams = val.getEncoded();
 236:             if (val.isConstructed())
 237:               der.skip(val.getLength());
 238:           }
 239:         byte[] privateKey = (byte[]) der.read().getValue();
 240:         if (algId.equals(ID_DSA))
 241:           {
 242:             if (algParams == null)
 243:               {
 244:                 throw new InvalidKeySpecException("missing DSA parameters");
 245:               }
 246:             AlgorithmParameters params = AlgorithmParameters.getInstance("DSA");
 247:             params.init(algParams);
 248:             DSAParameterSpec dsaSpec = (DSAParameterSpec)
 249:               params.getParameterSpec(DSAParameterSpec.class);
 250:             DERReader dsaPriv = new DERReader(privateKey);
 251:             return new GnuDSAPrivateKey((BigInteger) dsaPriv.read().getValue(),
 252:               dsaSpec.getP(), dsaSpec.getQ(), dsaSpec.getG());
 253:           }
 254:         else if (algId.equals(ID_RSA))
 255:           {
 256:             DERReader rsaParams = new DERReader(privateKey);
 257:             if (!rsaParams.read().isConstructed())
 258:               throw new InvalidKeySpecException("malformed encoded key");
 259:             return new GnuRSAPrivateKey(new RSAPrivateCrtKeySpec(
 260:               (BigInteger) rsaParams.read().getValue(), // n
 261:               (BigInteger) rsaParams.read().getValue(), // e
 262:               (BigInteger) rsaParams.read().getValue(), // d
 263:               (BigInteger) rsaParams.read().getValue(), // p
 264:               (BigInteger) rsaParams.read().getValue(), // q
 265:               (BigInteger) rsaParams.read().getValue(), // d mod (p - 1)
 266:               (BigInteger) rsaParams.read().getValue(), // d mod (q - 1)
 267:               (BigInteger) rsaParams.read().getValue())); // (inv q) mod p
 268:           }
 269:         else
 270:           throw new InvalidKeySpecException("unknown algorithm: " + algId);
 271:       }
 272:     catch (InvalidParameterSpecException iapse)
 273:       {
 274:         throw new InvalidKeySpecException(iapse.getMessage());
 275:       }
 276:     catch (NoSuchAlgorithmException nsae)
 277:       {
 278:         throw new InvalidKeySpecException(nsae.getMessage());
 279:       }
 280:     catch (IOException ioe)
 281:       {
 282:         throw new InvalidKeySpecException(ioe.getMessage());
 283:       }
 284:   }
 285: 
 286:   public KeySpec engineGetKeySpec(Key key, Class speClass)
 287:     throws InvalidKeySpecException
 288:   {
 289:     if ((key instanceof PrivateKey) && key.getFormat().equals("PKCS#8")
 290:         && speClass.isAssignableFrom(PKCS8EncodedKeySpec.class))
 291:       return new PKCS8EncodedKeySpec(key.getEncoded());
 292:     else if ((key instanceof PublicKey) && key.getFormat().equals("X.509")
 293:         && speClass.isAssignableFrom(X509EncodedKeySpec.class))
 294:       return new X509EncodedKeySpec(key.getEncoded());
 295:     else
 296:       throw new InvalidKeySpecException();
 297:   }
 298: 
 299:   public Key engineTranslateKey(Key key) throws InvalidKeyException
 300:   {
 301:     throw new InvalidKeyException("translating keys not supported");
 302:   }
 303: }