RSA Keys Generation
RSA (Rivest–Shamir–Adleman) is a widely used public-key crypto-system that enables secure data transmission, digital signatures, and key exchange.
RS256, part of the RSA encryption algorithm, utilizes SHA-256 for hashing and a key (usually 2048-bit, 4096-bit or higher) to secure digital communications.
In the realm of JSON Web Token authentication, RS256 plays a crucial role since the integrity and authenticity of JWTs can be verified through signature mechanisms, such as RS256, where a public/private key pair is employed. This ensures that the information contained within the token remains tamper-proof and trustworthy.
In this section you will learn how such keys are generated and used alongside the Authentication JWT plugin provided by Ktor.
Generating an RSA private key
To generate a private key, you can use OpenSSL, ssh-keygen
or another tool of your choice for creating authentication key pairs. For demonstration purposes, OpenSSL will be used.
In a new terminal window, run the following command:
The openssl genpkey command generates a private 2048-bit key using the RSA algorithm and stores it in the specified file, here ktor.pk8
. The content of the file is Base64 encoded and thus, needs to be decoded before the public key can be derived.
Deriving the public key
In order to derive the public key from your previously generated private key, you will need to perform the following steps:
Decode the private key.
Extract the public key.
Save the public key in PEM format.
To do this with OpenSSL, run the following command:
openssl rsa
: This is theOpenSSL
command for working with RSA keys. In this context, it is used to perform operations related to RSA keys.-in ktor.pk8
: This option specifies the input file (ktor.pk8
) from which OpenSSL should read the RSA private key.-pubout
: This option instructs OpenSSL to output the public key corresponding to the private key provided in the input file.|
: The pipe (|) symbol is used to redirect the output of the previous command (the public key generated by openssl rsa) to the tee command.tee ktor.spki
:tee
is a command-line utility that reads from standard input and writes to both standard output and one or more files. This part of the command instructs tee to write the received input to a file namedktor.spki
. So, the public key will be both displayed on the terminal and saved in thektor.spki
file.
With the public key at hand, you can now derive its exponent and modulus values.
Extracting the modulus & exponent attributes
Now that you have your key-pair, you need to extract the e
(exponent) and n
(modulus) attributes of your public key, in order to use them in your jwks.json
file. This requires the following steps:
Read the public key from the
.spki
file you created.Display information about the key in a human-readable format.
To do this using OpenSSL, run the following command:
pkey
: This is the OpenSSL command-line utility for processing private and public keys.-in ktor.spki
: Specifies the input file containing the public key in PEM format. In this case, the input file isktor.spki
.-pubin
: Indicates that the input file contains a public key. Without this option, OpenSSL would assume that the input file contains a private key.-noout
: This option prevents OpenSSL from outputting the encoded public key. The command will only display information about the public key, and the actual key won't be printed to the console.-text
: Requests that OpenSSL display the textual representation of the key. This includes details such as the key type, size, and the actual key data in human-readable form.
The expected output looks like this:
Converting and encoding the modulus and exponent attributes
In the previous step you extracted the n
and e
attributes needed for your jwks.json
file. However, they are in hexadecimal format. You now need to convert the hexadecimal representation of the exponent and modulus to their respective Base64URL encodings.
Exponent
The exponent attribute has a HEX value of 0x10001
. To convert the value to Base64URL, use the following command:
echo 010001
: This part of the command uses theecho
command to output the string "010001", which represents the public exponent (e) of the RSA key, to the standard output.|
: The|
character is a pipe that takes the output from the preceding command and passes it as input to the following command.xxd -p -r
: This command is used to convert hexadecimal to binary. It takes the hexadecimal input and produces the corresponding binary output.| base64
: This part of the command takes the binary output from the previous step and encodes it in Base64 format using thebase64
command.
This is the expected output for the aforementioned exponent value:
The Base64URL encoded value of the exponent is AQAB
and does not require further processing for this case. In other cases, you may need to use the tr
command as shown in the next step.
Modulus
For the n
attribute, you will use the tr
utility to further process the hexadecimal representation of the modulus.
echo "b5:f2:5a:2e:bc:d7:20:b5:20:d5:4d:cd:d4:a5: \ ... "
: This part of the command echoes a multi-line hexadecimal string, representing a series of bytes. The backslashes at the end of each line indicate line continuation.tr -d ": \n"
: Thetr
command is used to delete characters specified in the argument list. Here, it removes colons, spaces, and newline characters from the hexadecimal string, making it a continuous string of hex digits.xxd -p -r
:xxd
is a utility for creating a hex dump of a binary file or converting a hex dump back to binary. The-p
option specifies plain hexdump without line number or ASCII character columns. The-r
option reverses the operation, converting hex back to binary.base64
: Encodes the binary output from the previous step into Base64 format.tr +/ -_
: Translates the + and / characters in the Base64 output to - and _, respectively. This is a common modification for URL-safe Base64 encoding.tr -d "=\n"
: Removes any equal signs (=) and newline characters from the final Base64-encoded string.
The output of the above command is:
By leveraging the tr
command properly, the modulus field has been encoded into a Base64URL string that you can use in your jwks.json
file.
Populating the jwks.json file
In the previous steps, you gathered the following necessary information:
An RSA key-pair.
The modulus of the RSA public key in Base64URL format.
The exponent of the RSA public key in Base64URL format.
With these at hand, you can now populate the jwks.json file of your Ktor project with the following attributes:
The
e
andn
values with the Base64URL encoded values you produced in the previous steps.A key id (in this case, the
kid
is derived from the sample project).The
kty
attribute asRSA
.
The only remaining step is to specify your private key so that your Ktor project can use it for authentication.
Defining the private key
With your public key information set up, the last step is to provide your Ktor project with access to your private key.
Assuming that you have extracted your private key (which you generated at the beginning in your .pk8
file) into an environment variable on your system, called jwt_pk
in this case, your resources/application.conf
file's jwt section should look similar to: