1

We have a web-service that follows RFC 7515 / JWT: it supplies public keys on a /jwt endpoint and encodes data transferred on its main endpoints into JOSE+JSON. Using several standard JAVA libraries to achieve this process everything is now up and running.

I want to manually create the output for the /jwt endpoint that provides the public key in my keypair to supply it as a plaintext mock, however, I am not sure how to generate the "n" field of the jwt. The specs say this:

6.3.1.1. "n" (Modulus) Parameter

The "n" (modulus) parameter contains the modulus value for the RSA public key. It is represented as a Base64urlUInt-encoded value.

How do I properly get to the modulus value as Base64urlUInt?


Example

I have created a simple RSA key pair in Keystore Explorer for this question, of which the public key is the following:

-----BEGIN PUBLIC KEY-----     
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9KGWjySg0x9yJ5uOi8yF
JUS6jB9OC/DvOoTlZibihRZNo5Z54lyfE1tC5a5Cn0rpYlvo4xFoCFEqwSUOapmk
/n30rCTixBibhee/J7r9kRmavPijn6V54kaOuJ2fI0UY6JziS52tz/XXmbbtMyBR
KCeVSN9PmNyRMJ5WUsnnk4j/U853opPVhsPpSgN2kSOHVX8ZlsJL/HFTx8mfY8DS
5f/ayLwsuNmM7h/DIktvhfbtfYQ7pssuAafJ2NCykBh6ZgnL9huKkmlTz54/2Lcv
o78UJVHWWYQq10Mm1HJ0ivH+j7hZEMJqUNmbkya1PVRMhAMu0o+20vubr9X2Rifv
awIDAQAB
-----END PUBLIC KEY-----

And in the Keytool Explorer UI I can naviate to fields of the public key, for which the modulus value is this:

0xF4A1968F24A0D31F72279B8E8BCC852544BA8C1F4E0BF0EF3A84E56626E285164DA39679E25C9F135B42E5AE429F4AE9625BE8E3116808512AC1250E6A99A4FE7DF4AC24E2C4189B85E7BF27BAFD91199ABCF8A39FA579E2468EB89D9F234518E89CE24B9DADCFF5D799B6ED33205128279548DF4F98DC91309E5652C9E79388FF53CE77A293D586C3E94A0376912387557F1996C24BFC7153C7C99F63C0D2E5FFDAC8BC2CB8D98CEE1FC3224B6F85F6ED7D843BA6CB2E01A7C9D8D0B290187A6609CBF61B8A926953CF9E3FD8B72FA3BF142551D659842AD74326D472748AF1FE8FB85910C26A50D99B9326B53D544C84032ED28FB6D2FB9BAFD5F64627EF6B

Screenshot of modulus in Keystore Explorer

As far as I can tell, Base64URLEncoded this becomes:

MHhGNEExOTY4RjI0QTBEMzFGNzIyNzlCOEU4QkNDODUKMjU0NEJBOEMxRjRFMEJGMEVGM0E4NEU1NjYyNkUyODUKMTY0REEzOTY3OUUyNUM5RjEzNUI0MkU1QUU0MjlGNEEKRTk2MjVCRThFMzExNjgwODUxMkFDMTI1MEU2QTk5QTQKRkU3REY0QUMyNEUyQzQxODlCODVFN0JGMjdCQUZEOTEKMTk5QUJDRjhBMzlGQTU3OUUyNDY4RUI4OUQ5RjIzNDUKMThFODlDRTI0QjlEQURDRkY1RDc5OUI2RUQzMzIwNTEKMjgyNzk1NDhERjRGOThEQzkxMzA5RTU2NTJDOUU3OTMKODhGRjUzQ0U3N0EyOTNENTg2QzNFOTRBMDM3NjkxMjMKODc1NTdGMTk5NkMyNEJGQzcxNTNDN0M5OUY2M0MwRDIKRTVGRkRBQzhCQzJDQjhEOThDRUUxRkMzMjI0QjZGODUKRjZFRDdEODQzQkE2Q0IyRTAxQTdDOUQ4RDBCMjkwMTgKN0E2NjA5Q0JGNjFCOEE5MjY5NTNDRjlFM0ZEOEI3MkYKQTNCRjE0MjU1MUQ2NTk4NDJBRDc0MzI2RDQ3Mjc0OEEKRjFGRThGQjg1OTEwQzI2QTUwRDk5QjkzMjZCNTNENTQKNEM4NDAzMkVEMjhGQjZEMkZCOUJBRkQ1RjY0NjI3RUYKNkI=

