2
$\begingroup$

I have a web API with a custom API authentication system that users each have a SecretKey and a public ApiKey. Using these two keys client(or user) can generate a token for the authentication on the server.

Consider this function generating an authentication token

public string GetToken(string apiKey, string secretKey, string expireTimestamp)
{
    using var hashAlgorithm = SHA256.Create();
    var byteValue = Encoding.UTF8.GetBytes(apiKey + secretKey + expireTimestamp)
    var byteHash = hashAlgorithm.ComputeHash(byteValue)
    return Convert.ToBase64String(byteHash) + expireTimestamp
}

So a token is a combination of

$$token = SHA256(APIKey \mathbin\| SecretKey \mathbin\| expireTimestamp) \mathbin\| expireTimestamp$$

Using this token we have a unique expirable authentication system for our APIs,

questions:

  1. Should I concatenate keys+expTime or I should use something like HMAC? is this scenario vulnerable to attacks like length extension attacks without HMAC?
  2. What is the vulnerability of this system (if there is any)?
$\endgroup$
1
  • $\begingroup$ Comments are not for extended discussion; they have been moved to chat. $\endgroup$
    – fgrieu
    Dec 4, 2021 at 20:12

1 Answer 1

2
$\begingroup$

Using $$token = SHA256(APIKey \mathbin\| SecretKey \mathbin\| expireTimestamp) \mathbin\| expireTimestamp$$

is not secure since it can cause a length extension attack as;

$$token2 = SHA256(APIKey \mathbin\| SecretKey \mathbin\| expireTimestamp \| \color{red}{extension}) \mathbin\| (expireTimestamp \| \color{red}{extension}) $$

This is a valid token for the forgery.

NIST on call to SHA3 candidates required to be resistant to length-extension attacks. Keccak now named SHA3 as the winner and Blake2 is still a good alternative from the competition. Both are resistant to length extension attacks, Keccak by using the capacity and Blake2 is using HAIFA construction, are secure to length extension attacks.

To mitiage one can use HMAC;

$$token = \operatorname{HMAC-SHA256}(privateKey, publicKey \mathbin\| expireTimestamp) \mathbin\| expireTimestamp$$ Note that this will call the SHA-256 at least two times ( three times if the key is longer than the block size of the hash function, 512-bit for SHA-256).

Instead of HMAC, we can use BLAKE2. BLAKE2 is very fast and even we have a parallel version BLAKE3 and using

$$token = \operatorname{BLAKE2}( publicKey \mathbin\| privateKey \mathbin\|expireTimestamp) \mathbin\| expireTimestamp$$ is secure.

NIST also standardized a MAC for SHA3 named KMAC( or here).

Both BLAKE2 and KMAC are preferable to HMAC.

If you insist to use SHA2 with a 256-bit output size then use SHA-512/256 which is the truncated version of SHA-512/256 with different initial values to separate the domains. SHA-512/256 is immune to length extension attacks and it is 64-bit CPU friendly by design.

$\endgroup$
3
  • $\begingroup$ thank you @kelalaka, this really helps. your example with the extension created another question for me, What if all 3 part has a fixed length always. e.g (apikey=36, privateKey=44, expireTime=10). Is SHA256 vulnerable in this case or not. because expireTime has a fixed length no one can add a extension to it $\endgroup$ Dec 4, 2021 at 5:34
  • 1
    $\begingroup$ If you know the sizes and check them, then there is no longer an extension attack as long as the attacker doesn't trick that part too. I would go a length extension attack secure one to eliminate attack surfaces. $\endgroup$
    – kelalaka
    Dec 4, 2021 at 6:29
  • 1
    $\begingroup$ Note; I've updated the answer to include the SHA-512/256 that you may want to use. $\endgroup$
    – kelalaka
    Dec 4, 2021 at 7:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.