Search in sources :

Example 1 with PemAttributes

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);
}
Also used : ECPrivateKey(java.security.interfaces.ECPrivateKey) RSAPrivateCrtKey(java.security.interfaces.RSAPrivateCrtKey) GeneralSecurityException(java.security.GeneralSecurityException) PemAttributes(org.kse.utilities.pem.PemAttributes) PemInfo(org.kse.utilities.pem.PemInfo) PemAttribute(org.kse.utilities.pem.PemAttribute) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) Cipher(javax.crypto.Cipher) CryptoException(org.kse.crypto.CryptoException)

Example 2 with PemAttributes

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;
}
Also used : ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) ASN1Sequence(org.bouncycastle.asn1.ASN1Sequence) ByteArrayInputStream(java.io.ByteArrayInputStream) PemInfo(org.kse.utilities.pem.PemInfo) PemAttributes(org.kse.utilities.pem.PemAttributes) BigInteger(java.math.BigInteger) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) ASN1Integer(org.bouncycastle.asn1.ASN1Integer) IOException(java.io.IOException) ASN1Primitive(org.bouncycastle.asn1.ASN1Primitive)

Example 3 with PemAttributes

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);
    }
}
Also used : GeneralSecurityException(java.security.GeneralSecurityException) PemInfo(org.kse.utilities.pem.PemInfo) PemAttributes(org.kse.utilities.pem.PemAttributes) ASN1OctetString(org.bouncycastle.asn1.ASN1OctetString) ByteArrayInputStream(java.io.ByteArrayInputStream) Cipher(javax.crypto.Cipher) CryptoException(org.kse.crypto.CryptoException)

Aggregations

ASN1OctetString (org.bouncycastle.asn1.ASN1OctetString)3 PemAttributes (org.kse.utilities.pem.PemAttributes)3 PemInfo (org.kse.utilities.pem.PemInfo)3 ByteArrayInputStream (java.io.ByteArrayInputStream)2 GeneralSecurityException (java.security.GeneralSecurityException)2 Cipher (javax.crypto.Cipher)2 CryptoException (org.kse.crypto.CryptoException)2 IOException (java.io.IOException)1 BigInteger (java.math.BigInteger)1 ECPrivateKey (java.security.interfaces.ECPrivateKey)1 RSAPrivateCrtKey (java.security.interfaces.RSAPrivateCrtKey)1 ASN1Integer (org.bouncycastle.asn1.ASN1Integer)1 ASN1Primitive (org.bouncycastle.asn1.ASN1Primitive)1 ASN1Sequence (org.bouncycastle.asn1.ASN1Sequence)1 PemAttribute (org.kse.utilities.pem.PemAttribute)1