use of org.kse.utilities.pem.PemAttributes in project keystore-explorer by kaikramer.
the class OpenSslPvkUtil method getEncrypted.
/**
* OpenSSL encode and encrypt a private key. Encrypted OpenSSL private keys
* must always by PEM'd.
*
* @return The encrypted, PEM'd encoding
* @param privateKey
* The private key
* @param pbeType
* PBE algorithm to use for encryption
* @param password
* Encryption password
* @throws CryptoException
* Problem encountered while getting the encoded private key
*/
public static String getEncrypted(PrivateKey privateKey, OpenSslPbeType pbeType, Password password) throws CryptoException {
byte[] openSsl = get(privateKey);
String pemType = null;
if (privateKey instanceof RSAPrivateCrtKey) {
pemType = OPENSSL_RSA_PVK_PEM_TYPE;
} else if (privateKey instanceof ECPrivateKey) {
pemType = OPENSSL_EC_PVK_PEM_TYPE;
} else {
pemType = OPENSSL_DSA_PVK_PEM_TYPE;
}
byte[] salt = generateSalt(pbeType.saltSize() / 8);
String saltHex = bytesToHex(salt);
byte[] encOpenSsl = null;
try {
byte[] encryptKey = deriveKeyFromPassword(password, salt, pbeType.keySize());
// Create cipher - use all of the salt as the IV
Cipher cipher = createCipher(pbeType.jceCipher(), encryptKey, salt, ENCRYPT_MODE);
encOpenSsl = cipher.doFinal(openSsl);
} catch (GeneralSecurityException ex) {
throw new CryptoException(MessageFormat.format("OpenSslEncryptionFailed.exception.message", pbeType.friendly()), ex);
}
PemAttributes attributes = new PemAttributes();
attributes.add(new PemAttribute(PROC_TYPE_ATTR_NAME, PROC_TYPE_ATTR_VALUE));
String dekInfoAttrValue = MessageFormat.format(DEK_INFO_ATTR_VALUE_TEMPLATE, pbeType.dekInfo(), saltHex);
attributes.add(new PemAttribute(DEK_INFO_ATTR_NAME, dekInfoAttrValue));
PemInfo pemInfo = new PemInfo(pemType, attributes, encOpenSsl);
return PemUtil.encode(pemInfo);
}
use of org.kse.utilities.pem.PemAttributes in project keystore-explorer by kaikramer.
the class OpenSslPvkUtil method getEncryptionType.
/**
* Detect if a OpenSSL private key is encrypted or not.
*
* @param is
* Input stream containing OpenSSL private key
* @return Encryption type or null if not a valid OpenSSL private key
* @throws IOException
* If an I/O problem occurred
*/
public static EncryptionType getEncryptionType(InputStream is) throws IOException {
byte[] openSsl = ReadUtil.readFully(is);
// In PEM format?
PemInfo pemInfo = PemUtil.decode(new ByteArrayInputStream(openSsl));
if (pemInfo != null) {
String pemType = pemInfo.getType();
// PEM type of OpenSSL?
if (OPENSSL_RSA_PVK_PEM_TYPE.equals(pemType) || OPENSSL_DSA_PVK_PEM_TYPE.equals(pemType) || OPENSSL_EC_PVK_PEM_TYPE.equals(pemType)) {
// Encrypted? It is if PEM contains appropriate header attributes/values
PemAttributes pemAttributes = pemInfo.getAttributes();
if ((pemAttributes != null) && (pemAttributes.get(PROC_TYPE_ATTR_NAME) != null) && (pemAttributes.get(PROC_TYPE_ATTR_NAME).getValue().equals(PROC_TYPE_ATTR_VALUE)) && (pemAttributes.get(DEK_INFO_ATTR_NAME) != null)) {
return ENCRYPTED;
} else {
return UNENCRYPTED;
}
}
}
// In ASN.1 format?
try {
// If OpenSSL will be a sequence of 9 (RSA) or 6 (DSA) integers or 2-4 mixed elements (EC)
ASN1Primitive key = ASN1Primitive.fromByteArray(openSsl);
if (key instanceof ASN1Sequence) {
ASN1Sequence seq = (ASN1Sequence) key;
// }
if ((seq.size() >= 2) && (seq.size() <= 4) && seq.getObjectAt(0) instanceof ASN1Integer) {
BigInteger version = ((ASN1Integer) seq.getObjectAt(0)).getValue();
if (version.equals(VERSION_EC)) {
if (seq.getObjectAt(1) instanceof ASN1OctetString) {
// ASN.1 OpenSSL is always unencrypted
return UNENCRYPTED;
} else {
// Not OpenSSL
return null;
}
}
}
for (int i = 0; i < seq.size(); i++) {
if (!(seq.getObjectAt(i) instanceof ASN1Integer)) {
// Not OpenSSL
return null;
}
}
if ((seq.size() == 9) || (seq.size() == 6)) {
// ASN.1 OpenSSL is always unencrypted
return UNENCRYPTED;
}
}
} catch (IOException ex) {
// Not an OpenSSL file
return null;
}
// Not an OpenSSL file
return null;
}
use of org.kse.utilities.pem.PemAttributes in project keystore-explorer by kaikramer.
the class OpenSslPvkUtil method loadEncrypted.
/**
* Load an encrypted OpenSSL private key from the specified stream. The
* encoding of the private key will be PEM.
*
* @param is
* Stream load the encrypted private key from
* @param password
* Password to decrypt
* @return The private key
* @throws PrivateKeyUnencryptedException
* If private key is unencrypted
* @throws PrivateKeyPbeNotSupportedException
* If private key PBE algorithm is not supported
* @throws CryptoException
* Problem encountered while loading the private key
* @throws IOException
* An I/O error occurred
*/
public static PrivateKey loadEncrypted(InputStream is, Password password) throws CryptoException, IOException {
byte[] streamContents = ReadUtil.readFully(is);
EncryptionType encType = getEncryptionType(new ByteArrayInputStream(streamContents));
if (encType == null) {
throw new CryptoException(res.getString("NotValidOpenSsl.exception.message"));
}
if (encType == UNENCRYPTED) {
throw new PrivateKeyUnencryptedException(res.getString("OpenSslIsUnencrypted.exception.message"));
}
// OpenSSL must be encrypted and therefore must be PEM
PemInfo pemInfo = PemUtil.decode(new ByteArrayInputStream(streamContents));
byte[] encKey = pemInfo.getContent();
PemAttributes attributes = pemInfo.getAttributes();
String dekInfo = attributes.get(DEK_INFO_ATTR_NAME).getValue();
// Split DEK-Info into encryption pbe algorithm and salt
int separator = dekInfo.indexOf(',');
if (separator == -1) {
throw new CryptoException(MessageFormat.format("OpenSslDekInfoMalformed.exception.message", dekInfo));
}
String encAlg = dekInfo.substring(0, separator);
String salt = dekInfo.substring(separator + 1);
byte[] saltBytes = hexToBytes(salt);
OpenSslPbeType pbeType = OpenSslPbeType.resolveDekInfo(encAlg);
if (pbeType == null) {
throw new PrivateKeyPbeNotSupportedException(encAlg, MessageFormat.format(res.getString("PrivateKeyWrappingAlgUnsupported.exception.message"), encAlg));
}
try {
byte[] decryptKey = deriveKeyFromPassword(password, saltBytes, pbeType.keySize());
// Create cipher - use all of the salt as the IV
Cipher cipher = createCipher(pbeType.jceCipher(), decryptKey, saltBytes, DECRYPT_MODE);
byte[] key = cipher.doFinal(encKey);
return load(new ByteArrayInputStream(key));
} catch (GeneralSecurityException ex) {
throw new CryptoException(MessageFormat.format("OpenSslDecryptionFailed.exception.message", pbeType.friendly()), ex);
}
}
Aggregations