【问题标题】:JAVA to PHP 7 EncryptionJAVA 到 PHP 7 加密
【发布时间】:2019-09-18 21:32:37
【问题描述】:

我想将加密/解密从 JAVA 复制到 PHP。但我的问题结果不匹配。我对java一无所知,所以我试图理解java中的每一行代码并用PHP编写。

JAVA


    secretkey: thisisasecretkey
    import java.security.MessageDigest;
    import java.util.Arrays;
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;

    import org.apache.commons.codec.binary.Base64;

    public class TDESEncrypter {

    public String _encrypt(String message, String secretKey) throws Exception {
    
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] digestOfPassword = md.digest(secretKey.getBytes("utf-8"));
        byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
            
        SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        Cipher cipher = Cipher.getInstance("DESede");
        cipher.init(Cipher.ENCRYPT_MODE, key);
            
        byte[] plainTextBytes = message.getBytes("utf-8");
        byte[] buf = cipher.doFinal(plainTextBytes);
        byte [] base64Bytes = Base64.encodeBase64(buf);
        String base64EncryptedString = new String(base64Bytes);
            
        return base64EncryptedString;
    }

    public String _decrypt(String encryptedText, String secretKey) throws Exception {
    
        byte[] message = Base64.decodeBase64(encryptedText.getBytes("utf-8"));
            
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] digestOfPassword = md.digest(secretKey.getBytes("utf-8"));
        byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
        SecretKey key = new SecretKeySpec(keyBytes, "DESede");
            
        Cipher decipher = Cipher.getInstance("DESede");
        decipher.init(Cipher.DECRYPT_MODE, key);
            
        byte[] plainText = decipher.doFinal(message);
            
        return new String(plainText, "UTF-8");
    }
   
}

以下是使用 java 的步骤,可能有助于在 PHP 中复制函数。

  1. 使用 sha1 创建哈希
  2. 使用 utf-8 编码将密钥(从凭证)转换为字节数组
  3. 用 xeroes、截断或用零填充(如有必要)填充第 2 步,使副本的指定长度为 24
  4. 使用 DESede 使用 step3 中的密钥字节初始化 Secretkey

  5. 使用 DESede 实例创建密码

  6. 初始化密码模式以使用步骤 4 中的密钥进行加密
  7. 将要加密的数据(用户名/密码)转换为 utf-8 编码的字节数组
  8. 使用步骤 6 密码加密步骤 7
  9. 将 step8 编码为 base 64 格式
  10. 将 step9 转换为最终字符串加密消息的字符串

到目前为止我做了什么,

function encrypt($data, $secret)  { 



    $key = sha1(utf8_encode($secret), true); <-- Step 1 & 2
    $iv = utf8_encode("jvz8bUAx"); <-- Do I use initialise vector on it?

    $key .= substr($key, 0, 8); 

    $method = 'des-ede3-cbc'; //<-- Is this cypher method correct from the above?


    if (strlen($data) % 8) {
        $data = str_pad($data, strlen($data) + 8 - strlen($data) % 8, "\0");
    }

    $encrypted = openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); //Force zero padding.

    $encrypted = urlencode(base64_encode($encrypted)); // Added the urlencode.....
    return $encrypted;
} 

【问题讨论】:

  • 如果您不向我们展示原始 Java 代码,我们无能为力 ????
  • 如果您提供原始数据以及用于在 JAVA 中生成样本的“秘密”,也会很有帮助。但我想如果我们有 JAVA 代码,我们可以创建自己的...但是我们将不得不运行 JAVA...ai...
  • 并且还向我们展示了您在 PHP 中得到了什么。
  • @RealSkeptic 我认为代码就在那里......对我来说看起来像 PHP。或者这不是你的意思?
  • 不,我指的是 PHP 给出的 结果

标签: java php encryption encryption-symmetric 3des


【解决方案1】:

在 Java 代码中,加密算法指定为DESede。这对应于DESede/ECB/PKCS5Padding,即使用 ECB 模式和 PKCS5 填充。这意味着 PHP 代码:

  • des-ede3 必须申请
  • 必须删除与 IV 相关的所有代码部分(因为 ECB 模式不使用 IV)
  • 必须删除自定义填充(绝不是 PKCS5-Padding)(因为 openssl_encrypt 默认使用 PKCS5 填充)

在 Java 代码中,SHA1 哈希(大小为 20 字节)通过附加 0 值扩展为 24 字节。这个扩展也必须在 PHP 代码中完成。

Java _encrypt 方法的一种可能的 PHP 对应物是:

function encrypt($data, $secret)  {
    $key = sha1(mb_convert_encoding($secret, "UTF-8"), true);                   // Create SHA-1 hash (20 byte) 
    $key = str_pad($key, 24, "\0");                                             // Extend to 24 byte by appending 0-values (would also happen automatically on openssl_encrypt-call)
    $encrypted = openssl_encrypt($data, 'DES-EDE3', $key, OPENSSL_RAW_DATA);    // Encryption: DESede (24 byte key), ECB-mode, PKCS5-Padding
    return base64_encode($encrypted);                                           // Base64-encoding
}

最后:Java 代码有很多缺点,例如

  • 使用三重 DES。更好的选择是 AES,参见例如here
  • 使用了 ECB 模式,这本身就是不安全的,参见例如here。更好的选择是 CBC 或 GCM(后者在 AES 下)。
  • SHA-1 用作 KDF(它给出了一个太短的密钥,20 个字节而不是实际需要的 24 个字节)。更好的选择是PBKDF2

后者只是为了完整性,因为它可能是由于任何原因无法更改的遗留代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 2018-01-20
    • 2013-03-16
    • 2013-02-01
    • 2016-01-31
    • 2012-03-28
    • 1970-01-01
    相关资源
    最近更新 更多