PHP openssl_decrypt/encrypt => 到 Java AES 256 的翻译
Translation of PHP openssl_decrypt/encrypt => to Java AES 256
对于一个项目,我必须在 Java 中翻译 PHP 函数 openssl_decrypt 和 openssl_encrypt。
PHP 函数是这样调用的:
$cryptedValue = openssl_encrypt($dataSet[$cryptedFieldName], $this->getCryptOption('method'), $this->getCryptOption('hash'), false, $this->getCryptOption('vector'));
或:
$uncryptedValue = openssl_decrypt($dataSet[$cryptedFieldName], $this->getCryptOption('method'), $this->getCryptOption('hash'), false, $this->getCryptOption('vector'));
使用 cryptedFieldName = 要加密或解密的字符串,并且:
'method' = 'aes-256-cfb'
'hash' = 'GzH7vYfW2mp4TZKFx2UKuFvk4nPWy6KZyPSALFePVsWZp8kHhqDHfheZEABB5FAUdYQzbL25sPU9PbjHVHw8QgR2E832rHPKu9bV2HRzxLFWXV85j6CSGMeGpLks9duv'
'vector' = 'zvChhBgQ16yCBghn'
所以,我将之前的 PHP 代码翻译成下面的 Java 代码:
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import java.nio.charset.Charset;
import java.lang.reflect.Field;
public class Cryptage_EAS {
public String decrypt(String encryptedText, String salt, String hash, String vector) throws Exception {
// Autoriser le cryptage EAS 256
try {
Field field = Class.forName("javax.crypto.JceSecurity").
getDeclaredField("isRestricted");
field.setAccessible(true);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception ex) {
ex.printStackTrace();
}
// Set en tableau de byte des différentes entrées
byte[] vectorBytes = vector.getBytes(Charset.forName("UTF-8"));
byte[] saltBytes = salt.getBytes(Charset.forName("UTF-8"));
byte[] encryptedTextBytes = Base64.decodeBase64(encryptedText);
// Création de la clé
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(hash.toCharArray(), saltBytes, 1, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// Décryptage
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(vectorBytes));
return new String(cipher.doFinal(encryptedTextBytes), "UTF-8");
}
public String encrypt(String textToCrypt, String salt, String hash, String vector) throws Exception {
// Autoriser le cryptage EAS 256
try {
Field field = Class.forName("javax.crypto.JceSecurity").
getDeclaredField("isRestricted");
field.setAccessible(true);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception ex) {
ex.printStackTrace();
}
// Set en tableau de byte des différentes entrées
byte[] vectorBytes = vector.getBytes(Charset.forName("UTF-8"));
byte[] saltBytes = salt.getBytes(Charset.forName("UTF-8"));
// Création de la clé
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(hash.toCharArray(), saltBytes, 1, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// Cryptage
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(vectorBytes));
byte[] encryptedTextBytes = cipher.doFinal(textToCrypt.getBytes("UTF-8"));
return new Base64().encodeAsString(encryptedTextBytes);
}
}
主要class:
Cryptage_EAS c_EAS = new Cryptage_EAS();
String hash = "GzH7vYfW2mp4TZKFx2UKuFvk4nPWy6KZyPSALFePVsWZp8kHhqDHfheZEABB5FAUdYQzbL25sPU9PbjHVHw8QgR2E832rHPKu9bV2HRzxLFWXV85j6CSGMeGpLks9duv";
String salt = "SelDeMerFin";
String vector = "zvChhBgQ16yCBghn";
String strToCrypt = "The Answer Is 42";
String encryptedText = c_EAS.encrypt(strToCrypt, salt, hash, vector);
System.out.println("Encrypted : "+c_EAS.encrypt(strToCrypt, salt, hash, vector));
System.out.println("Decrypted : "+c_EAS.decrypt(encryptedText, salt, hash, vector));
我的 Java 代码有效,但我不确定它是否与 openssl_decrypt 和 openssl_encrypt 后面的编码完全一致。
例如,在 PHP 中不需要盐,但在我的 Java 函数中是必需的。
你觉得我的代码怎么样?是否可以在 PHP 函数中添加一个 Salt 参数?那么,它会产生相同的结果吗?我的主要问题终于来了:我对 PHP 函数的翻译对您来说似乎是正确的吗?我应该如何处理额外的和强制性的额外 salt 参数?
谢谢。
我真的不知道你为什么在 Java 中实现 PBKDF2。这与 openssl_encrypt
所做的相去甚远。事实上,如果您阅读过文档中的 first comment,您应该已经看到 pass
参数实际上是密钥而不是某种密码。如果你想要 AES-256,你需要为 openssl_encrypt
提供一个 32 字节的密钥,这将是你的 "hash" 的前 32 个字节:"GzH7vYfW2mp4TZKFx2UKuFvk4nPWy6KZ"
对于一个项目,我必须在 Java 中翻译 PHP 函数 openssl_decrypt 和 openssl_encrypt。
PHP 函数是这样调用的:
$cryptedValue = openssl_encrypt($dataSet[$cryptedFieldName], $this->getCryptOption('method'), $this->getCryptOption('hash'), false, $this->getCryptOption('vector'));
或:
$uncryptedValue = openssl_decrypt($dataSet[$cryptedFieldName], $this->getCryptOption('method'), $this->getCryptOption('hash'), false, $this->getCryptOption('vector'));
使用 cryptedFieldName = 要加密或解密的字符串,并且:
'method' = 'aes-256-cfb'
'hash' = 'GzH7vYfW2mp4TZKFx2UKuFvk4nPWy6KZyPSALFePVsWZp8kHhqDHfheZEABB5FAUdYQzbL25sPU9PbjHVHw8QgR2E832rHPKu9bV2HRzxLFWXV85j6CSGMeGpLks9duv'
'vector' = 'zvChhBgQ16yCBghn'
所以,我将之前的 PHP 代码翻译成下面的 Java 代码:
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import java.nio.charset.Charset;
import java.lang.reflect.Field;
public class Cryptage_EAS {
public String decrypt(String encryptedText, String salt, String hash, String vector) throws Exception {
// Autoriser le cryptage EAS 256
try {
Field field = Class.forName("javax.crypto.JceSecurity").
getDeclaredField("isRestricted");
field.setAccessible(true);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception ex) {
ex.printStackTrace();
}
// Set en tableau de byte des différentes entrées
byte[] vectorBytes = vector.getBytes(Charset.forName("UTF-8"));
byte[] saltBytes = salt.getBytes(Charset.forName("UTF-8"));
byte[] encryptedTextBytes = Base64.decodeBase64(encryptedText);
// Création de la clé
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(hash.toCharArray(), saltBytes, 1, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// Décryptage
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(vectorBytes));
return new String(cipher.doFinal(encryptedTextBytes), "UTF-8");
}
public String encrypt(String textToCrypt, String salt, String hash, String vector) throws Exception {
// Autoriser le cryptage EAS 256
try {
Field field = Class.forName("javax.crypto.JceSecurity").
getDeclaredField("isRestricted");
field.setAccessible(true);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception ex) {
ex.printStackTrace();
}
// Set en tableau de byte des différentes entrées
byte[] vectorBytes = vector.getBytes(Charset.forName("UTF-8"));
byte[] saltBytes = salt.getBytes(Charset.forName("UTF-8"));
// Création de la clé
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(hash.toCharArray(), saltBytes, 1, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// Cryptage
Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(vectorBytes));
byte[] encryptedTextBytes = cipher.doFinal(textToCrypt.getBytes("UTF-8"));
return new Base64().encodeAsString(encryptedTextBytes);
}
}
主要class:
Cryptage_EAS c_EAS = new Cryptage_EAS();
String hash = "GzH7vYfW2mp4TZKFx2UKuFvk4nPWy6KZyPSALFePVsWZp8kHhqDHfheZEABB5FAUdYQzbL25sPU9PbjHVHw8QgR2E832rHPKu9bV2HRzxLFWXV85j6CSGMeGpLks9duv";
String salt = "SelDeMerFin";
String vector = "zvChhBgQ16yCBghn";
String strToCrypt = "The Answer Is 42";
String encryptedText = c_EAS.encrypt(strToCrypt, salt, hash, vector);
System.out.println("Encrypted : "+c_EAS.encrypt(strToCrypt, salt, hash, vector));
System.out.println("Decrypted : "+c_EAS.decrypt(encryptedText, salt, hash, vector));
我的 Java 代码有效,但我不确定它是否与 openssl_decrypt 和 openssl_encrypt 后面的编码完全一致。 例如,在 PHP 中不需要盐,但在我的 Java 函数中是必需的。
你觉得我的代码怎么样?是否可以在 PHP 函数中添加一个 Salt 参数?那么,它会产生相同的结果吗?我的主要问题终于来了:我对 PHP 函数的翻译对您来说似乎是正确的吗?我应该如何处理额外的和强制性的额外 salt 参数? 谢谢。
我真的不知道你为什么在 Java 中实现 PBKDF2。这与 openssl_encrypt
所做的相去甚远。事实上,如果您阅读过文档中的 first comment,您应该已经看到 pass
参数实际上是密钥而不是某种密码。如果你想要 AES-256,你需要为 openssl_encrypt
提供一个 32 字节的密钥,这将是你的 "hash" 的前 32 个字节:"GzH7vYfW2mp4TZKFx2UKuFvk4nPWy6KZ"