apr_crypto_passphrase 使用的确切算法

Exact algorithm used by apr_crypto_passphrase

我需要编写一个 apache 模块来加密数据,我需要解密 java 中的数据。

到目前为止,我设法在 apache 端加密了数据,但是我找不到有效用于加密的密钥,因为它隐藏在 apr_crypto_passphrase 中并存储在 [=12= 中], 这是一个不完整的类型。

documentation 提到它使用 "default the PBKDF2 algorithm",但没有说明是哪种口味,例如PBKDF2WithHmacSHA256,也不是 "by default" 的意思,也看不到更改算法的方法。

我正在使用 OpenSSL 驱动程序并希望在 CBC 模式下使用 AES 128。

如何获取(或设置)有效使用的密钥,或者如何在 Java 中计算此密钥。

至少使用带有 SHA1 的 OpenSSL 驱动程序 PBKDF2(这是硬编码的)。

下面是两个代码片段,它们根据给定的纯文本、密码、salt、迭代次数和 IV 生成相同的输出。

C / APR(引用的函数可以在testcrypto.c中找到):

char *plain_text = apr_pstrdup(pool, "some value");
char *passphrase = apr_pstrdup(pool, "some pass");

const int salt_len = 9;
const char salt_in[] = {1, 1, 1, 1, 1, 1, 1, 1, 1};

const int iterations = 1000;

// everything after the 16th byte is ignored for AES 128
const int iv_len = 16;
const char iv_in[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

unsigned char *cipher_text = NULL;
apr_size_t cipher_text_len = 0;
apr_size_t block_size = 0;
apr_size_t iv_size = 0;

const apr_crypto_driver_t *driver = get_openssl_driver(r, pool);
apr_crypto_t *f1 = factory(pool, driver);

char *salt = apr_palloc(pool, salt_len);
memcpy(salt, salt_in, salt_len);

apr_crypto_key_t *crypto_key = NULL; // init to NULL is important, see docs!

apr_crypto_passphrase(&crypto_key, &iv_size, passphrase, strlen(passphrase), salt, salt_len, APR_KEY_AES_128, APR_MODE_CBC, 1, iterations, f1, pool);

unsigned char *iv = apr_palloc(pool, iv_len);
memcpy(iv, iv_in, iv_len);

encrypt_block(NULL, pool, driver, f1, crypto_key, plain_text, strlen(plain_text),
                           &cipher_text, &cipher_text_len, &iv, &block_size, "KEY_AES_128/MODE_CBC");

// Note: b64_len includes spaces for '[=10=]' terminator
int b64_len = apr_base64_encode_len(cipher_text_len);
char *b64 = apr_pcalloc(pool, b64_len);
apr_base64_encode_binary(b64, cipher_text, cipher_text_len);

Java:

/* Derive the key, given passphrase and salt. */
final String plainText = "some value";
final String passphrase = "some pass";
final byte[] salt = {1, 1, 1, 1, 1, 1, 1, 1, 1};
final int iterations = 1000;
byte[] iv = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(passphrase.toCharArray(), salt, iterations, 128);
SecretKey tmp = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plainText.getBytes("UTF-8"));

System.out.println(DatatypeConverter.printBase64Binary(ciphertext));

提醒:不要将这些值用于生产代码。