AES:使用随机数为 HMAC 创建新密钥
AES: Use nonce to create new key for HMAC
我使用 AES 为 API 调用创建 HMAC 签名,虽然我了解随机数是什么以及它们为何重要,但我对它们的确切实施位置感到有些困惑。
我想到了使用随机数来更改客户端的密钥以生成新的一次性密钥来签署调用,否则很容易被重放攻击所利用。
基本前提是用户在登录时获得密钥,调用设置 API 过程创建并 returns 交易 ID 和新随机数。然后用户结合他们自己的密钥和随机数来签署 TransactionID 和其他一些东西。然后,服务器会尝试使用该用户的当前活动随机数来匹配此签名。
服务器会自动清除旧的随机数并在进行新的设置调用时覆盖它们,因此用户必须始终遵循这个配对序列(您不能只重复使用第二个调用,因为旧的随机数将被删除并且服务器将不再接受此签名)。
如果这是使用随机数的有效方式,我如何将它们与客户端的密钥结合起来以获得有效的密钥?
我以这种方式生成 AES 提供程序:
private static AesCryptoServiceProvider GetProvider(byte[] key, byte[] IV)
{
AesCryptoServiceProvider result = new AesCryptoServiceProvider();
result.BlockSize = 128;
result.KeySize = 256;
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7;
result.IV = IV;
result.Key = key;
return result;
}
我使用 AES-256,所以我的密钥总是 32 字节长。但是如果我想使用 nonce 创建一个新密钥,我不能简单地将它们连接起来,因为生成的字符串将不再是 32 字节。
我是否应该连接然后使用固定长度的散列函数将结果恢复为 32 字节长度?或者是否有一个 AESCryptoServiceProvider constructor/method 可以自动处理我丢失的随机数?
或者我只是应该将明文的随机数附加到签名中,让服务器单独读取它们并直接检查它们?
有很多方法可以解决这个问题。最简单的方法是使用哈希。您可以使用 HMAC or even HKDF.
SessionKey = HMAC_SHA256(SecretKey, Nonce)
确保仅将用户的 SecretKey
用于派生其他密钥。如果你想将这个推导用于不同的东西,那么你需要将 uses 绑定到键中:
SessionKey = HMAC_SHA256(SecretKey, "Encryption".Concat(Nonce))
SessionToken = HMAC_SHA256(SecretKey, "Token".Concat(Nonce))
这只是伪代码。 Here 是 C# 中实际 HMAC 的一些示例。
我使用 AES 为 API 调用创建 HMAC 签名,虽然我了解随机数是什么以及它们为何重要,但我对它们的确切实施位置感到有些困惑。
我想到了使用随机数来更改客户端的密钥以生成新的一次性密钥来签署调用,否则很容易被重放攻击所利用。
基本前提是用户在登录时获得密钥,调用设置 API 过程创建并 returns 交易 ID 和新随机数。然后用户结合他们自己的密钥和随机数来签署 TransactionID 和其他一些东西。然后,服务器会尝试使用该用户的当前活动随机数来匹配此签名。
服务器会自动清除旧的随机数并在进行新的设置调用时覆盖它们,因此用户必须始终遵循这个配对序列(您不能只重复使用第二个调用,因为旧的随机数将被删除并且服务器将不再接受此签名)。
如果这是使用随机数的有效方式,我如何将它们与客户端的密钥结合起来以获得有效的密钥?
我以这种方式生成 AES 提供程序:
private static AesCryptoServiceProvider GetProvider(byte[] key, byte[] IV)
{
AesCryptoServiceProvider result = new AesCryptoServiceProvider();
result.BlockSize = 128;
result.KeySize = 256;
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7;
result.IV = IV;
result.Key = key;
return result;
}
我使用 AES-256,所以我的密钥总是 32 字节长。但是如果我想使用 nonce 创建一个新密钥,我不能简单地将它们连接起来,因为生成的字符串将不再是 32 字节。
我是否应该连接然后使用固定长度的散列函数将结果恢复为 32 字节长度?或者是否有一个 AESCryptoServiceProvider constructor/method 可以自动处理我丢失的随机数? 或者我只是应该将明文的随机数附加到签名中,让服务器单独读取它们并直接检查它们?
有很多方法可以解决这个问题。最简单的方法是使用哈希。您可以使用 HMAC or even HKDF.
SessionKey = HMAC_SHA256(SecretKey, Nonce)
确保仅将用户的 SecretKey
用于派生其他密钥。如果你想将这个推导用于不同的东西,那么你需要将 uses 绑定到键中:
SessionKey = HMAC_SHA256(SecretKey, "Encryption".Concat(Nonce))
SessionToken = HMAC_SHA256(SecretKey, "Token".Concat(Nonce))
这只是伪代码。 Here 是 C# 中实际 HMAC 的一些示例。