为了账号安全,请及时绑定邮箱和手机立即绑定

Java 256 位 AES 加密

Java 256 位 AES 加密

慕标5832272 2022-01-12 17:15:28
我需要为现金流实施 256 位 AES 加密我有 c# 答案,但答案不一样,对于新手,我不确定我的方向是否正确。这是我的代码public static void main(String[] args) {            String key = "12345678901234567890123456789012";            String hashIv = "1234567890123456";            String value = "MerchantID=3430112RespondType=JSONTimeStamp=1485232229Version=1.4MerchantOrderNo=S_1485232229Amt=40ItemDesc=UnitTest";            String result = encrypt(key, hashIv, value);            System.out.println(result);            System.out.println();            String sha256 = encrySha256("HashKey=" + key + "&" + result + "&HashIV=" + hashIv);            System.out.println(sha256.trim());        }    public static String encrypt(String hashKey, String hashIv, String text) {            try {                SecretKeySpec skeySpec = new SecretKeySpec(hashKey.getBytes("UTF-8"), "AES");                IvParameterSpec ivParameterSpec = new IvParameterSpec(hashIv.getBytes("UTF-8"));                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);                byte[] encrypted = cipher.doFinal((text.getBytes("UTF-8")));                String test = bytesToHex(encrypted);                return test.toLowerCase();                      } catch (Exception e) {                System.out.println(e.getMessage());            }            return null;        }   示例加密答案:ff91c8aa01379e4de621a44e5f11f72e4d25bdb1a18242db6cef9ef07d80b0165e476fd1d9acaa53170272c82d122961e1a0700a7427cfa1cf90db7f6d6593bbc93102a4d4b9b66d9974c13c31a7ab4bba1d4e0790f0cbbbd7ad64c6d3c8012a601ceaa808bff70f94a8efa5a4f984b9d41304ffd879612177c622f75f4214faencryptSha256 答案: EA0A6CC37F40C1EA5692E7CBB8AE097653DF3E91365E6A9CD7E91312413C7BB8
查看完整描述

2 回答

?
守着一只汪

TA贡献1872条经验 获得超3个赞

不同加密数据的原因是您比较不同的纯文本。在您的 Java 代码中,您加密纯文本


  MerchantID=3430112RespondType=JSONTimeStamp=1485232229Version=1.4MerchantOrderNo=S_1485232229Amt=40ItemDesc=UnitTest

并且您将加密数据与您的参考数据进行比较


  ff91c8aa01379e4de621a44e5f11f72e4d25bdb1a18242db6cef9ef07d80b0165e476fd1d9acaa53170272c82d122961e1a0700a7427cfa1cf90db7f6d6593bbc93102a4d4b9b66d9974c13c31a7ab4bba1d4e0790f0cbbbd7ad64c6d3c8012a601ceaa808bff70f94a8efa5a4f984b9d41304ffd879612177c622f75f4214fa

但是,这些参考数据对应的是不同的纯文本。后者您可以通过使用 C# DecryptAES256-method 解密参考数据轻松得出,该方法提供


  MerchantID=3430112&RespondType=JSON&TimeStamp=1485232229&Version=1.4&MerchantOrderNo=S_1485232229&Amt=40&ItemDesc=UnitTest

在这里,与 Java 代码中的纯文本相比,使用了& -delimiter。


如果您使用相同的纯文本,Java 加密和 C# EncryptAES256 方法提供相同的加密数据(假定相同的密钥、IV 和填充;对于后者,请参阅编辑部分)。


在以下测试用例中,使用了 Java 代码中的纯文本:


 encrypt("12345678901234567890123456789012", "1234567890123456", "MerchantID=3430112RespondType=JSONTimeStamp=1485232229Version=1.4MerchantOrderNo=S_1485232229Amt=40ItemDesc=UnitTest")


 EncryptAES256("MerchantID=3430112RespondType=JSONTimeStamp=1485232229Version=1.4MerchantOrderNo=S_1485232229Amt=40ItemDesc=UnitTest")

两者都提供加密数据:


 ff91c8aa01379e4de621a44e5f11f72ef45b7b9f9663d386da51af13f7f3b8f2b1ed4a3b7ac6b7783402193ea1d766e3046b6acf612d62568ccdbc475e5a14d114273735b069464dcc8281f4e5bf8486eb97d31602c3fe79cfe7140d2848413edad9d96fabf54d103f3d7a9b401c83fa5e4f17b10a280df10b3d61f23e69bbb8

这(如预期的那样)与您的参考数据不同(第一个块除外)。


编辑


关于填充还有第二个问题:您的 C# EncryptAES256-method 使用 C# AddPKCS7Padding-method 提供的自定义填充,填充为32 bytes的倍数。


相比之下,您的 Java 加密方法使用 PKCS5Padding 填充为16 bytes的倍数。


因此,如果纯文本的长度在 16 * n 字节和 16 * (n + 1) - 1 字节之间,甚至 n (0,2,4 ,...)。


对于奇数 n (1,3,5,...),加密数据是相同的。在上面的示例中,纯文本的字节数组有 116 个字节,即 n = 7 (112 <= 116 <= 127),因此加密数据是相同的。


如果 Java 加密方法应该使用与 C# EncryptAES256 方法相同的填充,您还必须实现类似的 Java 方法,例如:


private static byte[] addPKCS7Padding(byte[] data, int iBlockSize)

{

    int iLength = data.length;

    byte cPadding = (byte)(iBlockSize - (iLength % iBlockSize));

    byte[] output = new byte[iLength + cPadding];

    System.arraycopy(data, 0, output, 0, iLength);

    for (int i = iLength; i < output.length; i++)

        output[i] = (byte)cPadding;

    return output;

}

在 Java 加密方法中你必须替换:


 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");


 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

并且


 byte[] encrypted = cipher.doFinal(text.getBytes("UTF-8"));


 byte[] encrypted = cipher.doFinal(addPKCS7Padding(text.getBytes("UTF-8"), 32));


查看完整回答
反对 回复 2022-01-12
?
慕娘9325324

TA贡献1783条经验 获得超4个赞

前:

MerchantID=3430112RespondType=JSONTimeStamp=1485232229Version=1.4MerchantOrderNo=S_1485232229Amt=40ItemDesc=UnitTest

后:

MerchantID=3430112&RespondType=JSON&TimeStamp=1485232229&Version=1.4&MerchantOrderNo=S_1485232229&Amt=40&ItemDesc=UnitTest

我只在每个参数中添加“&”,它的工作!!!!试试看!!!

(我只加了&就成功了,你的代码没问题,只是参数要加了而已)


查看完整回答
反对 回复 2022-01-12
  • 2 回答
  • 0 关注
  • 558 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信