However, that value doesn't work in my program. Also, using publicly available PEM->JWT converters (e.g. JWK to PEM Convertor online) I get different results for the modulus "n", see:

{"kty":"RSA","e":"AQAB","kid":"351556fe-fc69-4cf7-bce6-47a8806445a0","n":"9KGWjySg0x9yJ5uOi8yFJUS6jB9OC_DvOoTlZibihRZNo5Z54lyfE1tC5a5Cn0rpYlvo4xFoCFEqwSUOapmk_n30rCTixBibhee_J7r9kRmavPijn6V54kaOuJ2fI0UY6JziS52tz_XXmbbtMyBRKCeVSN9PmNyRMJ5WUsnnk4j_U853opPVhsPpSgN2kSOHVX8ZlsJL_HFTx8mfY8DS5f_ayLwsuNmM7h_DIktvhfbtfYQ7pssuAafJ2NCykBh6ZgnL9huKkmlTz54_2Lcvo78UJVHWWYQq10Mm1HJ0ivH-j7hZEMJqUNmbkya1PVRMhAMu0o-20vubr9X2Rifvaw"}

How do I calculate this "n" myself properly? I have tried removing the 0x prefix from the modulus, and the base10 value of the modulus to no avail. It would be extra handy if you could help me finding the right parts directly in Keystore Explorer.

Spork
  • 255
  • 4
  • 11

1 Answers1

2

You base64url-encoded the characters 0, x, F, 4, A, 1, etc., plus CRLF pairs every 32 characters. The display 0xF4A1... is a C/python-style hex representation of what is actually a binary value; you need to encode that value, consisting of bytes whose values in hex are 0xF4, 0xA1, etc. How you create such a value depends on the programming language(s) or tool(s) you are using which you didn't specify, and anyway this is not about information security but basic programming.

Although as an awful hack which may be acceptable for testing only, which depends on the ASN.1 DER encoding making it marginally on-topic IMBO, because DER of X.509 SubjectPublicKeyInfo for 2048-bit RSA key has the modulus magnitude at a multiple of 3, you can textually manipulate the PEM format by:

  • remove the BEGIN and END lines and join the rest to a single line/string
  • delete the first 44 and last 6 characters (encoding the first 33 and last 4.5 bytes)
  • change any + and / characters to - and _ respectively
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9KGWjySg0x9yJ5uOi8yF
JUS6jB9OC/DvOoTlZibihRZNo5Z54lyfE1tC5a5Cn0rpYlvo4xFoCFEqwSUOapmk
/n30rCTixBibhee/J7r9kRmavPijn6V54kaOuJ2fI0UY6JziS52tz/XXmbbtMyBR
KCeVSN9PmNyRMJ5WUsnnk4j/U853opPVhsPpSgN2kSOHVX8ZlsJL/HFTx8mfY8DS
5f/ayLwsuNmM7h/DIktvhfbtfYQ7pssuAafJ2NCykBh6ZgnL9huKkmlTz54/2Lcv
o78UJVHWWYQq10Mm1HJ0ivH+j7hZEMJqUNmbkya1PVRMhAMu0o+20vubr9X2Rifv
awIDAQAB
-----END PUBLIC KEY-----

->

9KGWjySg0x9yJ5uOi8yFJUS6jB9OC_DvOoTlZibihRZNo5Z54lyfE1tC5a5Cn0rpYlvo4xFoCFEqwSUOapmk_n30rCTixBibhee_J7r9kRmavPijn6V54kaOuJ2fI0UY6JziS52tz_XXmbbtMyBRKCeVSN9PmNyRMJ5WUsnnk4j_U853opPVhsPpSgN2kSOHVX8ZlsJL_HFTx8mfY8DS5f_ayLwsuNmM7h_DIktvhfbtfYQ7pssuAafJ2NCykBh6ZgnL9huKkmlTz54_2Lcvo78UJVHWWYQq10Mm1HJ0ivH-j7hZEMJqUNmbkya1PVRMhAMu0o-20vubr9X2RifvawID

Presto!

dave_thompson_085
  • 9,759
  • 1
  • 24
  • 28
  • Thank you. I feel silly of course now that it's hitting me in the face, I had indeed just converted the hex value as characters. The second part of your answer brought me new insights though - which may be equally silly, but less logically silly - I never bothered to understand what was in the DER, so it just contains the modulus right there...! – Spork Sep 19 '19 at 08:54