+++ /dev/null
-package org.argeo.ident;
-
-import java.nio.charset.StandardCharsets;
-import java.security.GeneralSecurityException;
-import java.security.MessageDigest;
-import java.util.Arrays;
-import java.util.Base64;
-
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-/**
- * Decrypts OpenSSL encrypted data.
- *
- * From
- * https://stackoverflow.com/questions/11783062/how-to-decrypt-file-in-java-encrypted-with-openssl-command-using-aes
- *
- * See also
- * https://stackoverflow.com/questions/54171959/badpadding-exception-when-trying-to-decrypt-aes-based-encrypted-text/54173509#54173509
- * for new default message digest (not yet in CentOS 7 as of July 2019)
- */
-public class OpenSslDecryptor {
- private static final int INDEX_KEY = 0;
- private static final int INDEX_IV = 1;
- private static final int ITERATIONS = 1;
-
- private static final int SALT_OFFSET = 8;
- private static final int SALT_SIZE = 8;
- private static final int CIPHERTEXT_OFFSET = SALT_OFFSET + SALT_SIZE;
-
- /** In bits. */
- private final int keySize;
-
- private Cipher cipher;
- private MessageDigest messageDigest;
-
- public OpenSslDecryptor() {
- /*
- * Changed to SHA-256 from OpenSSL v1.1.0 (see
- * https://stackoverflow.com/questions/39637388/encryption-decryption-doesnt-
- * work-well-between-two-different-openssl-versions)
- */
- this(128, "MD5");
- }
-
- public OpenSslDecryptor(int keySize, String messageDigest) {
- this.keySize = keySize;
- try {
- this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
- this.messageDigest = MessageDigest.getInstance(messageDigest);
- } catch (GeneralSecurityException e) {
- throw new IllegalArgumentException("Cannot initialise decryptor", e);
- }
- }
-
- public String decryptAuthd(String dataBase64, String passphrase) {
- try {
- byte[] headerSaltAndCipherText = Base64.getDecoder().decode(dataBase64);
-
- boolean withSalt = true;
- byte[] salt = withSalt ? Arrays.copyOfRange(headerSaltAndCipherText, SALT_OFFSET, SALT_OFFSET + SALT_SIZE)
- : null;
- byte[] encrypted = withSalt
- ? Arrays.copyOfRange(headerSaltAndCipherText, CIPHERTEXT_OFFSET, headerSaltAndCipherText.length)
- : headerSaltAndCipherText;
-
- final byte[][] keyAndIV = EVP_BytesToKey(keySize / Byte.SIZE, cipher.getBlockSize(), messageDigest, salt,
- passphrase.getBytes(StandardCharsets.US_ASCII), ITERATIONS);
- SecretKeySpec key = new SecretKeySpec(keyAndIV[INDEX_KEY], "AES");
- IvParameterSpec iv = new IvParameterSpec(keyAndIV[INDEX_IV]);
-
- cipher.init(Cipher.DECRYPT_MODE, key, iv);
- byte[] decrypted = cipher.doFinal(encrypted);
-
- String answer = new String(decrypted, StandardCharsets.US_ASCII);
- return answer;
- } catch (BadPaddingException e) {
- throw new IllegalStateException("Bad password, algorithm, mode or padding;"
- + " no salt, wrong number of iterations or corrupted ciphertext.", e);
- } catch (IllegalBlockSizeException e) {
- throw new IllegalStateException("Bad algorithm, mode or corrupted (resized) ciphertext.", e);
- } catch (GeneralSecurityException e) {
- throw new IllegalStateException(e);
- }
- }
-
- private static byte[][] EVP_BytesToKey(int key_len, int iv_len, MessageDigest md, byte[] salt, byte[] data,
- int count) {
- byte[][] both = new byte[2][];
- byte[] key = new byte[key_len];
- int key_ix = 0;
- byte[] iv = new byte[iv_len];
- int iv_ix = 0;
- both[0] = key;
- both[1] = iv;
- byte[] md_buf = null;
- int nkey = key_len;
- int niv = iv_len;
- int i = 0;
- if (data == null) {
- return both;
- }
- int addmd = 0;
- for (;;) {
- md.reset();
- if (addmd++ > 0) {
- md.update(md_buf);
- }
- md.update(data);
- if (null != salt) {
- md.update(salt, 0, 8);
- }
- md_buf = md.digest();
- for (i = 1; i < count; i++) {
- md.reset();
- md.update(md_buf);
- md_buf = md.digest();
- }
- i = 0;
- if (nkey > 0) {
- for (;;) {
- if (nkey == 0)
- break;
- if (i == md_buf.length)
- break;
- key[key_ix++] = md_buf[i];
- nkey--;
- i++;
- }
- }
- if (niv > 0 && i != md_buf.length) {
- for (;;) {
- if (niv == 0)
- break;
- if (i == md_buf.length)
- break;
- iv[iv_ix++] = md_buf[i];
- niv--;
- i++;
- }
- }
- if (nkey == 0 && niv == 0) {
- break;
- }
- }
- for (i = 0; i < md_buf.length; i++) {
- md_buf[i] = 0;
- }
- return both;
- }
-
- public static void main(String[] args) {
- String dataBase64 = args[0];
- String passphrase = args[1];
- OpenSslDecryptor decryptor = new OpenSslDecryptor();
- System.out.println(decryptor.decryptAuthd(dataBase64, passphrase));
- }
-
-}
\ No newline at end of file