【问题标题】:Android AES Encryption Missing Bytes after Cipher.doFinalCipher.doFinal 之后的 Android AES 加密丢失字节
【发布时间】:2019-07-23 11:40:06
【问题描述】:

我正在尝试加密来自 glide 的输入流。

我将输入流转换为字节数组并在我的加密方法中传递:

fun encrypt(input: ByteArray): ByteArray {

    Log.e("TAG", "inputsize: ${input.size}")

    val iv           = ByteArray(KeyStoreHelper.IV_SIZE)
    val secureRandom = SecureRandom()
    secureRandom.nextBytes(iv)

    val c = Cipher.getInstance(KeyStoreHelper.AES_MODE)
    c.init(Cipher.ENCRYPT_MODE, getKey(), GCMParameterSpec(KeyStoreHelper.GCM_SIZE, iv))
    Log.e("TAG", "outputsize: ${c.getOutputSize(input.size)}")
    val encodedBytes = c.doFinal(input)

    Log.e("TAG", "encodedBytesSize: ${encodedBytes.size}")

    val byteBuffer = ByteBuffer.allocate( iv.size + encodedBytes.size)
    byteBuffer.put(iv)
    byteBuffer.put(encodedBytes)

    Log.e("TAG", "byteBuffer: ${byteBuffer.array().size}")


    return byteBuffer.array()
}

日志如下所示:

inputsize: 750683 
outputsize: 750699 
encodedBytesSize: 95339 
byteBuffer: 95351

如您所见,加密的图像字节数组太小了,我不明白为什么 - 如果我尝试加密字符串或更小的图像(大约 100kb-200kb),它就像一个魅力。

感谢您帮助我!

亲切的问候 汤姆

【问题讨论】:

  • 有趣,这可能是一个错误。当然,首先读取数组中所有内容的想法是个坏主意,但doFinal 不应该这样做。请说明使用的运行时和库(主要是为密码配置的提供程序(打印出c.getProvider().toString())。
  • 嗨,马丁,感谢您的回复!有什么比“首先读取数组中的所有内容”更好的做法 - 很难找到一个好的、有效的、相对最新的示例...... c.getProvider().toString() 给我以下内容:AndroidKeyStoreBCWorkaround version 1.0
  • 一般你可以使用CipherInputStreamCipherOutputStream,但首先检查它是否适用于Android上的GCM; 之后,这些流经常被改装以与 GCM 兼​​容。
  • 通常您将CipherOutputStream 连接到另一个流。您可以先将其写入该流。随机数也可以通过其他方式计算或传输,因此将它作为密文的一部分是没有意义的(顺便说一下,在我看来,标签也不应该是密文的一部分 - 至少不在API)。
  • 酷。 Kudo 使用 Android 密钥库、GCM 和一个独特的随机数。顺便说一句,您的getKey 代码需要紧急重构。 getter 不应该在幕后做所有这些事情,而且您不应该首先创建诸如此类的包罗万象的方法。将其拆分为密钥生成、检索和算法初始化。这段代码当然不遵守最少意外原则。

标签: android encryption kotlin aes


【解决方案1】:

您似乎遇到了一个错误,奇怪的是在一个不合逻辑的位置:95339 是一个素数。您几乎会认为某些开发人员是故意保留该值的,以防他忘记或测试测试团队。

但是,对于如此大量的信息,将所有数据缓存在内存中并不是一个好主意,即使对于 GCM 也是如此。您应该尝试改用流式传输。您可以使用CipherOutputStream 进行加密,使用CipherInputStream 进行解密。您可以将这些流连接到其他流,例如FileOutputStreamFileInputStream,以直接读取/写入文件系统。也可以将 IV 写入这些底层流。

请注意,不同提供商处理 GCM 的方式可能存在很大差异。正如您所注意到的,与 Android 密钥库相关联的密钥库是为安全而构建的——无论如何都是密钥——而不是速度。 GCM 的其他实现可能不会显示此错误。请注意,不同的 Java(-esk) 平台和这些平台的版本之间可用的提供程序可能不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 2015-11-04
    相关资源
    最近更新 更多