解密信用卡号时返回 javax.crypto.IllegalBlockSizeException

标签 java jakarta-ee encryption cryptography

我的加密方法是:

private static final String ALGORITHM = "AES/ECB/PKCS5Padding";
private static final byte[] KEY = "StBet9834#$10BCy".getBytes();

private String encryptCreditCard(String ccNumber) {
    // do some encryption
    if (ccNumber == null || ccNumber.length() == 0) {
        return "";
    }
    Key key = new SecretKeySpec(KEY, "AES");
    try {
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.ENCRYPT_MODE, key);
        //return Base64.encodeBytes(c.doFinal(ccNumber.getBytes()));
        byte[] ccNumberBytes = ccNumber.getBytes();
        byte[] encCCNumber = c.doFinal(ccNumberBytes);
        return new String(Base64.encodeBase64(encCCNumber));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

我使用以下方法来解密我的信用卡详细信息:

public void decryptCreditCard() {
  Key key = new SecretKeySpec(KEY, "AES");
  try {
    String ccNumber = this.cardNumber;
    if (ccNumber == null || ccNumber.length() == 0) {
      return;
    }
    Cipher c = Cipher.getInstance(ALGORITHM);
    c.init(Cipher.DECRYPT_MODE, key);
    byte[] ccENCBytes = Base64.decodeBase64(ccNumber);
    byte[] ccDECBytes = c.doFinal(ccENCBytes);
    this.plainCardNumber = new String(ccDECBytes);
    this.last4CreditCard =             plainCardNumber.substring(this.plainCardNumber.length() - 4);
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

我的测试卡号字符串是:5123456789012346。执行此行时:

byte[] ccDECBytes = c.doFinal(ccENCBytes);

我收到以下异常:

Caused by: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
  at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:750)
  at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
  at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
  at javax.crypto.Cipher.doFinal(Cipher.java:2087)
  at stbet.model.core.CustomerAccount.decryptCreditCard(CustomerAccount.java:527)

这个错误说明什么?非常感谢任何帮助。

最佳答案

您的算法必须表示带填充的密码:例如:AES/CBC/PKCS5Padding。

并且编码消息的字符串表示不能丢失字节。您正在使用字符串的默认编码,因此很可能 UTF-8 不适合。您需要字节到字节的映射,例如:“ISO-8859-1”

返回新字符串(Base64.encodeBase64(encCCNumber),"ISO-8859-1");

或者简单地 Base64.encodeBase64String 应该可以完成这项工作;

关于解密信用卡号时返回 javax.crypto.IllegalBlockSizeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29170447/

相关文章:

java - 客户端-服务器应用程序的 JPA 悲观锁逻辑

java - 为什么我在使用 context.lookup ("java:comp/env/MyBean"时收到 NameNotFoundException )

Java线程模型

Javascript 公钥/私钥加密

java - 为什么两个不同的嵌套循环(具有相同的时间复杂度)执行时间不同?

应用于父类(super class)的子类中的java方法重写

java - PHP 没有返回预期的结果

java - ORDER BY 中的 HQL 案例排序不正确

javascript - 针对特定数据的 Crypto 与 Bcrypt

c - 如何将 IV(初始化 vector )添加到 AES-256 ECB 加密以创建 AES-256 CBC 模式?