org.apache.commons.ssl
Class PKCS8Key

java.lang.Object
  extended by org.apache.commons.ssl.PKCS8Key

public class PKCS8Key
extends java.lang.Object

Utility for decrypting PKCS8 private keys. Way easier to use than javax.crypto.EncryptedPrivateKeyInfo since all you need is the byte[] array and the password. You don't need to know anything else about the PKCS8 key you pass in.

Can handle base64 PEM, or raw DER. Can handle PKCS8 Version 1.5 and 2.0. Can also handle OpenSSL encrypted or unencrypted private keys (DSA or RSA).

The PKCS12 key derivation (the "pkcs12()" method) comes from BouncyCastle.

Since:
7-Nov-2006
Author:
Credit Union Central of British Columbia, www.cucbc.com, juliusdavies@cucbc.com, bouncycastle.org

Nested Class Summary
static class PKCS8Key.DecryptResult
           
 
Field Summary
private  byte[] decryptedBytes
           
static java.lang.String DSA_OID
           
private  boolean isDSA
           
private  boolean isRSA
           
private  int keySize
           
static java.lang.String OPENSSL_DSA
           
static java.lang.String OPENSSL_RSA
           
static java.lang.String PKCS8_ENCRYPTED
           
static java.lang.String PKCS8_UNENCRYPTED
           
private  java.security.PrivateKey privateKey
           
static java.lang.String RSA_OID
           
private  java.lang.String transformation
           
 
Constructor Summary
PKCS8Key(byte[] encoded, char[] password)
           
PKCS8Key(java.io.ByteArrayInputStream in, char[] password)
           
PKCS8Key(java.io.InputStream in, char[] password)
           
 
Method Summary
private static boolean allZeroes(byte[] b)
           
static PKCS8Key.DecryptResult decrypt(java.lang.String cipher, java.lang.String mode, DerivedKey dk, boolean des2, byte[] iv, byte[] encryptedBytes)
           
private static PKCS8Key.DecryptResult decryptPKCS8(ASN1Structure pkcs8, char[] password)
           
static DerivedKey deriveKeyPKCS12(char[] password, byte[] salt, int iterations, int keySizeInBits, int ivSizeInBits, java.security.MessageDigest md)
           
static DerivedKey deriveKeyV1(byte[] password, byte[] salt, int iterations, int keySizeInBits, int ivSizeInBits, java.security.MessageDigest md)
           
static DerivedKey deriveKeyV2(byte[] password, byte[] salt, int iterations, int keySizeInBits, int ivSizeInBits, javax.crypto.Mac mac)
           
static byte[] encode(DEREncodable der)
           
static byte[] formatAsPKCS8(byte[] privateKey, java.lang.String oid, ASN1Structure pkcs8)
           
static javax.crypto.Cipher generateCipher(java.lang.String cipher, java.lang.String mode, DerivedKey dk, boolean des2, byte[] iv, boolean decryptMode)
           
 byte[] getDecryptedBytes()
           
 int getKeySize()
           
 java.security.PrivateKey getPrivateKey()
           
 java.security.PublicKey getPublicKey()
           
 java.lang.String getTransformation()
           
 boolean isDSA()
           
 boolean isRSA()
           
static void main(java.lang.String[] args)
           
private static PKCS8Key.DecryptResult opensslDecrypt(PEMItem item, char[] password)
           
private static byte[] pkcs12(int idByte, int n, byte[] salt, byte[] password, int iterationCount, java.security.MessageDigest md)
          This PKCS12 key derivation code comes from BouncyCastle.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

RSA_OID

public static final java.lang.String RSA_OID
See Also:
Constant Field Values

DSA_OID

public static final java.lang.String DSA_OID
See Also:
Constant Field Values

PKCS8_UNENCRYPTED

public static final java.lang.String PKCS8_UNENCRYPTED
See Also:
Constant Field Values

PKCS8_ENCRYPTED

public static final java.lang.String PKCS8_ENCRYPTED
See Also:
Constant Field Values

OPENSSL_RSA

public static final java.lang.String OPENSSL_RSA
See Also:
Constant Field Values

OPENSSL_DSA

public static final java.lang.String OPENSSL_DSA
See Also:
Constant Field Values

privateKey

private final java.security.PrivateKey privateKey

decryptedBytes

private final byte[] decryptedBytes

transformation

private final java.lang.String transformation

keySize

private final int keySize

isDSA

private final boolean isDSA

isRSA

private final boolean isRSA
Constructor Detail

PKCS8Key

public PKCS8Key(java.io.InputStream in,
                char[] password)
         throws java.security.GeneralSecurityException,
                java.io.IOException
Parameters:
in - pkcs8 file to parse (pem or der, encrypted or unencrypted)
password - password to decrypt the pkcs8 file. Ignored if the supplied pkcs8 is already unencrypted.
Throws:
java.security.GeneralSecurityException - If a parsing or decryption problem occured.
java.io.IOException - If the supplied InputStream could not be read.

PKCS8Key

