2017-02-09 86 views
0

我试图从使用奇尔卡特专有的解密库转换为Apache的公共密码。我正在使用2个示例加密输入。第一个是16个字节,第二个是96个字节。第一个很好,但第二个CryptoCipher似乎并没有使用最后的16个字节。Java CryptoCipher不消耗所有输入字节

这里的设置和解密和输出的一些示例代码:

短输入:

--16 
encln 16 
consume 0 
finish 13 

龙输入

Properties properties = new Properties(); 
    CryptoCipher crypt = CryptoCipherFactory.getCryptoCipher("AES/CBC/PKCS5Padding", properties); 
    MessageDigest digest = MessageDigest.getInstance("SHA-256"); 

    byte[] hashedKeyBytes = digest.digest("SHARED_SECRET".getBytes(
      StandardCharsets.UTF_8)); 
    MessageDigest ivDigest = MessageDigest.getInstance("MD5"); 

    byte[] ivBytes = ivDigest.digest("SHARED_SECRET".getBytes(StandardCharsets.UTF_8)); 
    final SecretKeySpec key = new SecretKeySpec(hashedKeyBytes, "AES"); 
    IvParameterSpec iv = new IvParameterSpec(ivBytes); 

    crypt.init(Cipher.DECRYPT_MODE, key, iv); 

    ByteBuffer encBuffer = ByteBuffer.allocateDirect(enc.length); 
    System.out.println("--" + enc.length); 
    encBuffer.put(enc); 
    encBuffer.flip(); 
    System.out.println("encln " + encBuffer.limit()); 

    ByteBuffer decoded = ByteBuffer.allocateDirect(bufferSize); 
    CryptoCipher crypt = init(); 

    System.out.println("consume " + crypt.update(encBuffer, decoded)); 
    System.out.println("finish " + crypt.doFinal(encBuffer, decoded)); 
    decoded.flip(); 
    return asString(decoded); 

此为2个输入产生这些2个输出:

--96 
encln 96 
consume 80 
finish 3 

正如你所看到的,它只需要从输入中消耗80个字节......由于与Chilkat生成的输出相比,较短的输入产生了正确的输出,所以我不确定在哪里接近这个以使其与较长的输入一起工作。

回答

4

crypt.update()crypt.doFinal(..)返回的数字是解密的字节数,而不是操作消耗的字节数。当您的数据被填充(或至少您将其指定为PKCS5Padded)时,您的加密数据将始终比解密版本大一点。使用PSCS5AES填充将添加1到16字节的填充到最接近的多字节16字节,这是块大小AES

在第一个例子中,您的13个字节的清除数据有3个字节的填充,给出16个字节的加密数据(或一个完整的AES块)。在第二个例子中,您有83个字节的清除数据和13个字节的填充(给出6个16字节的AES块)。

+0

嗯......我想知道为什么最后的字符会被截断...我会花一些时间来确认传入的字节数组是否正确。当从字符串转换为字节[]时,它可能以某种方式被切断... – user2963069

+0

当您加密时填充会自动添加,并且在您解密时会自动删除。如果使用3个字节的填充对16个字节的消息进行解密,则只能得到13个字节的解密数据。 –