当前位置: 首页 > 知识库问答 >
问题:

Java Android AES解密结果如果只有长字符串,将被截断

长孙哲
2023-03-14

我正在尝试用AES(“AES/CBC/PKCS7Padding”)用密码加密和解密纯文本。
由KeyGenerator制作secretKey,并用它加密/解密。这一开始效果很好。

但是,如果纯文本是一个大字符串(如183244个字符),则解密其中的一部分,而不是全部。

“part of it”表示
如果纯文本为“abcdefghijklmn”,则解密文本为“abcdefgh”
(这是一个示例。实际上,只有字符太长时才会出现这种情况)

        // get key from Android kyestore
        SecretKey secretKey = (SecretKey)mKeyStore.getKey(KEY_ALIAS, null);

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        IvParameterSpec ivParams = cipher.getParameters().getParameterSpec(IvParameterSpec.class);

        //
        // Encrypt
        //
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher);
        cipherOutputStream.write(plainString.getBytes("UTF-8"));
        cipherOutputStream.close();

        String encryptedString = Base64.encodeToString(outputStream.toByteArray(), Base64.DEFAULT);

        //
        // Decrypt
        //
        Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, ivParams);

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.decode(encryptedString, Base64.DEFAULT));
        CipherInputStream cipherInputStream = new CipherInputStream(byteArrayInputStream, decryptCipher);
        outputStream = new ByteArrayOutputStream();

        int b;
        while ((b = cipherInputStream.read()) != -1) {
            outputStream.write(b);
        }
        outputStream.close();

        String decryptedString =  outputStream.toString("UTF-8");

        //
        // results. decrypted string is part of source string and short.
        //
        int sourceStringLength = plainString.length(); // is 183244;
        int decryptedStringLength = decryptedString.length()); // is UNEXPECTED 68553;

你能告诉我修好这件事的要点吗?

我检查了加密/解密的字节数。

加密输出字节:“OutputStream.TobyteArray().Length”为68560
解密输入字节:“Base64.Decode(encryptedString,Base64.Default).Length”也为68560

  cipherOutputStream.write(plainString.getBytes("UTF-8"));
  cipherOutputStream.close();
        // NOTE: workaround. too bit bytes doesn't writted correctly.
        byte[] bytes = plainString.getBytes("UTF-8");

        int oneBulkSize = 1024;// temp value for proof of concept. might be bigger one.
        int numOfBulk = (bytes.length / oneBulkSize);

        for (int i = 0; i < numOfBulk; i++) {
            cipherOutputStream.write(bytes, oneBulkSize * i, oneBulkSize);
        }

        if ((bytes.length % oneBulkSize) != 0) {
            cipherOutputStream.write(bytes, oneBulkSize * numOfBulk, bytes.length % oneBulkSize);
        }
        cipherOutputStream.close();

解决了问题。

共有1个答案

程正阳
2023-03-14

AES没有数据长度限制。加密数据的长度应与输入相同,再加上最多16字节的填充长度。

在加密循环中添加一些调试代码,并验证正在读取整个输入。也许加密流和解密流一样需要一个循环。

另一种可能是183244是UTF-16编码的字节大小,但您读取的是UTF-8,大多数UTF-16字符可以是一个UTF-8字节。

  cipherOutputStream.write(plainString.getBytes("UTF-8"));
  cipherOutputStream.close();
        // NOTE: workaround. too bit bytes doesn't writted correctly.
        byte[] bytes = plainString.getBytes("UTF-8");

        int oneBulkSize = 1024;// temp value for proof of concept. might be bigger one.
        int numOfBulk = (bytes.length / oneBulkSize);

        for (int i = 0; i < numOfBulk; i++) {
            cipherOutputStream.write(bytes, oneBulkSize * i, oneBulkSize);
        }

        if ((bytes.length % oneBulkSize) != 0) {
            cipherOutputStream.write(bytes, oneBulkSize * numOfBulk, bytes.length % oneBulkSize);
        }
        cipherOutputStream.close();
 类似资料:
  • 问题内容: 我正在尝试从服务器获取JSON响应,并且当字符串长度达到约5525个字符时,响应字符串似乎总是被截断。 我还通过使用HttpEntity并读取响应流进行了尝试。但这也会在大约该长度处截断字符串。 请让我知道如何处理此问题。创建此文章时,我将其作为参考。 http://senior.ceng.metu.edu.tr/2009/praeda/2009/01/11/a-simple-rest

  • 问题内容: 我想将流结果输出转换为字符串,因为我想在Junit中使用它,我想我需要使用字符串编写器,但是我不确定如何确切地使用它。 谢谢费多 问题答案: 查看并学习使用StreamResult类的javadocs(http://java.sun.com/javase/6/docs/api/)。StreamResult的构造函数之一采用Writer对象作为参数。您将看到Writer的子类之一是Str

  • 问题内容: 如何在Python中将字符串截断为75个字符? 这是用JavaScript完成的方式: 问题答案:

  • 问题内容: 我在MySQL数据库中有一个description字段,我在两个不同的页面上访问数据库,一个页面显示整个字段,但在另一个页面上,我只想显示前50个字符。如果description字段中的字符串少于50个字符,则不会显示…,但是如果不是,则在前50个字符后显示…。 示例(完整字符串): 示例2(前50个字符): 问题答案: PHP的方法很简单: 但是您可以使用以下CSS达到更好的效果:

  • 问题内容: 我在存储过程中的MS- SQL中有一个结果集,可以说它有一个VARCHAR列,但有很多行。我想创建一个包含所有这些值的逗号分隔的字符串,是否有一种简单的方法来执行此操作,还是我必须逐步检查每个结果并手动构建字符串? 最好是我想在存储过程本身中执行此操作。 问题答案: 这是一种方法(使用AdventureWorks2008 DB): 这是另一个(从SQL 2005开始): 在这两种情况下

  • 问题内容: 我正在使用Oracle SQL开发人员版本3.0.04。我试图使用该功能将数据分组在一起。 但是,我不断收到错误消息, 我很确定输出可能会超过4000,因为这里提到的WEB_LINK是url stem和url query的串联值。 有没有解决的办法,或者还有其他选择吗? 问题答案: 由于聚合字符串的长度可以超过4000个字节,因此不能使用该函数。您可能会创建一个用户定义的集合函数,该函