Generate x5c certificate chain from JWK - jwt

I am using nimbus-jose-jwt 5.14 and I generated RSA key pair with the following code
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(2048);
KeyPair keyPair = gen.generateKeyPair();
JWK jwk = new RSAKey.Builder((RSAPublicKey)keyPair.getPublic())
.privateKey((RSAPrivateKey)keyPair.getPrivate())
.keyUse(KeyUse.SIGNATURE)
.keyID(UUID.randomUUID().toString())
.build();
Now I need to expone some "metadata" about the public key:
e
kid
kty
n
use
x5c
How can I obtain x5c ? Is it possible to generate X509 certificate with this library? This field is null:
if (jwk.getX509CertChain() == null)

You have generated a key pair, not a certificate. A certificate contains a public key but it is not derived from it, so you can't get a certificate directly from the public key.
To verify a JWT the recipient only needs the public key, so publishing the x5c is in fact unnecesary for this purpose
If you really want to publish a certificate, I suggest to generate it with OpenSSL and import the public key in your code to get the JWK parameters
openssl req -x509 -newkey rsa:2048 -keyout key.pem -days 365 -out certificate.pem

Related

Converting a .pem RSA Public and Private Key to .der X.509 certificates or JWK strings

I working on a project that uses JSON Web Tokens (JWT). I already have the code that creates the token that is signed by an RSA algorithm which was created by the openssl genrsa -des3 -out <private key file name>.pem 3076. I want to check the validity of the tokens I produce on the jwt.io website, but i need "[public/private] Key in...X.509 certificate, or JWK string format".
Format of private key:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,4AE3D092CB847166
(The actual key)
-----END RSA PRIVATE KEY-----
Format of public key:
-----BEGIN PUBLIC KEY-----
(The actual key)
-----END PUBLIC KEY-----
Is there any command/tools that can be used to convert these into X.509 certificates or JWK strings?
I have already tried using the openssl x509 -in <public or private key file name>.pem -inform PEM -out <X509 certificate file name>.der -outform DER command.
That would always return this error:
unable to load certificate
140258002609472: error: 0909006C: PEM routines: get_name:no start line:../crypto/pem/pem lib.c:745: Expecting: TRUSTED CERTIFICATE
All of the commands have been run using the terminal from a replit project. I am not sure if that plays a role or not but I mention it just in case.
Do you use Windows? Check the encoding. Change to UTF-8 through the Notepad and create it.

Keycloak does not have all the Keys available in the storage

I have created a realm and added new keystore(RS384) in the Providers section
When I tried authenticate using postman. I am getting below error in Keycloak console
PublicKey wasn't found in the storage. Requested kid: 'Y3RDLAudovJPEU3Z9BMJL3OyuzqsgAj4424CpxnJqkI' . Available kids: '[]'
Kid is available in the Keys section for the Realm. I am not sure what is causing that. Any help on this is so much appreciated
Edit
Client Authentication
Added JWKS keys from certs endpoint
In Postman made call to token endpoint with client_assertion which has signed JWT and got response back "Invalid client: Unable to load Public key "
I think you gave wrong a value(or format) of "Private RSA Key" and "X509 Certificate" file when you add the key-store at Keycloak UI.
it is possible to get the public Key for RS384 by Postman and UI.
I demoed with Keycloak 18.0.0 with "ssh-keygen" & "openssl" on Ubuntu.
Generate RS384 private key and public key and certification file
ssh-keygen -t rsa -b 4096 -E SHA384 -m PEM -P "" -f RS384.key
openssl req -new -x509 -key RS384.key -out RS384-cert.pem -days 360
it will create three files
RS384-cert.pem <- certification file
RS384.key <- private key
RS384.key.pub <- public key
Add Keystore with 1.'s files
New Keystore will be created
Can get Key by Postman
can compare public key between UI and openssl generated it.
you can check API call value and JWT creator web site
with KID and public key
https://russelldavies.github.io/jwk-creator/
The issue is I did not add "use":"sig" in the JWKS that is kid is not available

Add a public key to a jks keystore

I have been given a public xml key in the following format:
<RSAKeyValue>
<Modulus>MODULUS_VALUE</Modulus>
<Exponent>EXPONENT_VALUE</Exponent>
</RSAKeyValue>
With this key I need to verify a signed message that I would receive.
I have created a keystore with keytool but I am unable to import this public key there.
Is it possible to add this public key to a blank new jks keystore that I would create?
So far I haven't been able to do exactly that. I would imply that I don't have the private key, I only have the public key in xml format.

