【问题标题】:Encrypt By javascript and decrypt by Java用javascript加密,用java解密
【发布时间】:2020-02-25 12:41:16
【问题描述】:

我在我的 react-native 应用程序中使用 AES 加密,如下所示

import CryptoJS from 'crypto-js' ;
encryptFun() {
    var data = "123456";
    var key  = CryptoJS.enc.Latin1.parse('1234567812345678');
    var iv   = CryptoJS.enc.Latin1.parse('1234567812345678');  
    var encrypted = CryptoJS.AES.encrypt(
      data,
      key,
      {iv:iv,mode:CryptoJS.mode.CBC,padding:CryptoJS.pad.ZeroPadding
    });
    console.log('encrypted: ' + encrypted) ;
    var decrypted = CryptoJS.AES.decrypt(encrypted,key,{iv:iv,padding:CryptoJS.pad.ZeroPadding});
    console.log('decrypted: '+decrypted.toString(CryptoJS.enc.Utf8));
  }

出来=加密:aK7+UX24ttBgfTnAndz9aQ==

以下是我在后端使用 java 获取解密的代码

 public static String desEncrypt() throws Exception {

        try
        {
            String data = "aK7+UX24ttBgfTnAndz9aQ==" ;
            String key = "1234567812345678";
            String iv = "1234567812345678";

            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(data);

            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original);
            return originalString;
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

输出=解密:= 123456[][][][][][][][][][]

Iam 像上面那样输出为 16 位。 我想要的输出应该只有 123456。

【问题讨论】:

标签: javascript java reactjs spring-boot react-native


【解决方案1】:

我建议你使用java.util.Base64 进行解码。以下是正确的。我还建议在return originalString 中使用 trim 看看是否可行。

public class Decrypt {

    public static void main(String[] args) {
        try
        {
            String data = "aK7+UX24ttBgfTnAndz9aQ==" ;
            String key = "1234567812345678";
            String iv = "1234567812345678";

            Decoder decoder = Base64.getDecoder();   
             byte[] encrypted1 = decoder.decode(data);

            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original);
            System.out.println(originalString.trim());
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【讨论】:

  • System.out.println(originalString + "<<");,你会看到鬼魂的;)
  • 感谢您展示这一点 :) 。我添加了一个 trim() 来解决这个问题。
【解决方案2】:

当您在 JS 中使用 zeros 填充时,您无法使用 NoPadding 进行解密,解决方案是对数组或字符串进行操作

  • 修剪数组

    int i = original .length - 1;
    while (i >= 0 && original [i] == 0) {
        --i;
    }
    return new String(Arrays.copyOf(original , i + 1));
    
  • 修剪字符串

    return new String(original).trim();
    
  • 手动删除zero

    return new String(original).replace("\0", "");
    

或者,似乎没有在 Java 中实现 ZeroPAdding (Cipher Documentation),请查看建议使用 CryptoJS.pad.PkcsHow Encrypt with AES CBC Zero Padding in Javascript and decrypt with Java

【讨论】:

  • 我认为在从字节数组转换为字符串之前删除填充的零字节会更好。
猜你喜欢
  • 1970-01-01
  • 2021-01-09
  • 2014-07-12
  • 1970-01-01
  • 2014-08-10
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 2011-04-29
相关资源
最近更新 更多