Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用salt将Rijndael解密从PHP移植到Java_Java_Php_Encryption_Aes_Porting - Fatal编程技术网

用salt将Rijndael解密从PHP移植到Java

用salt将Rijndael解密从PHP移植到Java,java,php,encryption,aes,porting,Java,Php,Encryption,Aes,Porting,我在将php代码转换为java时遇到了问题。 以下是php代码: function decrypt($encrypted, $password, $salt='2#g+XK^Sc3"4ABXbvwF8CPD%en%;9,c(') { // Build a 256-bit $key which is a SHA256 hash of $salt and $password. $key = hash('SHA256', $salt . $password, true); //

我在将php代码转换为java时遇到了问题。 以下是php代码:

function decrypt($encrypted, $password, $salt='2#g+XK^Sc3"4ABXbvwF8CPD%en%;9,c(') {
    // Build a 256-bit $key which is a SHA256 hash of $salt and $password.
    $key = hash('SHA256', $salt . $password, true);
    // Retrieve $iv which is the first 22 characters plus ==, base64_decoded.
    $iv = base64_decode(substr($encrypted, 0, 22) . '==');
    // Remove $iv from $encrypted.
    $encrypted = substr($encrypted, 22);
    // Decrypt the data.  rtrim won't corrupt the data because the last 32 characters are the md5 hash; thus any \0 character has to be padding.
    $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($encrypted), MCRYPT_MODE_CBC, $iv), "\0\4");
    // Retrieve $hash which is the last 32 characters of $decrypted.
    $hash = substr($decrypted, -32);
    // Remove the last 32 characters from $decrypted.
    $decrypted = substr($decrypted, 0, -32);
    // Integrity check.  If this fails, either the data is corrupted, or the password/salt was incorrect.
    if (md5($decrypted) != $hash) return false;
    // Yay!
    return $decrypted;
}
这是我的java代码,我已经完成了。但这是行不通的

private static String password = "AxkbK2jZ5PMaeNZWfn8XRLUWF2waGwH2EkAXxBDU6aZ";
private static String salt = "2#g+XK^Sc3\"4ABXbvwF8CPD%en%;9,c(";
private static String text = "Fm+Zfufqe3DjRQtWcYdw9g9oXriDjrAkRrBLhEfu7fCtT4BzD0gw7D+8KxrcbbgJm26peTUWHU2k4YJ4KqCSRQN3NPzuXwlJ4mC4444Edg3Q==";

public String decrypt(String pass, String encr) {

    try {
        int i = 0;

        String key = hash();
        byte[] iv = Base64.decodeBase64(text.substring(0, 22) + "==");

        Cipher cipher = Cipher.getInstance("DES");
        SecretKeySpec keySpec = new SecretKeySpec(password.getBytes(), "DES");
        IvParameterSpec ivSpec = new IvParameterSpec(salt.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        ByteArrayInputStream fis = new ByteArrayInputStream(iv);
        CipherInputStream cis = new CipherInputStream(fis, cipher);
        ByteArrayOutputStream fos = new ByteArrayOutputStream();
        // decrypting
        byte[] b = new byte[8];
        while ((i = cis.read(b)) != -1) {
            fos.write(b, 0, i);
        }
        fos.flush();
        fos.close();
        cis.close();
        fis.close();

        return fos.toString();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

private String hash() {
    StringBuffer sb = new StringBuffer();

    try {
        MessageDigest md = null;
        md = MessageDigest.getInstance("SHA-256");
        md.update((password + salt).getBytes());
        byte byteData[] = md.digest();

        for (int i = 0; i < byteData.length; i++) {
            sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
        }
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } finally {
        return sb.toString();
    }

}
private static String password=“axkbk2jz5pmanzwfn8xrluwf2wagwh2ekaxxbdu6az”;
专用静态字符串salt=“2#g+XK^Sc3\”4ABXbvwF8CPD%en%;9,c(“;
私有静态字符串text=“Fm+zfufqe3djrqtwcydw9g9oxridjrakrblhefu7fctt4bzd0gw7d+8krcbgjm26petuwhu2k4yj4kqcsrqn3npzuxj4mc444edg3q=”;
公共字符串解密(字符串传递、字符串加密){
试一试{
int i=0;
String key=hash();
字节[]iv=Base64.decodeBase64(text.substring(0,22)+“=”;
Cipher Cipher=Cipher.getInstance(“DES”);
SecretKeySpec keySpec=新的SecretKeySpec(password.getBytes(),“DES”);
IvParameterSpec ivSpec=新的IvParameterSpec(salt.getBytes());
cipher.init(cipher.DECRYPT_模式,keySpec,ivSpec);
ByteArrayInputStream fis=新的ByteArrayInputStream(iv);
CipherInputStream cis=新的CipherInputStream(fis,密码);
ByteArrayOutputStream fos=新建ByteArrayOutputStream();
//解密
字节[]b=新字节[8];
而((i=cis.read(b))!=-1){
fos.写入(b,0,i);
}
fos.flush();
fos.close();
cis.close();
fis.close();
返回fos.toString();
}捕获(例外e){
e、 printStackTrace();
}
返回null;
}
私有字符串哈希(){
StringBuffer sb=新的StringBuffer();
试一试{
MessageDigest md=null;
md=MessageDigest.getInstance(“SHA-256”);
md.update((密码+salt).getBytes());
byte byteData[]=md.digest();
for(int i=0;i
您的代码有一些问题

  • MCRYPT\u RIJNDAEL\u 128
    是AES而不是DES。这是两种完全不同的算法
  • Cipher.getInstance(“DES”);
    可能默认为
    Cipher.getInstance(“DES/ECB/PKCS5Padding”);
    取决于默认的JCE提供程序
    • 欧洲央行和CBC完全不同
    • PHP PAD明文,带0x00字节,而添加(比较方法1和方法4)
    • 您需要使用
      Cipher.getInstance(“AES/CBC/NoPadding”);
      并删除尾随0x00和0x04字节
  • 您没有使用生成的
    密钥
    ,而是直接使用非密钥的密码。此外,您的密钥不应该是十六进制编码的,因为您在PHP中也使用原始密钥
  • 盐不是IV
  • 您并不是从恢复的明文末尾切掉散列来验证它

在您的原始PHP代码中,有些东西是值得一提的:

  • 现在单次通过SHA-256还不够好。您的密码需要非常长(50个以上随机字符)才能确保安全。使用PBKDF2、bcrypt、scrypt的成本很高,或者反复使用,以便能够使用更短的密码
  • 似乎IV实际上作为一个没有填充字节的Base64编码字符串附加到Base64编码的密文中。这是非常不寻常的,可能会导致误解
  • 使用MCrypt的零填充而不是利用
  • 检查明文的完整性是好的,但您应该检查密文的完整性,因为通常情况下更好。MD5也不够好。您应该至少使用HMAC-SHA256

    • 此外,
      md5($decrypted)!=$hash
      这里有太多错误。@Scott
      md5($decrypted)!=$hash
      有点好,因为它至少是一种类似于MAC-then-encrypt的完整性检查。encrypt-then-(实际-)MAC会更好。问题当然是它根本没有在Java代码中复制。我并不反对,我只是想补充一下。)