我正在尝试用openssl在php中使用pbkdf2withhmacsha512。但我不能创建与java创建的加密字符串相同的字符串。我试图加密的数据是atom insta pay。在下面提到的java代码中,我得到的是vnegn6vndj3z4wj4u3+z1g==但是在php中得到的是jquby9xcf+g9yasdnkq7cq==这是完全不同的。
// Java code
import java.util.logging.Logger;
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;
public class myEncryption {
static Logger log = Logger.getLogger(myEncryption.class.getName());
private static int pswdIterations = 65536;
private static int keySize = 256;
private static final byte[] ivBytes = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
public static String encrypt(String plainText, String key) {
try {
byte[] saltBytes = key.getBytes("UTF-8");
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
PBEKeySpec spec = new PBEKeySpec(key.toCharArray(), saltBytes, pswdIterations, keySize);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
IvParameterSpec localIvParameterSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(1, secret, localIvParameterSpec);
byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
return byteToHex(encryptedTextBytes);
}catch (Exception e) {
log.info("Exception while encrypting data:" + e.toString());
}
return null;
}
public static String decrypt(String encryptedText, String key) {
try {
byte[] saltBytes = key.getBytes("UTF-8");
byte[] encryptedTextBytes = hex2ByteArray(encryptedText);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
PBEKeySpec spec = new PBEKeySpec(key.toCharArray(), saltBytes, pswdIterations, keySize);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
IvParameterSpec localIvParameterSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(2, secret, localIvParameterSpec);
byte[] decryptedTextBytes = (byte[]) null;
decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
return new String(decryptedTextBytes);
}catch (Exception e) {
log.info("Exception while decrypting data:" + e.toString());
}
return null;
}
private static String byteToHex(byte[] byData) {
StringBuffer sb = new StringBuffer(byData.length * 2);
for (int i = 0; i < byData.length; ++i) {
int v = byData[i] & 0xFF;
if (v < 16)
sb.append('0');
sb.append(Integer.toHexString(v));
}
return sb.toString().toUpperCase();
}
private static byte[] hex2ByteArray(String sHexData) {
byte[] rawData = new byte[sHexData.length() / 2];
for (int i = 0; i < rawData.length; ++i) {
int index = i * 2;
int v = Integer.parseInt(sHexData.substring(index, index + 2), 16);
rawData[i] = (byte) v;
}
return rawData;
}
}
//PHP code
$method = "AES-256-CBC";
$salt = 'A4476C2062FFA58980DC8F79EB6A799E';
$key = 'A4476C2062FFA58980DC8F79EB6A799E';
$data = 'Demo String';
//Converting Array to bytes
$iv = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
$chars = array_map("chr", $iv);
$IVbytes = join($chars);
$salt1 = mb_convert_encoding($salt, "UTF-8"); //Encoding to UTF-8
$key1 = mb_convert_encoding($key, "UTF-8"); //Encoding to UTF-8
//SecretKeyFactory Instance of PBKDF2WithHmacSHA512 Java Equivalent
$hash = openssl_pbkdf2($key1,$salt1,'256','65536', 'sha512');
$encrypted = openssl_encrypt($data, $method, $hash, OPENSSL_RAW_DATA, $IVbytes);
echo base64_encode($encrypted);
1条答案
按热度按时间cczfrluj1#
php解决方案比java端更“简单”,可以使用key和salt作为直接输入(无需转换它们)。
当您想比较base64编码的密文时,示例代码返回base64编码的密文,而不是java程序发出的十六进制字符串。
这是具有相同结果的输出:
安全警告:您的代码使用的是静态salt和iv,这使得加密不安全(我希望这只是为了演示)。
代码如下: