openssl_encrypt aes 256,散列在 java
openssl_encrypt aes 256 with hash in java
来自下面的php加密函数:
$data = "1212312121447";
$cipher = "aes-256-ofb";
$secretKey = "aNdRgUjXn2r5u8x/A?D(G+KbPeShVmYp";
$ivLength = openssl_cipher_iv_length($cipher);
$keyOfb = substr(hash('sha256', $secretKey, true), 0, 32);
$ivOfb = substr($keyOfb, 0, $ivLength);
$encryptedOfb = openssl_encrypt($data, $cipher, $keyOfb, OPENSSL_RAW_DATA, $ivOfb);
echo "ofb-encrypted: " . base64_encode($ivOfb . $encryptedOfb);
加密结果为MyFTCJx8RPzOx7h8QNxEtQgeiNIRwnrJ+uc0V70=
我试过在 Java 中这样写这个函数:
public static SecretKeySpec hashKey(String key){
String keyPass = key;
SecretKeySpec result = null;
try{
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(keyPass.getBytes());
byte[] AesKeyData = Arrays.copyOfRange(md.digest(), 0, 32);
SecretKeySpec keySpec = new SecretKeySpec(AesKeyData, "AES");
result = keySpec;
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return result;
}
public static String encryptedOFB(String inp){
String result = "";
String key = "aNdRgUjXn2r5u8x/A?D(G+KbPeShVmYp";
SecretKeySpec keyHashed = hashKey(key);
try{
byte[] initVectorSize = Arrays.copyOfRange(keyHashed.toString().getBytes(), 0, 16);
Cipher cipher = Cipher.getInstance("AES/OFB/NoPadding");
IvParameterSpec iv = new IvParameterSpec(initVectorSize, 0, cipher.getBlockSize());
cipher.init(Cipher.ENCRYPT_MODE, keyHashed, iv);
byte[] encrypted = cipher.doFinal(inp.getBytes());
ByteArrayOutputStream conc = new ByteArrayOutputStream();
conc.write(initVectorSize);
conc.write(encrypted);
byte[] concEnc = conc.toByteArray();
result = new String(Base64.getEncoder().encode(concEnc));
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return result;
}
结果是amF2YXguY3J5cHRvLnNwZYUmrJNv8ycvLua0O9g=
为什么我的 java 函数 return 与 php 的结果不同?
以及如何修复 java 函数以获得与 php 相同的结果?
谢谢。
IV 确定错误。您必须使用 keyHashed.getEncoded()
而不是 keyHashed.toString().getBytes()
。然后你得到 PHP 代码的结果。
除此之外,您的密钥派生是不安全的:由于 IV 是密钥的前 16 个字节,相同的密码也意味着相同的 key/IV 对,这是不安全的。对于密码,最好结合使用可靠的密钥派生函数和随机生成的盐。 IV 可以与密钥一起推断或独立随机生成。 Salt(或 IV)不是秘密的,可以与密文一起传递以进行解密,通常是串联的。
编码时(例如inp.getBytes()
),应始终指定编码(例如StandardCharsets.UTF_8
)。与解码 (new String(..., StandardCharsets.UTF_8)
) 类似。否则使用默认编码,会导致跨平台问题。
来自下面的php加密函数:
$data = "1212312121447";
$cipher = "aes-256-ofb";
$secretKey = "aNdRgUjXn2r5u8x/A?D(G+KbPeShVmYp";
$ivLength = openssl_cipher_iv_length($cipher);
$keyOfb = substr(hash('sha256', $secretKey, true), 0, 32);
$ivOfb = substr($keyOfb, 0, $ivLength);
$encryptedOfb = openssl_encrypt($data, $cipher, $keyOfb, OPENSSL_RAW_DATA, $ivOfb);
echo "ofb-encrypted: " . base64_encode($ivOfb . $encryptedOfb);
加密结果为MyFTCJx8RPzOx7h8QNxEtQgeiNIRwnrJ+uc0V70=
我试过在 Java 中这样写这个函数:
public static SecretKeySpec hashKey(String key){
String keyPass = key;
SecretKeySpec result = null;
try{
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(keyPass.getBytes());
byte[] AesKeyData = Arrays.copyOfRange(md.digest(), 0, 32);
SecretKeySpec keySpec = new SecretKeySpec(AesKeyData, "AES");
result = keySpec;
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return result;
}
public static String encryptedOFB(String inp){
String result = "";
String key = "aNdRgUjXn2r5u8x/A?D(G+KbPeShVmYp";
SecretKeySpec keyHashed = hashKey(key);
try{
byte[] initVectorSize = Arrays.copyOfRange(keyHashed.toString().getBytes(), 0, 16);
Cipher cipher = Cipher.getInstance("AES/OFB/NoPadding");
IvParameterSpec iv = new IvParameterSpec(initVectorSize, 0, cipher.getBlockSize());
cipher.init(Cipher.ENCRYPT_MODE, keyHashed, iv);
byte[] encrypted = cipher.doFinal(inp.getBytes());
ByteArrayOutputStream conc = new ByteArrayOutputStream();
conc.write(initVectorSize);
conc.write(encrypted);
byte[] concEnc = conc.toByteArray();
result = new String(Base64.getEncoder().encode(concEnc));
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return result;
}
结果是amF2YXguY3J5cHRvLnNwZYUmrJNv8ycvLua0O9g=
为什么我的 java 函数 return 与 php 的结果不同?
以及如何修复 java 函数以获得与 php 相同的结果?
谢谢。
IV 确定错误。您必须使用 keyHashed.getEncoded()
而不是 keyHashed.toString().getBytes()
。然后你得到 PHP 代码的结果。
除此之外,您的密钥派生是不安全的:由于 IV 是密钥的前 16 个字节,相同的密码也意味着相同的 key/IV 对,这是不安全的。对于密码,最好结合使用可靠的密钥派生函数和随机生成的盐。 IV 可以与密钥一起推断或独立随机生成。 Salt(或 IV)不是秘密的,可以与密文一起传递以进行解密,通常是串联的。
编码时(例如inp.getBytes()
),应始终指定编码(例如StandardCharsets.UTF_8
)。与解码 (new String(..., StandardCharsets.UTF_8)
) 类似。否则使用默认编码,会导致跨平台问题。