Package org.keyczar.jce

Source Code of org.keyczar.jce.EcKeyFactoryImpl

package org.keyczar.jce;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactorySpi;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.mozilla.jss.asn1.ASN1Value;
import org.mozilla.jss.asn1.BIT_STRING;
import org.mozilla.jss.asn1.INTEGER;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
import org.mozilla.jss.asn1.OCTET_STRING;
import org.mozilla.jss.asn1.SEQUENCE;
import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
import org.mozilla.jss.pkix.primitive.PrivateKeyInfo;

/**
* This class implements an EC key factory capable of generating:
* <ul>
* <li>Private keys from PKCS#8 and ECPrivateKeySpec
* <li>Public keys from X.509 and ECPublicKeySpec
* </ul>
*
* @author martclau@gmail.com
*
*/
public class EcKeyFactoryImpl extends KeyFactorySpi {

  public EcKeyFactoryImpl() {
    super();
  }

  // "Translate" e.g. {1 2 840 10045 2 1} to 1.2.840.10045.2.1
  private static String decodeOID(ASN1Value val) throws Exception {
    OBJECT_IDENTIFIER.Template ot = new OBJECT_IDENTIFIER.Template();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    val.encode(baos);
    OBJECT_IDENTIFIER o = (OBJECT_IDENTIFIER) ot
        .decode(new ByteArrayInputStream(baos.toByteArray()));
    StringBuffer sb = new StringBuffer();
    long[] nums = o.getNumbers();
    for (int i = 0; i < nums.length - 1; i++) {
      sb.append(nums[i] + ".");
    }
    sb.append(nums[nums.length - 1]);
    return sb.toString();
  }

  @Override
  protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
      throws InvalidKeySpecException {
    if (keySpec instanceof PKCS8EncodedKeySpec) {
      try {
        PrivateKeyInfo.Template pkiTemp = new PrivateKeyInfo.Template();
        byte[] data = ((PKCS8EncodedKeySpec) keySpec).getEncoded();
        PrivateKeyInfo pki = (PrivateKeyInfo) pkiTemp
            .decode(new ByteArrayInputStream(data));

        AlgorithmIdentifier algid = pki.getPrivateKeyAlgorithm();
        if (!algid.getOID().toString().equals("{1 2 840 10045 2 1}")) // ecPublicKey
          throw new IllegalArgumentException("Unsupported key");

        ECParameterSpec params = EcCore.getParams(decodeOID(algid
            .getParameters()));

        SEQUENCE.Template foo = new SEQUENCE.Template();
        foo.addElement(new INTEGER.Template());
        foo.addElement(new OCTET_STRING.Template());

        SEQUENCE ecPrivateKey = (SEQUENCE) foo.decode(new ByteArrayInputStream(
            pki.getEncoded()));
        OCTET_STRING arrhh = (OCTET_STRING) ecPrivateKey.elementAt(1);
        return new EcPrivateKeyImpl(new BigInteger(1, arrhh.toByteArray()),
            params);
      } catch (Exception e) {
        throw new InvalidKeySpecException("Invalid key encoding", e);
      }
    }
    if (keySpec instanceof ECPrivateKeySpec) {
      ECPrivateKeySpec spec = (ECPrivateKeySpec) keySpec;
      return new EcPrivateKeyImpl(spec.getS(), spec.getParams());
    }
    throw new IllegalArgumentException("Type of KeySpec is not supported");
  }

  @Override
  protected PublicKey engineGeneratePublic(KeySpec keySpec)
      throws InvalidKeySpecException {
    if (keySpec instanceof X509EncodedKeySpec) {
      try {
        SEQUENCE.Template outer = new SEQUENCE.Template();
        outer.addElement(AlgorithmIdentifier.getTemplate());
        outer.addElement(BIT_STRING.getTemplate());

        byte[] data = ((X509EncodedKeySpec) keySpec).getEncoded();
        SEQUENCE ecPublicKey = (SEQUENCE) outer
            .decode(new ByteArrayInputStream(data));

        AlgorithmIdentifier algid = (AlgorithmIdentifier) ecPublicKey
            .elementAt(0);
        if (!algid.getOID().toString().equals("{1 2 840 10045 2 1}")) // ecPublicKey
          throw new IllegalArgumentException("Unsupported key");

        ECParameterSpec params = EcCore.getParams(decodeOID(algid
            .getParameters()));

        BIT_STRING bs = (BIT_STRING) ecPublicKey.elementAt(1);
        data = bs.getBits();

        return new EcPublicKeyImpl(EcCore.bytesToECPoint(data, params), params);
      } catch (Exception e) {
        throw new InvalidKeySpecException("Invalid key encoding", e);
      }
    }
    if (keySpec instanceof ECPublicKeySpec) {
      ECPublicKeySpec spec = (ECPublicKeySpec) keySpec;
      return new EcPublicKeyImpl(spec.getW(), spec.getParams());
    }
    throw new IllegalArgumentException("Type of KeySpec is not supported");
  }

  @Override
  protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec) {
    throw new UnsupportedOperationException("Method not supported");
  }

  @Override
  protected Key engineTranslateKey(Key key) {
    throw new UnsupportedOperationException("Method not supported");
  }
}
TOP

Related Classes of org.keyczar.jce.EcKeyFactoryImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.