AES 自定义密码密钥

Posted

技术标签:

【中文标题】AES 自定义密码密钥【英文标题】:AES custom password key 【发布时间】:2017-10-28 15:50:54 【问题描述】:

我正在尝试实现 AES 自定义密码加密,并希望了解以下代码。

我不太明白为什么需要指定密钥大小 256“PBEKeySpec(password, salt, 65536, 256)”,当我使用“PBKDF2WithHmacSHA256”时,它假设将 SecretKey 生成为 256 位。

在使用我的密码+盐生成密钥后,为什么我需要将其与 SecretKeySpec 关联为 AES 算法。

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

【问题讨论】:

明确一点:您问的是基于密码的加密,其中密码用于派生密钥,然后用于加密其他数据,而不是加密密码本身,对吗?跨度> @ArtjomB。是的。我正在尝试实现基于密码的加密。我想我还有一个问题是加密这个“密码”,它是用来加密数据的。 【参考方案1】:

为什么需要指定密钥大小为 256

PBKDF2 是一个灵活的基于密码的密钥派生函数。它使用具有多次迭代的底层哈希函数。它可以输出您想要的任何大小的密钥。即使在生成 AES-128 密钥时也经常使用 SHA-256,因为不知道 SHA-256 会被破坏,并且与其他哈希函数(例如 MD5 和 SHA-512(仅在 x64 上)相比)相对较慢。缓慢是 PBKDF 的一个重要因素,因为当攻击者尝试暴力破解密码时,它会直接影响攻击者。当然,您还可以调整迭代次数。

此外,PBKDF2 可以输出比底层散列函数输出大小更多的密钥材料。例如,通常要求 PBKDF2 的输出包含 IV。在您的情况下,输出应该是 384 位长。

一般情况下,不建议向 PBKDF2 请求超过底层哈希函数。如果你也想推导出 IV,你应该 use SHA-512。只要每次加密随机生成盐并与密文一起存储,这应该足以实现语义安全。

所以,为了回答您的问题,PBKDF2 不知道您想如何使用输出。你对此负责。你必须知道你在做什么。有上百万种不同的方法可以解决加密的 PBKDF 部分。

为什么我需要将其与 SecretKeySpec 关联为 AES 算法。

如果您想使用 Cipher 实例使用 AES 加密某些内容,您需要传入一个 java.security.Key 对象,该对象将在运行时解析为 AES。 Key#getAlgorithm() 方法用于此目的。如果您在创建SecretKeySpec 时没有指定"AES",您将得到一个InvalidKeyException

【讨论】:

你的意思是我可以考虑 KeyGenerator.getInstance("HmacSHA256") 而不是 KeyGenerator.getInstance("AES") 如果我想要一个 AES 密钥进行加密?并使用 kgen.init(128);我可以指明我想要 128 位还是 256 位密钥。 HMAC 密钥与 PBKDF2 的输出不同。但由于 HMAC 和 AES 不要求密钥具有任何特定的内部结构,因此您可以生成 HMAC 密钥并将其用作 AES 密钥。问题是,你为什么要这样做?这对代码的可读性和可理解性非常不利。

以上是关于AES 自定义密码密钥的主要内容,如果未能解决你的问题,请参考以下文章

Keycloak |如何添加自定义密钥泄露密码策略?

对于使用 Facebook iOS SDK 的混合 SSO 场景,为我们自己的自定义用户记录生成密码/密钥的最佳方式是啥?

iOS - 使用自定义加密密钥保护文件?

DES_3DES_AES_IDES_RSA密码算法比较

AES加密解密,自定义加密规则记录

如何在 android KeyStore 中生成 KeyPair,受自定义密码保护