Add a public key to a jks keystore - rsa

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.

Related

DirName and serial number to the X509 Authority Key Identifier extension

I'm trying to add DirName and serial number to the X509 Authority Key Identifier extension using the FreeIPA/IDM server (not openssl) so it will looks like
X509v3 Authority Key Identifier
keyid:11:1B:30:08:A2:F0:F9:6C:D5:8D:24:E3:31:EA:D3:A8:FC:BC:13:FD
DirName:/CN=.
serial:D4.....
I tried to add parameters to a certificate profile and then requested an SSL certificate using this profile I tried by adding only the serial number first
policyset.serverCertSet.9.constraint.class_id=noConstraintImpl
policyset.serverCertSet.9.constraint.name=No Constraint policyset.serverCertSet.9.default.class_id=authorityKeyIdentifierExtDefaultImpl
policyset.serverCertSet.9.default.name=Authority Key Identifier
Extension Default
policyset.serverCertSet.9.default.params.authorityKeyIdentifierCertificateSe
rialNumber=1000
and I replaced the bottom line with:
policyset.serverCertSet.9.default.params.authorityKeyIdentifierCertSerialNumber=1000
policyset.serverCertSet.9.default.params.authorityCertSerialNumber=1000
However the serial number doesn't show in the Authority Key Identifier extension

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

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.

Generate x5c certificate chain from JWK

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