Duo Secret Key Length Issue

Fix versions

Description

The Duo OIDC client secret key is a 40 character alphanumeric (^[a-zA-z0-9]*$) string. The key is used as a pre-shared secret between the client and Duo. Duo use, and only use, the HS512 algorithm to compute a hashed message authentication code (HMAC) in order to preserve JWT integrity and prove authenticity.

The 40 character secret key is stored internally as a 16 bit (UTF-16) Java String but converted by the Auth0 libraries to a byte array (to get the key in bits) assuming a UTF-8 encoding. As the characters pool is limited to a subset of ASCII,  the 40 character secret is represented by 40 bytes. It is this array of 40 bytes (320 bits) that is used as the secret key to generate the JWS authentication code.

According to the JSON Web Algorithms (JWA) Specification (RFC7518), the secret key length must be the *same* size as the size of the hash output or *larger* - this can also be observed as a recommendation in the HMAC RFC (RFC2014 section 2). For HS512 for example, as the output size is 512bits, according to both ‘best practice’ and the JWA specification the key length must be at least 512bits[1]. That means the Duo Secret key should be at least 64 characters assuming a UTF-8 encoding of the restricted character set, or better, as a more complex (higher entropy) 512bit string base64 encoded.

Is this a problem?

Primarily there are security implications from using ‘weaker’ keys and hence 'weaker' HMACs. In addition, for our implementation going forward, Duo’s OIDC authorization endpoint *requires* a signed Request JWT, and the token endpoint *requires* a signed client_assertion JWT. The Java Nimbus OIDC-JWT library follows the JWA specification closely in terms of generating a JWS and is unable to generate a HS512 signature using the existing 40 character string key (UTF-8 encoded). Because of this, we can not directly use Nimbus to either; create the authorization request JWT parameter, or create the JWT used for exchanging the auth_code for the id_token .

This also implies the Duo authorization service is generating a JWS using the same (not recommended) private key length and algorithm.

[1]This requirement is echoed in other specifications e.g. IPSec also fixes the key length to the output length of the algorithm used for authentication/integrity cases (RFC4868), and TLS uses the same key length as the hash function output.

Environment

None

Assignee

Activity

Show:

Philip SmartOctober 28, 2020 at 4:29 PM

created a new issue, JDUO-20.

Philip SmartOctober 16, 2020 at 1:32 PM

I think I will do that, to remove the Auth0 dep and make the Nimbus client based module a viable alternative to the DuoSDK.

Philip SmartOctober 16, 2020 at 12:59 PM

Probably manageable if we limit the scope (as you say) to supporting a single algorithm. As with the other libs we would be (ignoring the subtleties for the time being) sending the header and payload (using JSON compact serialisation) to the standard JCA Mac algorithm and appending the code to the end of the JWT.

Scott CantorOctober 16, 2020 at 12:50 PM

It had occurred to me to ask how much we'd have to build to handle one HMAC algorithm.

Philip SmartOctober 16, 2020 at 10:28 AM
Edited

Looks unlikely Duo are going to improve the strength of their secret key.

It also seems unlilely that Auth0 (the library Duo use to generate the JWS) will add a key length requirement to their library (https://github.com/auth0/java-jwt/issues/444#issuecomment-706985538).

This makes the Nimbus Duo client module a bit messy, because it has to use something other than Nimbus to sign (create an auth code for) the token - so unless we build our own version of that into the oidc-commons lib, we are stuck using yet another library.

Won't Fix

Details

Reporter

Affects versions

Created September 14, 2020 at 4:14 PM
Updated March 24, 2021 at 3:41 PM
Resolved October 28, 2020 at 4:32 PM