java - 使用 JAVA (jasypt) 加密并使用 PHP 解密
问题描述
使用 JAVA (jasypt) 加密并使用 PHP 解密 - 什么是较不易受攻击的算法?
我正在使用具有以下任务的遗留系统:
1) Java 应用程序将一些加密数据保存在 mysql 数据库中。这种情况很少发生。数据保存一次,很少更新。
2) PHP 页面从 mysql 数据库加载加密数据并将其用于内部逻辑。这个 php 页面必须能够在内部对其进行解密,但不能对其进行加密。
3) java 应用程序还从 mysql 数据库加载加密数据并对其进行解密以供内部使用。
换句话说,我有一个可以加密和解密数据的 Java 应用程序。而且我有一个必须能够解密数据的php单页。
目前,我必须使用新的加密算法重新执行此操作。我在 stackoverflow 进行了研究,许多人说要远离 MD5 和 DES。据我了解,我必须使用 AES,所以我想出了下面的 Java 代码。然而:
a)我不确定如何使用 php 解密,我通常使用 openSSL,但我不知道 php 中的等效算法名称。
<?php
ini_set('display_errors', 1);
$salt = 'nXdHqFg74g22g4Vq';
$key = $salt; // ? not sure
$data = 'uVJ+m3FGkzFTCQXpZJysmo53rWh5+5L9dWzyyD8xues=';
$method = "AES-256-CFB"; //not sure which
//openssl_decrypt ( string $data , string $method , string $key [, int $options = 0 [, string $iv = "" [, string $tag = "" [, string $aad = "" ]]]] ) : string
echo openssl_decrypt($data, "AES-256-CFB", $key);
?>
b)这对于一般用途是否足够安全?我不需要任何足够安全的东西,因为这些数据主要通过 https 传输。
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.iv.IvGenerator;
import org.jasypt.iv.StringFixedIvGenerator;
public class MyCryptoTest {
//private static final byte[] key = "nXdHqFg74g22g4Vq".getBytes();
private static final byte[] key = {110, 88, 100, 72, 113, 70, 103, 55, 52, 103, 50, 50, 103, 52, 86, 113};
private static PooledPBEStringEncryptor textCryptor = new PooledPBEStringEncryptor();
public static void main(String args[]) throws Exception {
//System.out.println(Arrays.toString(key));
//System.out.println(Arrays.toString("nXdHqFg74g22g4Vq".getBytes(Charset.forName("UTF-8"))));
String input = "stackoverflow";
String x = encrypt(input);
String y = decrypt(x);
System.out.println(x);
System.out.println(y);
System.out.println("Test Result: " + input.equals(y));
}
static {
IvGenerator ivGenerator = new StringFixedIvGenerator("some_random_word?");
textCryptor.setPoolSize(2);
textCryptor.setPassword(new String(key));
textCryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256");
textCryptor.setIvGenerator(ivGenerator);
}
public static String encrypt(String strClearText) throws Exception {
String strData = "";
try {
strData = textCryptor.encrypt(strClearText);
} catch (Exception ex) {
ex.printStackTrace();
throw new Exception(ex);
}
return strData;
}
public static String decrypt(String strEncrypted) throws Exception {
String strData = "";
try {
//System.out.println(strEncrypted);
strData = textCryptor.decrypt(strEncrypted);
} catch (Exception ex) {
throw new Exception(ex);
}
return strData;
}
}
参考文献中的重要引述:
理想情况下,您应该远离 DES,并且由于这种填充将成为 PHP 中的一个问题,为什么不看看您是否可以将加密算法更改为不那么麻烦且更安全的东西呢?
为了帮助您可以显示此页面:http ://www.ietf.org/rfc/rfc4772.txt ,其中简洁地表示 DES 容易受到暴力攻击,因此已被弃用并被 AES 取代。
社区♦ 111 银徽章于 2013 年 12 月 17 日 17:15 回答
詹姆斯·布莱克
MD5 和 DES 都存在已知漏洞,不应使用。– SLaks 2012 年 4 月 24 日 14:45
MD5 实际上适用于密钥派生,单个 DES 仅适用于实时、短期加密目的(基本上永远不会)。当然,两者都应该避免,尤其是当你不知道自己在做什么的时候。– Maarten Bodewes 2012 年 4 月 25 日 20:06
参考:
解决方案
关于Jasypt代码,必须考虑以下几点:
PBEWithHMACSHA512AndAES_256
使用PBKDF2,即通过摘要、密码、盐和迭代计数来导出加密/解密密钥,即解密也需要这些参数。算法和摘要可以直接导出:AES-256 和 SHA-512。作为操作模式应用CBC。由于随机生成的盐,发布的代码每次都会生成不同的密文。用户定义的盐可以传递给类似于 IV的
PooledPBEStringEncryptor
实例:textCryptor
textCryptor.setSaltGenerator(new StringFixedSaltGenerator(<YourSalt>));
Jasypt使用块大小(AES 为 16 字节)作为盐大小。较小的盐会导致异常,较大的盐会被简单地截断。
- IV 的处理类似于盐:较小的 IV 会导致异常,较大的 IV 会被截断。
- 如果没有用 , 显式设置迭代计数
PooledPBEStringEncryptor#setKeyObtentionIterations(<iteration count>)
,1000
则默认使用。 - Jasypt需要一个 ASCII 字符串作为密码(只是为了完整性,因为发布的代码也是如此)。
使用Salt A16bytesSalt_012
Jasypt代码提供以下密文:. 这个密文可以用 PHP 解密,如下所示:Lg01eeYnujbof0Wy9rs3XQ==
hash_pbkdf2
<?php
$salt = 'A16bytesSalt_012'; // First 16 bytes of the salt used in Jasypt code
$iv = 'some_random_word'; // First 16 bytes of the IV used in Jasypt code
$iterations = 1000; // Jasypt default
$password = array(110, 88, 100, 72, 113, 70, 103, 55, 52, 103, 50, 50, 103, 52, 86, 113); // Password used in Jasypt code
$password = implode(array_map("chr", $password));
$key = hash_pbkdf2("sha512", $password, $salt, $iterations, 32, TRUE);
$data = 'Lg01eeYnujbof0Wy9rs3XQ=='; // Ciphertext from Jasypt code
$method = "aes-256-cbc"; // Algorithm and mode used in Jasypt code
echo openssl_decrypt($data, $method, $key, 0, $iv);
?>
推荐阅读
- kotlin - 在 Kotlin 中隐藏基类构造函数参数
- python - 表输入参数和标量输出参数
- java - 什么是隐藏堆栈帧?
- php - 如何使用 for 循环使用多维索引数组?
- git - 适用于非常小的开发团队的 GIT 功能分支策略
- javascript - 确认数据是否已呈现的方法
- php - JQUERY AJAX GET 和 POST 访问不同的文件?
- java - Spring boot、ElasticSearch 和 TestContainers 集成测试。拒绝连接
- javascript - 使用模型 [Angular] 的嵌套对象填充选择下拉列表
- java - Android Studio 的模拟器摄像头倒置打开?