How to obtain the ADFS Public Key and validate the signature on a JWT Token?

I need to validate the signature of a JWT token which was signed on an ADFS server. I can validate a self-signed JWT token, but not a token received from ADFS. How should I be obtaining the public key?
To get the public key from the ADFS server I asked my colleague to export
the certificate from the ADFS server. On the ADFS console He looked in
"Services" > "Edit Federation Service Properties",
"General" tab where he found three entires. They were under the headings
"Token Signing", "Token Decrypting" and "Service Communication".
For each he viewed the certificate and then exported the DER certificate
(without private key). They were then transformed to PEM (using
openssl x509 -inform der -in cert.cer -out cert.pem) but none of these keys
allow my code to validate the sniffed JWT tokens.
My Java code takes a JWT Token and a Public Key, and validates that the token was signed with the Public Key. If I use a self-signed key pair and a self generated JWT Token then the code appears to work, and reports the signature is OK. When the token is copied from an HTTP Header in a message from ADFS the same code reports the signature is invalid.
Here is the code I use to load the PEM public key:
FileInputStream fis = new FileInputStream(publicKeyFile)
Reader keyReader = new InputStreamReader(publicKeyStream);
PemReader pemReader = new PemReader(keyReader);
PEMParser pemParser = new PEMParser(pemReader);
Object pemObject = pemParser.readObject();
if (pemObject instanceof X509CertificateHolder) {
X509CertificateHolder x509CertificateHolder = (X509CertificateHolder) pemObject;
X509Certificate x509Certificate = new JcaX509CertificateConverter()
.setProvider("BC").getCertificate(x509CertificateHolder);
return x509Certificate.getPublicKey();
}
Here is the code I use to validate the signature:
String signatureAlgorithm = publicKey.getAlgorithm();
Signature signatureInstance = Signature.getInstance(signatureAlgorithm);
signatureInstance.initVerify(publicKey);
byte[] messageBytes = Base64.encodeBase64(message.getBytes(UTF_8));
signatureInstance.update(messageBytes);
byte[] receivedSignature = Base64.decodeBase64URLSafe(signature);
return signatureInstance.verify(receivedSignature);
(I've removed the exception handling and resource closing for brevity above.
I'm using tomcat's Base64 class.)
The code runs without error but indicates that the signature is not valid. It seems to me that any of the below could be wrong:
None of the public keys extracted from the ADFS server are the relevant public key.
The conversion of the public keys from .cer to .pem may be incorrect.
The code to validate the signature, or load the public key, may be wrong.
Refer this and this.
The keys you refer to:
"Token Signing" - used for a SAML token derived from a CP or RP trust e.g. federation via SAML or WS-Fed
"Token Decrypting" - likewise
"Service Communication" - used for server SSL communication
For a JWT, I assume you are using OpenId Connect?
You use:
https://[Your ADFS hostname]/adfs/.well-known/openid-configuration
This has a pointer to the keys.

Apple Push Certificate - Invalid Certificate Signing Request

