【问题标题】:encrypt/decrypt in Java and python using AES使用 AES 在 Java 和 python 中加密/解密
【发布时间】:2018-09-07 18:10:16
【问题描述】:

我正在尝试使用 AES 加密/解密 python 和 java 中的字符串,两者的加密结果相同。加密工作正常,但是当我尝试在 java 中解密字符串时,它向我显示了这个错误( javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher )。在python中它工作正常。 java解密有什么问题?

private static String toHexString(byte[] data) {        
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < data.length; ++i) {
        String s = Integer.toHexString(data[i] & 0XFF);
        buf.append((s.length() == 1) ? ("0" + s) : s);
    }
    return buf.toString();
}

public static String encrypt(String input, String key) {
    byte[] crypted = null;
    try {
        SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skey);
        crypted = cipher.doFinal(input.getBytes());
        final String encryptedString = toHexString(Base64.encodeBase64(crypted));
        return encryptedString;
    } catch (Exception e) {
        System.out.println(e.toString());
    }
    return "";
}




  public static String decrypt(String encrypted, String key)  {
         char[] ch= encrypted.toCharArray();
    try {

        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher2 = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher2.init(Cipher.DECRYPT_MODE, skeySpec);

       byte[] h =Hex.decodeHex(ch);

     String de = new String(Base64.decodeBase64(cipher2.doFinal(Hex.decodeHex(ch))),"UTF-8");  

    return de; 
    } catch (Exception e) {
        System.out.println(e.toString());
    }
    return null;
}

【问题讨论】:

  • 您需要检查加密后和解密前加密字节的字节长度是否相同。该错误告诉您您正在尝试解密长度不是 16 倍数的字节数组。某处的东西要么丢失字节,要么添加字节。有时字符串处理会添加不需要的换行符等。最好逐字节检查这两个字节数组,看看差异在哪里。
  • 你为什么同时使用base64和十六进制编码?我认为一个就足够了
  • 1.如果您无法解密,您怎么知道“加密工作正常”?仅仅因为没有错误指示并不意味着它按预期正常工作。 2.javax.crypto.IllegalBlockSizeException表示要解密的数据大小不正确,必须是16字节的倍数。 3.提供测试密钥、数据和加密数据。 3. 最好的猜测是编码不匹配,参见上面的第 3 点。
  • 不要在新作品中使用 ECB 模式并尽快更新旧作品,它不安全,请参阅ECB mode,向下滚动到企鹅。而是使用带有随机IV的CBC模式,只需在加密数据前加上IV用于解密即可,它不需要保密。

标签: java encryption aes


【解决方案1】:

很简单,你应该在解密之前执行base 64解码,而不是之后。


这里是一个密文是 base 64 编码的例子。确实没有理由执行 base 64 hex 编码,您可以使用其中任何一种,但同时使用这两种编码没有意义。

我使用了另一种 Base64 编解码器,您没有指定您使用的是哪一个。

警告:请勿复制以下代码,不安全;它只提供对问题的直接答案。

public static String encrypt(String input, String key) {
    byte[] crypted = null;
    try {
        SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skey);
        crypted = cipher.doFinal(input.getBytes());
        final String encryptedString = Base64.toBase64String(crypted);
        return encryptedString;
    } catch (Exception e) {
        System.out.println(e.toString());
    }
    return "";
}

public static String decrypt(String encrypted, String key) {
    // char[] ch= encrypted.toCharArray();
    try {

        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher2 = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher2.init(Cipher.DECRYPT_MODE, skeySpec);

        // byte[] h = Hex.decode(encrypted);

        String de = new String(cipher2.doFinal(Base64
                .decode(encrypted)), "UTF-8");

        return de;
    } catch (Exception e) {
        System.out.println(e.toString());
    }
    return null;
}

我认为这是出于学习目的,因为代码存在许多问题,例如使用字符串中的密钥、ECB 模式加密等。

【讨论】:

  • 虽然不做上述任何事情可能应该是首选,但我会对此做一个简短的直接回答。
  • 请问你能告诉我怎么做吗?我尝试过,但没有成功
猜你喜欢
  • 2017-02-21
  • 2019-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-03
  • 2014-01-14
相关资源
最近更新 更多