AES:使用nonce为HMAC创建新密钥

时间:2017-04-10 16:54:46

标签: c# security cryptography aes hmac

我使用AES为API调用创建HMAC签名,虽然我了解其中的nonce是什么以及为什么它们很重要,但我对它们的实现位置有点困惑。

我有一个想法是使用nonce来改变客户端的密钥,以生成一个新的一次性密钥来签署调用,否则这些调用很容易被重放攻击利用。

基本前提是用户在登录时获取密钥,调用设置API过程,该过程创建并返回transactionID和新的nonce。然后,用户将他们自己的秘密密钥和随机数组合在一起,以签署TransactionID和其他一些东西。然后,服务器尝试使用该用户当前活动的nonce来匹配此签名。

当进行新的设置调用时,服务器会自动清除旧的nonce并覆盖它们,因此用户必须始终遵循此配对序列(您不能只重用第二次调用,因为旧的nonce将被删除,服务器将不再接受此签名)。

如果这是使用随机数的有效方法,我如何将它们与客户端密钥组合以获得有效的密钥?

我以这种方式生成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字节长。但是如果我想使用现时创建一个新密钥,我不能简单地连接它们,因为结果字符串将不再是32字节。

我应该连接然后使用固定长度的哈希函数将结果恢复为32字节长度吗?或者是否有一个AESCryptoServiceProvider构造函数/方法可以自动处理我缺少的nonce? 或者我只是想将明文中的nonces附加到签名中并让服务器单独读取它们并直接检查它们?

1 个答案:

答案 0 :(得分:1)

有很多方法可以解决这个问题。最简单的方法是使用散列。您可以使用HMAC甚至HKDF

SessionKey = HMAC_SHA256(SecretKey, Nonce)

请务必仅使用用户的SecretKey来获取其他密钥。如果要将此派生用于不同的事物,则需要将用法绑定到键中:

SessionKey = HMAC_SHA256(SecretKey, "Encryption".Concat(Nonce))
SessionToken = HMAC_SHA256(SecretKey, "Token".Concat(Nonce))

这只是伪代码。 Here是C#中实际HMAC的一些示例。