在安卓设备中安全地存储AES密钥

3
我在尝试加密由用户指定的字符串列表。用于加密和解密此数据的AES密钥必须保存在设备上,以便在用户需要解密数据时可以使用它。我已经了解到使用Keystore是存储密钥的好选择,但我阅读的大部分指南都将其与应用程序签名相关联,这并不是我想要的。我的应用程序需要用户输入密码,然后使用使用密码解锁的密钥解密字符串数据。我该怎么做?
谢谢。
1个回答

2
没有您明确“安全”的定义,很难回答您的问题。您是在谈论应用程序的安全性吗?还是防止其他用户的安全性?还是防止设备丢失的安全性?或者是防止数据丢失的安全性?
此外,您所说的安全级别是什么?给定密钥下的数据是否足够敏感,需要认真考虑如何存储密钥?
据我所知,如果数据具有高度敏感性,则应直接从密码中派生密钥,使用基于密码的密钥派生函数(例如PBKDF #2、Bcrypt或Scrypt)。这样,密钥材料无需直接存储在设备上。
如果您打算出于任何原因存储主加密密钥,请使用密码密钥进行加密,并将其作为Base64字符串存储在SharedPreferences下的 MODE_PRIVATE 中,以保护其免受其他应用的攻击。即使密钥被恶意用户/设备盗窃恢复,也没有正确的密码密钥,密钥材料本身也是无用的。
如果您想防止密钥丢失,则不应将密钥存储在设备上,而应将其存储在自己的服务器上,再次使用密码密钥加密,以便数据库破坏不会导致数据泄露。
总之,我建议您尽量不要将任何私钥存储在设备本身上,而是将派生自密码的密钥用作所有加密操作的主密钥。将密钥库留给公钥密码学中生成的专为私钥和已知公钥证书。

另外,即使我要生成每次都相同的PBKDF2密钥,我也必须硬编码盐,这可能会被攻击者检索到,对吗? - sm123
@gl321 首次随机生成盐并将其存储在共享首选项中。该算法的盐和参数不是私有的,攻击者可以检索它们而不会造成任何安全风险,只需确保每个用户的盐都是随机的(禁用为所有用户生成彩虹表)。一旦生成了初始密钥,请确保不会丢失盐(可能也存储在您自己的服务器上)。下次用户登录时可以定期更改编码密钥,并生成新的盐。 - initramfs
我认为如果密钥更改,我必须解密并重新加密字符串。有没有解决方案?此外,IV参数也应该硬编码吗? 非常感谢您的帮助。 - sm123
@gl321 不要硬编码任何东西。让它们在需要时随机生成,然后存储。如果您使用相同的(生成的)种子与PBKDF #2 / Bcrypt或Scrypt,则会得到相同的密钥。如果您确实需要更改密钥,无论出于什么原因,您都需要解密然后重新加密所有内容,这是不可避免的。我建议只有在大多数数据已经为用户解密时才执行密钥更改,这样您只需要根据需要重新加密数据即可。不知道系统任务的精确性质很难评估您的系统需求。 - initramfs
@gl321 可能只是字符集的问题。尝试明确将其设置为UTF-8,看看会发生什么。 - initramfs
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接