TeslaGov / ngx-http-auth-jwt-module

Secure your NGINX locations with JWT
MIT License
317 stars 122 forks source link

Documentation: JWT Key must be in hex format #50

Closed katsar0v closed 5 years ago

katsar0v commented 5 years ago

As seen here: https://github.com/TeslaGov/ngx-http-auth-jwt-module/blob/master/src/ngx_http_auth_jwt_module.c#L164

The key should be in hex format, a bit confusing.. some documentation + examples in other languages would be perfect

fitzyjoe commented 5 years ago

Thank you for pointing this out. I added some text to the readme to clarify.

katsar0v commented 5 years ago

Thank you @fitzyjoe. Any idea why it should represent 256 bits of data and exactly 32 pairs? Cannot it be a normal string like: .secret@pw123#@!

fitzyjoe commented 5 years ago

The module cannot use a string like the one you specified because hex pairs only range from 00 to FF.

The reason why it's coded this way is because when you can specify any byte value in hex... but using an ascii string, you cannot. For example if you wanted to represent 0 (0x00) you'd need to use a null character... or if you wanted to represent 8, you'd need to include a backspace (not possible). So if we allow a password to be specified by the normal range of ascii characters (numbers, uppercase letters, lowercase letters, symbols) we're restricting the byte values from 33 (0x21) to 126 (0x7E). When it's all said and done, these encryption/signing algorithms operate on bytes and you want your key to have an equal possibility of containing any byte as the next byte in the key.

I may have been too restrictive in my documentation of the key. I believe the algorithm actually supports a variable length key... however there are guidelines for the key length.

See NIST Special Publication 800-107 Recommendation for Applications Using Approved Hash Algorithms (you have to search a bit harder right now because of the government shutdown)

We're using HS-256, which is also known as HMAC with SHA-256. Here's a relevant snippet from the doc:

5.3.4 Security of the HMAC Algorithm

The security strength of the HMAC algorithm4 is the minimum of the security strength of K and the value of 2L (i.e., security strength = min(security strength of K, 2L)). For example, if the security strength of K is 128 bits, and SHA-1 is used, then the security strength of the HMAC algorithm is 128 bits. The HMAC key K shall be generated with a security strength that meets or exceeds the desired security strength of the HMAC application, and the approved hash algorithm in the HMAC application shall have a message digest length of at least half of the desired security strength (in bits) of the HMAC application. For example, if the desired security strength of the HMAC application is 256 bits, the HMAC key K shall be generated with a security strength of at least 256 bits, and an approved hash function with the message digest length of at least 256/2 (128) bits shall be used.

If you want to specify an ascii password as a key, your solution must include a Key Derivation Function https://en.wikipedia.org/wiki/Key_derivation_function

On Tue, Jan 8, 2019 at 3:45 AM Kristiyan notifications@github.com wrote:

Thank you @fitzyjoe https://github.com/fitzyjoe. Any idea why it should represent 256 bits of data and exactly 32 pairs? Cannot it be a normal string like: .secret@pw123#@!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/TeslaGov/ngx-http-auth-jwt-module/issues/50#issuecomment-452218876, or mute the thread https://github.com/notifications/unsubscribe-auth/AF68mugJgMJQnCrFlWLaJGD4Cq3SPXu4ks5vBFq9gaJpZM4ZzMJA .

katsar0v commented 5 years ago

Can we have an adapter that translates the string, because any language with libraries (Python & PyJWT or PHP and php-jwt) use normal string. I cannot use hex strings in format \x11\x22 in other languages, just because this module cannot translate the strings properly. In Python and PHP I can say that my secret can be whatever string I like, am sure that in Go language and much other languages this is possible as well. Do not get me wrong, if I knew C or C++ I would have already made a pull request.

katsar0v commented 5 years ago

If I have the secret .secret! in Python or Go, how do I translate it here? I need to change the whole system and security because of one incompatibility. You can also see the php documentation for signing with sha-256 with hmac: http://docs.php.net/manual/uk/function.hash-hmac.php - There is nothing for the key mentioned, so any string would be compatible

crain9412 commented 5 years ago

Using ASCII limits the entropy of your secret, which you really don't want to do. You can represent .secret! as 0x2e 0x73 0x65 0x63 0x72 0x65 0x74 0x21 in hex, but the point of using 0x00 to 0xFF is you can represent the full range of the possible values of a byte. If you encoded your string into hex you would only ever use 33 (0x21) to 126 (0x7E), which would make your secret much easier to guess both in terms of brute force and actually make it susceptible to dictionary attacks if people knew you were using a string encoded as hex.

https://en.wikipedia.org/wiki/ASCII is a system for representing bytes as human readable characters. For encryption purposes we have no reason to limit it to human readable characters, we use hex as a convenient method to represent the bytes we're using for our secret.

fitzyjoe commented 5 years ago

This shows how to specify a hex value as the key in php:

https://stackoverflow.com/questions/33814177/how-do-you-supply-a-specific-binary-key-to-the-php-hash-hmac-function

On Thu, Jan 10, 2019 at 11:51 AM Crain notifications@github.com wrote:

Using ASCII limits the entropy of your secret, which you really don't want to do. You can represent .secret! as 0x2e 0x73 0x65 0x63 0x72 0x65 0x74 0x21 in hex, but the point of using 0x00 to 0xFF is you can represent the full range of possible bytes. If you encoded your string into hex you would only ever use 33 (0x21) to 126 (0x7E), which would make your secret much easier to guess both in terms of brute force and actually make it susceptible to dictionary attacks if people knew you were using a string encoded as hex.

https://en.wikipedia.org/wiki/ASCII is a system for representing bytes as human readable characters. For encryption purposes we have no reason to limit it to human readable characters.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/TeslaGov/ngx-http-auth-jwt-module/issues/50#issuecomment-453168242, or mute the thread https://github.com/notifications/unsubscribe-auth/AF68mhWU9uKvdETFr6f3F47jvT85ybFrks5vB2-PgaJpZM4ZzMJA .

katsar0v commented 5 years ago

Thank you guys for the help, as well thanks for the clarification.