方案3:(针对使用了应用锁、文件锁等功能,需要用户输入密码才能访问的功能)
存储密钥最安全的方式,无疑是存储在用户的脑子里。对于一些特殊功能的应用,比如文件锁、应用锁等,可以使用PBKDF2函数,把用户输入的密码做为参数来生成加密密钥。如果用户的密码足够复杂,那么这个方案应该是很安全的。谷歌实现了这个方案。
e86K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3q4F1k6s2u0G2K9h3c8Q4x3X3c8V1k6i4k6W2L8r3!0H3k6i4u0K6i4K6u0W2j5X3I4G2k6%4y4H3L8%4c8Q4x3X3g2U0L8$3#2Q4x3V1j5J5x3o6p5K6i4K6u0r3x3o6u0Q4x3V1k6#2M7$3W2F1k6#2)9J5k6r3y4J5P5i4m8@1L8$3N6J5j5i4m8Z5P5g2)9J5k6s2c8G2i4K6u0V1M7%4c8G2M7X3g2Q4x3X3c8U0M7X3g2V1k6h3&6@1K9h3q4D9M7#2)9J5k6h3S2@1L8h3H3`.
代码:
public static SecretKey generateKey(char[] passphraseOrPin, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
// Number of PBKDF2 hardening rounds to use. Larger values increase
// computation time. You should select a value that causes computation
// to take >100ms.
final int iterations = 1000;
// Generate a 256-bit key
final int outputKeyLength = 256;
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(“PBKDF2WithHmacSHA1″);
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
return secretKey;
}
Note:这个salt是一个随机的数,可以和需要加密的数据一块存储在应用私有目录。
关于SecureRandom的使用
Android 4.2之前使用的SecureRandom是由Bouncy Castle-based 实现的,4.2开始默认由OpenSSL提供。下面这段代码在4.2之前的系统上,调用secureRandom.nextInt()生成的数字是相同的,随机性被破坏。
SecureRandom secureRandom = new SecureRandom();
byte[] b = new byte[] { (byte) 1 };
secureRandom.setSeed(b);
// Prior to Android 4.2, the next line would always return the same number!
System.out.println(secureRandom.nextInt());
建议在使用SecureRandom时不要使用setSeed()来设置seed。
最安全的方案:189K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3q4F1k6s2u0G2K9h3c8Q4x3X3c8V1k6i4k6W2L8r3!0H3k6i4u0K6i4K6u0W2j5X3I4G2k6%4y4H3L8%4c8Q4x3X3g2U0L8#2)9J5k6i4g2C8i4K6u0r3x3U0l9I4x3#2)9J5c8U0l9^5i4K6u0r3M7$3!0E0k6g2)9J5k6s2y4W2j5%4g2J5k6i4u0S2L8X3c8G2L8g2)9J5k6s2c8Z5L8%4g2Y4K9s2c8K6i4K6u0W2K9s2c8E0L8l9`.`.