public PKCS8Key(java.io.ByteArrayInputStream in,
                char[] password)
         throws java.security.GeneralSecurityException
Parameters:
in - pkcs8 file to parse (pem or der, encrypted or unencrypted)
password - password to decrypt the pkcs8 file. Ignored if the supplied pkcs8 is already unencrypted.
Throws:
java.security.GeneralSecurityException - If a parsing or decryption problem occured.

PKCS8Key

public PKCS8Key(byte[] encoded,
                char[] password)
         throws java.security.GeneralSecurityException
Parameters:
encoded - pkcs8 file to parse (pem or der, encrypted or unencrypted)
password - password to decrypt the pkcs8 file. Ignored if the supplied pkcs8 is already unencrypted.
Throws:
java.security.GeneralSecurityException - If a parsing or decryption problem occured.
Method Detail

isRSA

public boolean isRSA()

isDSA

public boolean isDSA()

getTransformation

public java.lang.String getTransformation()

getKeySize

public int getKeySize()

getDecryptedBytes

public byte[] getDecryptedBytes()

getPrivateKey

public java.security.PrivateKey getPrivateKey()

getPublicKey

public java.security.PublicKey getPublicKey()
                                     throws java.security.GeneralSecurityException
Throws:
java.security.GeneralSecurityException

opensslDecrypt

private static PKCS8Key.DecryptResult opensslDecrypt(PEMItem item,
                                                     char[] password)
                                              throws java.security.GeneralSecurityException
Throws:
java.security.GeneralSecurityException

generateCipher

public static javax.crypto.Cipher generateCipher(java.lang.String cipher,
                                                 java.lang.String mode,
                                                 DerivedKey dk,
                                                 boolean des2,
                                                 byte[] iv,
                                                 boolean decryptMode)
                                          throws java.security.NoSuchAlgorithmException,
                                                 javax.crypto.NoSuchPaddingException,
                                                 java.security.InvalidKeyException,
                                                 java.security.InvalidAlgorithmParameterException
Throws:
java.security.NoSuchAlgorithmException
javax.crypto.NoSuchPaddingException
java.security.InvalidKeyException
java.security.InvalidAlgorithmParameterException

decrypt

public static PKCS8Key.DecryptResult decrypt(java.lang.String cipher,
                                             java.lang.String mode,
                                             DerivedKey dk,
                                             boolean des2,
                                             byte[] iv,
                                             byte[] encryptedBytes)
                                      throws java.security.NoSuchAlgorithmException,
                                             javax.crypto.NoSuchPaddingException,
                                             java.security.InvalidKeyException,
                                             java.security.InvalidAlgorithmParameterException,
                                             javax.crypto.IllegalBlockSizeException,
                                             javax.crypto.BadPaddingException
Throws:
java.security.NoSuchAlgorithmException
javax.crypto.NoSuchPaddingException
java.security.InvalidKeyException
java.security.InvalidAlgorithmParameterException
javax.crypto.IllegalBlockSizeException
javax.crypto.BadPaddingException

decryptPKCS8

private static PKCS8Key.DecryptResult decryptPKCS8(ASN1Structure pkcs8,
                                                   char[] password)
                                            throws java.security.GeneralSecurityException
Throws:
java.security.GeneralSecurityException

deriveKeyV1

public static DerivedKey deriveKeyV1(byte[] password,
                                     byte[] salt,
                                     int iterations,
                                     int keySizeInBits,
                                     int ivSizeInBits,
                                     java.security.MessageDigest md)

deriveKeyPKCS12

public static DerivedKey deriveKeyPKCS12(char[] password,
                                         byte[] salt,
                                         int iterations,
                                         int keySizeInBits,
                                         int ivSizeInBits,
                                         java.security.MessageDigest md)

pkcs12

private static byte[] pkcs12(int idByte,
                             int n,
                             byte[] salt,
                             byte[] password,
                             int iterationCount,
                             java.security.MessageDigest md)
This PKCS12 key derivation code comes from BouncyCastle.

Parameters:
idByte - 1 == key, 2 == iv
n - keysize or ivsize
salt - 8 byte salt
password - password
iterationCount - iteration-count
md - The message digest to use
Returns:
byte[] the derived key

deriveKeyV2

public static DerivedKey deriveKeyV2(byte[] password,
                                     byte[] salt,
                                     int iterations,
                                     int keySizeInBits,
                                     int ivSizeInBits,
                                     javax.crypto.Mac mac)
                              throws java.security.InvalidKeyException
Throws:
java.security.InvalidKeyException

formatAsPKCS8

public static byte[] formatAsPKCS8(byte[] privateKey,
                                   java.lang.String oid,
                                   ASN1Structure pkcs8)

allZeroes

private static boolean allZeroes(byte[] b)

encode

public static byte[] encode(DEREncodable der)
                     throws java.io.IOException
Throws:
java.io.IOException

main

public static void main(java.lang.String[] args)
                 throws java.lang.Exception
Throws:
java.lang.Exception