/* See LICENSE for licensing and NOTICE for copyright. */
package org.cryptacular.asn;
import org.cryptacular.EncodingException;
import org.cryptacular.util.PemUtil;
/**
* Base class for all private key decoders.
*
* @param <T> Type produced by decode operation.
*
* @author Middleware Services
*/
public abstract class AbstractPrivateKeyDecoder<T> implements ASN1Decoder<T>
{
@Override
public T decode(final byte[] encoded, final Object... args) throws EncodingException
{
try {
final byte[] asn1Bytes;
if (args != null && args.length > 0 && args[0] instanceof char[]) {
asn1Bytes = decryptKey(encoded, (char[]) args[0]);
} else {
asn1Bytes = tryConvertPem(encoded);
}
return decodeASN1(asn1Bytes);
} catch (EncodingException e) {
throw e;
} catch (RuntimeException e) {
throw new EncodingException("Key encoding error", e);
}
}
/**
* Tests the given encoded input and converts it to PEM if it is detected, stripping out any header/footer data in the
* process.
*
* @param input Encoded data that may be PEM encoded.
*
* @return Decoded data if PEM encoding detected, otherwise original data.
*/
protected byte[] tryConvertPem(final byte[] input)
{
if (PemUtil.isPem(input)) {
return PemUtil.decode(input);
}
return input;
}
/**
* Decrypts an encrypted key in either PKCS#8 or OpenSSL "traditional" format. Both PEM and DER encodings are
* supported.
*
* @param encrypted Encoded encrypted key data.
* @param password Password to decrypt key.
*
* @return Decrypted key.
*/
protected abstract byte[] decryptKey(byte[] encrypted, char[] password);
/**
* Decodes the given raw ASN.1 encoded data into a private key of the type supported by this class.
*
* @param encoded Encoded ASN.1 data.
*
* @return Private key object.
*/
protected abstract T decodeASN1(byte[] encoded);
}