【问题标题】:Invalid AES key length: 12 bytes in java无效的 AES 密钥长度:java 中的 12 个字节
【发布时间】:2021-01-07 10:24:46
【问题描述】:

按照给定的步骤,我已执行加密,但出现错误。

  1. 生成一个 16 位随机数(会话密钥)。说RANDOMNORANDOMNO = 1111222233334444
  2. 使用 RSA/ECB/PKCS1Padding 加密 RANDOMNO 并使用 Base64 进行编码。说ENCR_KEYENCR_KEY = B64Encode(RSA/ECB/PKCS1Encryption(RANDOMNO,ICICIPubKey.cer))
  3. 使用 RANDOMNO 作为密钥和初始化向量对请求有效负载执行 AES/CBC/PKCS5Padding 加密。说ENCR_DATAENCR_DATA = B64Encode(AES/CBC/PKCS5Padding(REQUEST_DATA, RANDOMNO, IV))
  4. 现在,客户端可以选择从以下两个选项之一请求发送 IV。 在“iv”标签中发送 Base64 编码的 IV。
  public  byte[] generateRandomBytes() {
          SecureRandom ng=new SecureRandom();
          byte[] randomBytes=new byte[16];
          ng.nextBytes(randomBytes);
          return randomBytes;
        }

//new method for encryption -we need to check
 public  String encryptRandomKeyWithCertificate(byte[] randomNumber) throws BadPaddingException, IllegalBlockSizeException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, FileNotFoundException, CertificateException {

    //step2: encrypt the random number with certificate
    FileInputStream fin = new FileInputStream("D:\\cedge_uat\\ICICIUATpubliccert.cer");
    CertificateFactory f = CertificateFactory.getInstance("X.509");
    X509Certificate certificate = (X509Certificate) f.generateCertificate(fin);
    PublicKey publicKey = certificate.getPublicKey();
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte[] cipherData = cipher.doFinal(randomNumber);
    String encodedData = Base64.getEncoder().encodeToString(cipherData);
    return encodedData;
}

public  String encryptRequestWithKey(String text, byte[] randomNumber) throws Exception {

    //step3: encrypt the requestString with randomkeyEncrypted
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    BASE64Decoder decoder = new BASE64Decoder();
    SecretKeySpec keySpec = new SecretKeySpec(randomNumber, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(new byte[16]);
    cipher.init(Cipher.ENCRYPT_MODE, keySpec,ivSpec);
    byte[] cipherData = cipher.doFinal(text.getBytes());
    // BASE64Encoder encoder = new BASE64Encoder();
    //return encoder.encode(cipherData).replaceAll("[\r\n]+", "");
    String encodedData = Base64.getEncoder().encodeToString(cipherData);
    return encodedData;
}

      
public static void main(String[] args) throws IOException {
    
    String requestString = "CORP_USER=";
    byte[] randomNumber;
    String encryptedKey;
    try {
        randomNumber=encryption.generateRandomBytes();
        encryptedKey = encryption.encryptRandomKeyWithCertificate(randomNumber);
        String encryptedData =encryption.encryptRequestWithKey(requestString,randomNumber);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

【问题讨论】:

  • 请帮助我,按照步骤,我已经完成了加密,但出现错误。但为什么我得到这个错误
  • 使用数字的字符串表示对于键来说是一个糟糕的选择。而且您的随机数可能没有 16 位数字。改为生成随机字节并使用诸如 SecureRandom 之类的 PRNG,而不是 Math.Random。
  • 现在我像这样更改了上面的行 SecretKeySpec keySpec = new SecretKeySpec(randomNumber.getBytes(), "AES");现在加密完成但访问 url 401 未经授权,哪一方是error.client 或服务器
  • 你能帮帮我吗
  • 正如@Marc 已经写的那样,您仍在使用字符串作为 AES 密钥 其次:您仍然使用 Math.random 而不是 SecureRandom 生成密钥。第三:您正在使用一个静态初始化向量(填充 16 x00),它使完整的加密 UNSECURE。在寻求帮助之前,请更正您的代码并编辑您的问题,谢谢。

标签: java encryption aes public-key-encryption


【解决方案1】:

根据AES encryption 上的维基百科页面,AES 密钥可以是 128、192 或 256 位;即 16、24 或 32 字节。

您提供的密钥大小取决于您生成的“随机”数字字符串。看起来它将在 1 到 19 位数字加上一个可能的符号之间。当您在该字符串上调用 getBytes() 时,您将获得一个 1 到 20 个字节之间的字节数组。这通常不是 AES 可接受的密钥大小之一。

您应该做的是使用 SecureRandom.nextBytes(byte[]) 并提供一个字节数组,该数组是 AES 的三种可接受的密钥大小之一。

【讨论】:

  • 密钥文件以-----BEGIN RSA PRIVATE KEY-----开头
  • 使用算法 (RSA/ECB/PKCS1Padding) 和客户端的私钥解密 encryptedKey。我有 .key 扩展名 t 中的 RSA 私钥,但我不知道如何用该密钥解密。你能建议任何代码如何实现这一点
  • 你已经完全改变了问题。请将问题转回您关于 AES 密钥大小的原始问题。
  • 我创建了新问题,你能检查并提出解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 2014-03-27
  • 1970-01-01
  • 2010-12-18
  • 1970-01-01
  • 2017-11-15
相关资源
最近更新 更多