I've created my own CSR with the following command
openssl req -new -newkey rsa:2048 -nodes -out bgsisson_com.csr -keyout bgsisson_com.key -subj "/C=US/ST=CA/L=Los Angeles/O=Benjamin Sisson/OU=Development/CN=bgsisson.com/emailAddress=myemail#dom.com"
Then I created a CRT with the following command
openssl x509 -req -days 365 -in bgsisson_com.csr -signkey bgsisson_com.key -out bgsisson_com.crt
When I try to upload this cert to https://identity.apple.com/pushcert/ I get a invalid certificate signing request.
Am I creating the certificate wrong? Does the cert need to be verified?
Thanks!
Update - Removed wildcard from CN. I'm still getting an Invalid Cert signing request.
Update - added CSR and CRT. I test uploading both of them, but I think I just need to upload the CSR
Update - added emailAddress to CSR
bgsisson_com.csr
-----BEGIN CERTIFICATE REQUEST----- MIICvDCCAaQCAQAwdzELMAkGA1UEBhMCdXMxCzAJBgNVBAgTAkNBMRQwEgYDVQQH
EwtMb3MgQW5nZWxlczEYMBYGA1UEChMPQmVuamFtaW4gU2lzc29uMRQwEgYDVQQL
EwtEZXZlbG9wbWVudDEVMBMGA1UEAxMMYmdzaXNzb24uY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAudmpTvmnWLivwLaFNx6w/kgwUbPCr8ujZOtx
1Lu/+alpuHPoQ4Kpyt3rsj9wc/PSWXBFjIV607YCINTJrQfHUJMq55s3aWxeroB9
llqXn0qTJ2GujAmuWBX2nvIZucQVF1xX3/V1179CKM/+z/rE4ehiJdEnMQk6Otrv
HT1W/eIL5rzSjky+ZpaRSguUpyQSsSuD4Cdfo6NMiY5RVvh9N/Q/O+jEpAJxEHOd
nAbJj8WU2WW9MxtUw21UODh5kHX+b8sLfuKB9EJ2XUqwvdJt9MgnrAiYVkvjq1iT
dZFd2nHiKZnLRr2jBZ74u9duqwm9kD8zoOAiMzbFUTjD1AZIHwIDAQABoAAwDQYJ
KoZIhvcNAQEFBQADggEBAK+Zr5pdtcqVUtMD8843wz7h3bAOVIvrJpbr2/g1mUvo
4Pn27Xlw/CZL2aqOniTTCOeGvWAvHtckxaTxPL3Ruid2/QTnOgKecUnqVPAoqaBP
0SPJDo3X1rbWKVTTJOvT67Kywtd8q+Msx46IqE/2YWur+XO47dnKWR4lPJipgjjY
p+zt9TPTAqu+M6xwqsslUy9r68GaQGTdRdQSyZB5XAg+I271mtxrSrImaAPEi1MY
2ch9r4NaFWH9X7CH67Y0QCKsGjKU4Ftz6x8c1cf4n8TuWgD5/S2UeY+zj3JvjVgj
DJlQyKGmYCC6G0FcoWSD7yCvJ+k0DcoJuGUO3094RIg=
-----END CERTIFICATE REQUEST-----
bgsisson_com.crt
-----BEGIN CERTIFICATE----- MIIDajCCAlICCQCMvMl8OXFb3jANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQGEwJ1
czELMAkGA1UECBMCQ0ExFDASBgNVBAcTC0xvcyBBbmdlbGVzMRgwFgYDVQQKEw9C
ZW5qYW1pbiBTaXNzb24xFDASBgNVBAsTC0RldmVsb3BtZW50MRUwEwYDVQQDEwxi
Z3Npc3Nvbi5jb20wHhcNMTIwMzIyMTY1MzA1WhcNMTMwMzIyMTY1MzA1WjB3MQsw
CQYDVQQGEwJ1czELMAkGA1UECBMCQ0ExFDASBgNVBAcTC0xvcyBBbmdlbGVzMRgw
FgYDVQQKEw9CZW5qYW1pbiBTaXNzb24xFDASBgNVBAsTC0RldmVsb3BtZW50MRUw
EwYDVQQDEwxiZ3Npc3Nvbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC52alO+adYuK/AtoU3HrD+SDBRs8Kvy6Nk63HUu7/5qWm4c+hDgqnK3euy
P3Bz89JZcEWMhXrTtgIg1MmtB8dQkyrnmzdpbF6ugH2WWpefSpMnYa6MCa5YFfae
8hm5xBUXXFff9XXXv0Ioz/7P+sTh6GIl0ScxCTo62u8dPVb94gvmvNKOTL5mlpFK
C5SnJBKxK4PgJ1+jo0yJjlFW+H039D876MSkAnEQc52cBsmPxZTZZb0zG1TDbVQ4
OHmQdf5vywt+4oH0QnZdSrC90m30yCesCJhWS+OrWJN1kV3aceIpmctGvaMFnvi7
126rCb2QPzOg4CIzNsVROMPUBkgfAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBALa5
1rkRjCAJF1WU2TIM9FA7A7upb8YVKnagthCIn3kLYBqI4wRHO28HPm53IWJP/hUG
80rjczKY03PFjuiikrlPzUdBR99n4jq6UhcFdG4Z948lXoS2WsIJc6vZmA6wBAIE
h+Xe4SjdPvhsKKrVLFEgpSb/67mUdHF2qVkhvkqs8EgJ65fozjW2adyF6NxOWrmG
5Q++Dp/+K1TSkLM/yZieWWbQ042OyYCZ+agIuwpduW5waKbN1+TERKJo0eFlwQUi
w7KsgLpfoyGji4FzznODGxRq/2Ja5VPnnfa4pxG+l0qkn5VoW27qFHJy5E6Z7Bqb
RqpfbiQ6jeLcqCiWgig=
-----END CERTIFICATE-----
You need to sign the certificate request from a vendor with an Enterprise Developer Account. The information is available at http://www.softhinker.com/in-the-news/iosmdmvendorcsrsigning
I suspect that it is tripping over the wildcard in the CN as AppIDs with wildcards are not accepted.