9

Is there a way to generate PrivateKey from byte array? I got this byte array using getEncoded() method, but now I have to convert it back to PrivateKey.

Thanks, Vuk

Robert
  • 39,162
  • 17
  • 99
  • 152
Vuk
  • 283
  • 2
  • 3
  • 5

5 Answers5

8

I was looking for this answer too and finally found it. keyBytes is a byte array originally created with getEncoded().

//add BouncyCastle as a provider if you want
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
//create a keyfactory - use whichever algorithm and provider
KeyFactory kf = KeyFactory.getInstance("DSA", "BC");
//for private keys use PKCS8EncodedKeySpec; for public keys use X509EncodedKeySpec
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(keyBytes);
PrivateKey pk = kf.generatePrivate(ks);

I've never done anything for JavaCard but from this post, it looks like you can use the KeyFactory class. You'll probably need to download the BouncyCastle library.

marchica
  • 2,326
  • 23
  • 21
  • 1
    thanks. Great work! You saved me hours of research. This should be selected as the correct answer, unless the OP's platform does not support bouncy castle. – Jus12 Jul 28 '11 at 06:25
  • I didn't get what you meant by "if you want". Is it optional? – Jus12 Jul 28 '11 at 06:36
  • @Jus12 I meant if you want to use BouncyCastle and it's not already included as a provider on the platform you're using. For example, on Android I added the BouncyCastle library and had to use that line to add BC as a provider and use BC's implementations of the algorithms. Glad I could help someone! :) – marchica Jul 29 '11 at 15:42
5

As stated on the Java docs

Keys are generally obtained through key generators, certificates, or various Identity classes used to manage keys. Keys may also be obtained from key specifications (transparent representations of the underlying key material) through the use of a key factory.

The KeyFactory class can help you out with this.

Patrick
  • 17,669
  • 6
  • 70
  • 85
  • I forgot to say that I am working with javacard, which doesn't support KeyFactory class. It does support keyBuilder, but I cannot really figure out how to use this class for my need. – Vuk Jan 05 '11 at 02:23
3

Throw away the encoded byte array. On JavaCard there is AFAIR no way to decode it directly - you have to set the different key components separately.

For example an RSAPrivateKey needs to be initialized with the exponent and the modulus:

rsaPrivate = (RSAPrivateKey) javacard.security.KeyBuilder.buildKey
  (javacard.security.KeyBuilder.TYPE_RSA_PRIVATE, 
  javacard.security.KeyBuilder.LENGTH_RSA_512, false);

byte[] exponent = {(byte) 7};
byte[] modulus = {(byte) 33};
rsaPrivate.setExponent(exponent, (short) 0, (short) exponent.length);
rsaPrivate.setModulus(modulus, (short) 0, (short) modulus.length);

BTW: For JavaCard questions I recommend the JavaCard Forum in the Oracle forums. If you search there for RSAPrivateKey you will find some interesting posts.

Robert
  • 39,162
  • 17
  • 99
  • 152
  • what is the point of getEncoded then? They might have as well thrown an UnsupportedOperationException. – Jus12 Jul 28 '11 at 06:21
  • getEncoded() is only available on J2SE. It returns a private key in PKCS#8 encoded form which can be used nearly everywhere. The JavaCard platform is one of those exceptions. – Robert Jul 28 '11 at 07:19
  • @Robert I have a key pair generated on the card and I would like to send the public key in a response APDU. How do I generate a byte array from the public key? Thank you! – bp14 May 10 '15 at 11:18
1
//ECDSA algo of signature type prime256 of key
Security.addProvider(new BouncyCastleProvider());
KeyFactory factory = KeyFactory.getInstance("ECDSA", "BC");
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("prime256v1");
ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(new BigInteger(1, privKey), spec);
PrivateKey privateKey = factory.generatePrivate(ecPrivateKeySpec);
Pritesh Patel
  • 678
  • 17
  • 35
0

Either you have to decode the PKCS#8 encoded blob yourself (ASN.1 BER parsing) and set the components, or you can get the components from the private key (at least the private exponent and modulus) as Java BigIntegers, convert those to unsigned byte arrays and set them in the Java Card API as explained by Robert. PKCS#8 parsing can be done on Java Card but it's a pretty horrendous excercise.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263