gpt4 book ai didi

Android 4.2 破解了我的加密/解密代码并且提供的解决方案不起作用

转载 作者:IT老高 更新时间:2023-10-28 21:43:07 25 4
gpt4 key购买 nike

首先,我已经看到了 Android 4.2 broke my AES encrypt/decrypt codeEncryption error on Android 4.2以及提供的解决方案:

SecureRandom sr = null;
if (android.os.Build.VERSION.SDK_INT >= JELLY_BEAN_4_2) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}

对我不起作用,因为在 Android 4.2 中解码在 Android<4.2 中加密的数据时,我得到:

javax.crypto.BadPaddingException: pad block corrupted
at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:709)

我的代码很简单,一直运行到 Android 4.2:

public static byte[] encrypt(byte[] data, String seed) throws Exception {

KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecureRandom secrand = SecureRandom.getInstance("SHA1PRNG");
secrand.setSeed(seed.getBytes());
keygen.init(128, secrand);

SecretKey seckey = keygen.generateKey();
byte[] rawKey = seckey.getEncoded();

SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal(data);
}

public static byte[] decrypt(byte[] data, String seed) throws Exception {

KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecureRandom secrand = SecureRandom.getInstance("SHA1PRNG");
secrand.setSeed(seed.getBytes());
keygen.init(128, secrand);

SecretKey seckey = keygen.generateKey();
byte[] rawKey = seckey.getEncoded();

SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return cipher.doFinal(data);
}

我的猜测是,默认提供程序并不是 Android 4.2 中唯一改变的东西,否则我的代码将适用于建议的解决方案。

我的代码基于很久以前在 StackOverflow 上找到的一些帖子;我发现它与提到的帖子不同,因为它只是加密和解密字节数组,而其他解决方案加密和解密字符串(我认为是 HEX 字符串)。

这和种子有关吗?它是否有最小/最大长度、字符限制等?

有什么想法/解决方案吗?

编辑:经过大量测试,我发现有2个问题:

  1. 在 Android 4.2 (API 17) 中更改了提供程序 -> 这个很容易修复,只需应用我在帖子顶部提到的解决方案

  2. BouncyCaSTLe 在 Android 2.2 (API 8)->Android2.3 (API 9) 中从 1.34 更改为 1.45,所以我之前讲的解密问题和这里描述的一样:BouncyCastle AES error when upgrading to 1.45

所以现在的问题是:有没有办法在 BouncyCaSTLe 1.45+ 中恢复在 BouncyCaSTLe 1.34 中加密的数据?

最佳答案

首先声明:

切勿使用 SecureRandom 来派生 key !这是坏的,没有意义!

问题中的以下代码块尝试从密码中确定性地派生 key ,称为“种子”,因为密码用于“种子”随机数生成器。

KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecureRandom secrand = SecureRandom.getInstance("SHA1PRNG");
secrand.setSeed(seed.getBytes());
keygen.init(128, secrand);
SecretKey seckey = keygen.generateKey();

但是,"SHA1PRNG" 算法的定义不明确,"SHA1PRNG" 的实现可能会返回不同的甚至完全随机的 key 结果。


如果您从磁盘读取 AES key ,只需存储实际 key ,不要经历这种奇怪的舞蹈。您可以通过执行以下操作从字节中获取用于 AES 使用的 SecretKey:

    SecretKey key = new SecretKeySpec(keyBytes, "AES");

如果您使用密码来派生 key ,请关注 Nelenkov's excellent tutorial需要注意的是,一个好的经验法则是盐的大小应该与键输出的大小相同。

iterationCount(工作系数)当然会发生变化,并且应该随着 CPU 功率的提高而变化 - 通常建议不要低于 2018 年的 40 到 100K。请注意 PBKDF2只会增加猜测密码的持续时间延迟;它不能替代非常弱的密码。

看起来像这样:

    /* User types in their password: */
String password = "password";

/* Store these things on disk used to derive key later: */
int iterationCount = 1000;
int saltLength = 32; // bytes; should be the same size as the output (256 / 8 = 32)
int keyLength = 256; // 256-bits for AES-256, 128-bits for AES-128, etc
byte[] salt; // Should be of saltLength

/* When first creating the key, obtain a salt with this: */
SecureRandom random = new SecureRandom();
byte[] salt = new byte[saltLength];
random.nextBytes(salt);

/* Use this to derive the key from the password: */
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt,
iterationCount, keyLength);
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
SecretKey key = new SecretKeySpec(keyBytes, "AES");

就是这样。任何其他你不应该使用的东西。

关于Android 4.2 破解了我的加密/解密代码并且提供的解决方案不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13433529/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com