【问题标题】:Is AES/ CBC/ PKCS5Padding encryption decryption algorithm and SHA-1 hashing algorithm avaible in all type of Android devicesAES/ CBC/ PKCS5Padding 加密解密算法和 SHA-1 哈希算法是否适用于所有类型的 Android 设备
【发布时间】:2015-06-16 22:46:42
【问题描述】:

我曾尝试在 Nexus 5 中运行以下 AES/ CBC/ PKCS5Padding 加密和解密代码,并使用 SHA-1 作为密钥生成。它运行良好到目前为止。

不过,我唯一关心的是,AES/CBC/PKCS5Padding 加密解密算法和 SHA-1 哈希算法是否适用于所有类型的 Android 设备?

以下代码是否有可能无法在某些 Android 设备上运行?如果有,有没有后备计划?

AES/CBC/PKCS5Padding

// http://stackoverflow.com/questions/3451670/java-aes-and-using-my-own-key
public static byte[] generateKey(String key) throws GeneralSecurityException, UnsupportedEncodingException {
    byte[] binary = key.getBytes("UTF-8");
    MessageDigest sha = MessageDigest.getInstance("SHA-1");
    binary = sha.digest(binary);
    // Use only first 128 bit.
    binary = Arrays.copyOf(binary, 16);
    return binary;
}

// http://stackoverflow.com/questions/17322002/what-causes-the-error-java-security-invalidkeyexception-parameters-missing
public static String encrypt(byte[] key, String value) throws GeneralSecurityException {
    // Argument validation.
    if (key.length != 16) {
        throw new IllegalArgumentException("Invalid key size.");
    }

    // Setup AES tool.
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));

    // Do the job with AES tool.
    byte[] original = value.getBytes(Charset.forName("UTF-8"));
    byte[] binary = cipher.doFinal(original);
    return Base64.encodeToString(binary, Base64.DEFAULT);
}

// // http://stackoverflow.com/questions/17322002/what-causes-the-error-java-security-invalidkeyexception-parameters-missing
public static String decrypt(byte[] key, String encrypted) throws GeneralSecurityException {
    // Argument validation.
    if (key.length != 16) {
        throw new IllegalArgumentException("Invalid key size.");
    }

    // Setup AES tool.
    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));

    // Do the job with AES tool.
    byte[] binary = Base64.decode(encrypted, Base64.DEFAULT);
    byte[] original = cipher.doFinal(binary);
    return new String(original, Charset.forName("UTF-8"));
}

用法

byte[] key = generateKey("my secret key");
String ciphertext = encrypt(key, "my plain content");
String plainContent = decrypt(key, ciphertext);

【问题讨论】:

  • 在所有可用的模拟器图像中尝试一下,但我认为没有理由不应该在任何地方实施。如果您仍然不想自己尝试,则默认使用 BouncyCastle/SpongyCastle 提供程序。
  • @OlegEstekhin 它认为关于这个问题有点过头了。这意味着提问者仍然需要在所有模拟器上进行测试,这可能只是您在设计应用程序后才想做的事情。

标签: android encryption cryptography


【解决方案1】:

不,它不太可能失败。 Android API 是从 Java API 派生的。自 1.4 版以来,Java API 已包含 "AES/CBC/PKCS5Padding"

至于"SHA-1",这是一个更老的算法,从一开始就被支持。

注意不要改用"PKCS7Padding"。 Java 使用"PKCS5Padding" 作为替代,"PKCS7Padding" 支持可能是粗略的,即使它意味着相同的东西。


请注意,您应该使用基于密码的加密 (PBE) 而不是 AES/CBC 和 SHA-1。尤其是使用 SHA-1 作为密钥派生方法特别危险,因为您不使用盐或工作因子作为良好的基于​​密码的密钥派生函数,如 PBKDF2 应该。基本上只有在您知道您的密码包含足够的熵时才这样做。

虽然对同一个键使用全零 IV 会更糟(正如 cmets 中已经指出的那样)。它使攻击者可以找到明文输入(的起始块)的重复。始终建议使用经过身份验证的加密(例如使用 HMAC-SHA-1),并且或多或少需要传输模式加密(与无法进行纯文本/填充 oracle 攻击的就地加密相反)。

【讨论】:

  • 我刚刚意识到我不能使用“AES/CBC/PKCS5Padding”,因为它会破坏我的一些旧加密数据。旧的加密数据使用“AES”。 “AES”和“AES/CBC/PKCS5Padding”一样普遍吗
  • 是的,据我所知,它总是在 Java 和 Android 上评估为 "AES/ECB/PKCS5Padding",即使它官方依赖于提供程序默认值。所以它可能会改变(未来的)供应商。我强烈建议您改为指定"AES/ECB/PKCS5Padding",并意识到它甚至比IV 为零的CBC 更不安全。欧洲央行不使用IvParameterSpec
  • 但我的观察是,使用“AES”和“AES/ECB/PKCS5Padding”会产生不同的行为。如果我使用“AES”,则使用 cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 而不使用 IvParameterSpec 将起作用。但是,如果我使用“AES/ECB/PKCS5Padding”,而没有IvParameterSpec,它将失败。
  • 这太奇怪了,您能否进一步说明密文是如何以及在哪个运行时创建的?你能打印出cipher.getProvider()吗?
  • 这是一个可行的 AES 示例:gist.github.com/yccheok/e43aa336894dbf5106df 我在 Java 8 桌面上测试了代码。
【解决方案2】:

这不是直接回答您的问题,而是...

cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));

不要使用这个结构!它会破坏您认为自己获得的任何安全性!

此调用使用全零初始化向量初始化您的密码对象。这是一件非常非常非常糟糕的事情,尤其是对于 CBC:CBC 具有很强的延展性,并且不做任何完整性保护。确保使用 SecureRandom 或类似名称生成 IV,最好使用 GCM 或 CCM。

【讨论】:

  • 但是,如果我使用随机IV加密,并使用另一个随机IV解密,我将无法恢复我的原始源消息吗?
  • 您在加密时生成一个随机 IV,并将其与密文一起发送。解密时,必须给解密码同样的IV。
  • 我意识到如果我使用“AES”而不是“AES/CBC/PKCS5Padding”,我可以使用cipher.init(Cipher.DECRYPT_MODE, skeySpec);。如果我一次性消除 IvParameterSpec,你知道任何潜在的漏洞吗?
  • 不幸的是,我认为这确实更像是一个评论而不是一个答案。
  • 我认为这意味着您正在使用 ECB 模式,这也是一个坏主意。阅读有关分组密码模式的 Wikipedia 文章,它将详细解释原因,但简而言之,这意味着攻击者可能会通过频率分析攻击来破解密码。但这取决于“AES”的实际含义;在这种情况下,环境实际上可能会为您执行此操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 1970-01-01
  • 2021-01-05
相关资源
最近更新 更多