Java 相当于 PHP 三重 DES ECB encryption/decryption
Java equivalent for PHP Triple DES ECB encryption/decryption
我有一个下面的 PHP 函数,我想在 Java 中实现,但运气不好,我无法获得相同的输出:
function encryptText( $plainText, $key )
{
$mcopen = mcrypt_module_open (MCRYPT_TripleDES, "", MCRYPT_MODE_ECB,"");
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($mcopen), MCRYPT_RAND);
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$cryptedHash = '';
if (mcrypt_generic_init($td, $key, $iv) != -1)
{
$cryptedHash = mcrypt_generic($td, $plainText);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}
return base64_encode($cryptedHash);
}
这是我的 java 找到的代码 here :
public static String encrypt(String message, String key) throws Exception {
final MessageDigest md = MessageDigest.getInstance("md5");
final byte[] digestOfPassword = md.digest(key.getBytes("utf-8"));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
final SecretKey keyz = new SecretKeySpec(keyBytes, "DESede");
final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keyz, iv);
final byte[] plainTextBytes = message.getBytes("utf-8");
final byte[] cipherText = cipher.doFinal(plainTextBytes);
final String encodedCipherText = new sun.misc.BASE64Encoder().encode(cipherText);
return encodedCipherText;
}
你有几个问题。
既然要使用ECB模式,那么就需要指定ECB模式。 CBC是一种不同的模式。
您不是 运行 您在 PHP 代码中通过 MD5 的密钥,因此您不应该在 Java 中这样做。
ECB 或 CBC 模式中的块密码需要填充才能加密任意消息。 Mcrypt 默认使用零填充,但您在 Java 中指定了 PKCS#5 填充。由于默认的 Sun 提供程序没有实现 ZeroPadding,您需要通过指定 "NoPadding" 并自己实现零填充来自己实现它,或者使用 BouncyCastle 提供程序:Cipher.getInstance("DESede/ECB/ZeroPadding", "BC")
.
其他注意事项:
切勿使用 ECB 模式。它在语义上不安全。如果你用同一个密钥对同一条消息加密两次,攻击者可以很容易地看到你再次加密了同一条消息(或消息的相同部分)。
已解决,解决办法:
public static String cryptBC(String data, String key) throws Exception{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
byte[] input = data.getBytes();
byte[] keyBytes = key.getBytes() ;
SecretKeySpec skey = new SecretKeySpec(keyBytes, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding", "BC");
if(input.length % 8 != 0){
byte[] padded = new byte[input.length + 8 - (input.length % 8)];
System.arraycopy(input, 0, padded, 0, input.length);
input = padded;
}
System.out.println("input : " + new String(input));
cipher.init(Cipher.ENCRYPT_MODE, skey);
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
return new String(Base64.encodeBase64(cipherText));
}
我有一个下面的 PHP 函数,我想在 Java 中实现,但运气不好,我无法获得相同的输出:
function encryptText( $plainText, $key )
{
$mcopen = mcrypt_module_open (MCRYPT_TripleDES, "", MCRYPT_MODE_ECB,"");
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size ($mcopen), MCRYPT_RAND);
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$cryptedHash = '';
if (mcrypt_generic_init($td, $key, $iv) != -1)
{
$cryptedHash = mcrypt_generic($td, $plainText);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}
return base64_encode($cryptedHash);
}
这是我的 java 找到的代码 here :
public static String encrypt(String message, String key) throws Exception {
final MessageDigest md = MessageDigest.getInstance("md5");
final byte[] digestOfPassword = md.digest(key.getBytes("utf-8"));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
final SecretKey keyz = new SecretKeySpec(keyBytes, "DESede");
final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keyz, iv);
final byte[] plainTextBytes = message.getBytes("utf-8");
final byte[] cipherText = cipher.doFinal(plainTextBytes);
final String encodedCipherText = new sun.misc.BASE64Encoder().encode(cipherText);
return encodedCipherText;
}
你有几个问题。
既然要使用ECB模式,那么就需要指定ECB模式。 CBC是一种不同的模式。
您不是 运行 您在 PHP 代码中通过 MD5 的密钥,因此您不应该在 Java 中这样做。
ECB 或 CBC 模式中的块密码需要填充才能加密任意消息。 Mcrypt 默认使用零填充,但您在 Java 中指定了 PKCS#5 填充。由于默认的 Sun 提供程序没有实现 ZeroPadding,您需要通过指定 "NoPadding" 并自己实现零填充来自己实现它,或者使用 BouncyCastle 提供程序:
Cipher.getInstance("DESede/ECB/ZeroPadding", "BC")
.
其他注意事项:
切勿使用 ECB 模式。它在语义上不安全。如果你用同一个密钥对同一条消息加密两次,攻击者可以很容易地看到你再次加密了同一条消息(或消息的相同部分)。
已解决,解决办法:
public static String cryptBC(String data, String key) throws Exception{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
byte[] input = data.getBytes();
byte[] keyBytes = key.getBytes() ;
SecretKeySpec skey = new SecretKeySpec(keyBytes, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding", "BC");
if(input.length % 8 != 0){
byte[] padded = new byte[input.length + 8 - (input.length % 8)];
System.arraycopy(input, 0, padded, 0, input.length);
input = padded;
}
System.out.println("input : " + new String(input));
cipher.init(Cipher.ENCRYPT_MODE, skey);
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
ctLength += cipher.doFinal(cipherText, ctLength);
return new String(Base64.encodeBase64(cipherText));
}