Given a private key using algorithm RSA-PSS with SHA256 is it possible to use this key to sign a JWT using algorith RS256 (RSA with SHA256) instead of PS256 (RSA-PSS with SHA256)?
The German government seems to be of the opinion it is possible and wants us to do this for one of their new tax reporting related APIs.
So far I've tried to generate a JWT using:
- (java) auth0/java-jwt
- (nodejs) jsonwebtoken
Neither library would allow this.
I also pushed ChatGTP 3.5 about this topic and it claims it should somehow be possible:
RSA-PSS (Probabilistic Signature Scheme) and RSA (used in RS256) are two different signature schemes. While both are based on RSA, they have different padding schemes and formats for generating signatures. RS256 specifically uses the PKCS#1 v1.5 padding scheme with RSA, whereas RSA-PSS uses a different padding scheme.
In most cases, if a certificate is generated using the RSA-PSS algorithm, it may not be directly compatible with the RS256 algorithm, as they use different padding schemes and signature formats.
However, some cryptographic libraries and frameworks might provide ways to convert between different signature schemes or to extract the RSA key pair from the X.509 certificate for use in other algorithms. If such conversion or extraction methods are available and the resulting RSA key pair is compatible with RS256 (using the appropriate padding scheme), then you could potentially use the RSA-PSS certificate to sign JWT tokens with RS256.
So is it technically possible? Any recommendations for tools that support this? Thanks.
Command used to generate the key pair (details replaced with variables):
openssl req -newkey rsa-pss -new -nodes -x509 -days 3650 \
-subj "/C=$C/ST=$ST/L=$L/O=$O/OU=$OU/CN=$CN/emailAddress=$email" \
-pkeyopt rsa_keygen_bits:4096 \
-pkeyopt rsa_pss_keygen_md:sha256 \
-pkeyopt rsa_pss_keygen_mgf1_md:sha256 \
-pkeyopt rsa_pss_keygen_saltlen:32 \
-sigopt rsa_pss_saltlen:32 \
-sigopt rsa_padding_mode:pss \
-sigopt rsa_mgf1_md:sha256 \
-keyout privateKey.pem \
-out cert.pem
openssl x509 -pubkey -noout -in cert.pem > publicKey.pem
Edit:
Based on the advise I got here (thanks again) I went with the following:
# create private key in RSA format
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:4096
create self-signed certificate with RSA-PSS signing algorithm from this private key
openssl req -x509 -new -key private_key.pem -out certificate.pem -days 3650 -sha256
-sigopt rsa_padding_mode:pss
-sigopt rsa_pss_saltlen:32
optionally create public key in RSA format from certificate
openssl x509 -pubkey -noout -in certificate.pem > public_key.pem
or from private key
openssl rsa -pubout -in private_key.pem -out public_key.pem
The certificate then has the following settings:
$ openssl x509 -in certificate.pem -text | grep Algorithm
Public Key Algorithm: rsaEncryption
Signature Algorithm: rsassaPss
It can now be used to verify RS256 JWTs that have been signed using the private key.