How to use RSA as kty jwk parameter (using jose4j) - rsa

I am using jose4j to encrypt a String with JWE, following this documentation https://bitbucket.org/b_c/jose4j/wiki/JWE%20Examples
In the example, they used {\"kty\":\"oct\",\"k\":\"Fdh9u8rINxfivbrianbbVT1u232VQBZYKx1HGAGPt2I\"}
It works well, but how to use RSA as kty ? Should I generate myself a key and put it in the "k" parameter ?

no, a JWK representation of an RSA key has different parameters e.g.:
{
"kty":"RSA",
"n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx
4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs
tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2
QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI
SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb
w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
"e":"AQAB",
"alg":"RS256",
"kid":"2011-04-29"
}
See RFC7517 : https://www.rfc-editor.org/rfc/rfc7517

Additions to Hans answer, I've looked to the Jose4j Github, and there were many tests that helped me to understand how RSA works on this lib.
Found my answer here : https://github.com/pvliesdonk/jose4j/blob/master/src/test/java/org/jose4j/jwe/RsaOaepKeyManagementAlgorithmTest.java

Related

How do you set permissions on a certificate in the Windows Certificate Store through PowerShell 7?

Every resource I've found so far, such as this question, boils down to:
Get the certificate as an X509Certificate2
Cast the PrivateKey property to RSACryptoServiceProvider
Do stuff involving CspKeyContainerInfo property on the private key
This works in PowerShell 5, but in PowerShell 7, the PrivateKey property is an RSACng, not an RSACryptoServiceProvider, and so step 2 doesn't work.
FYI, PrivateKey was deprecated. You are now required to use the GetRSAPrivateKey extension method.
I cannot find any documentation, but it appears that .Net Framework used to return an RSA that also implemented RSACryptoServiceProvider which is where we could get the CspKeyContainerInfo, but now we are required to grab the key RSA derived type RSACng which is returned by the extension method. From here you can grab properties like the $cert.Key.UniqueName

How to get publicKey in RSA_encrypt key-pair generation algorithm in STRING format in flutter

I am currently working on encryption in my flutter app wherein I am using RSA key-pair generator to get public and private key using the following code-
import 'package:rsa_encrypt/rsa_encrypt.dart';
import 'package:pointycastle/api.dart' as crypto;
//Future to hold our KeyPair
Future<crypto.AsymmetricKeyPair> futureKeyPair;
//to store the KeyPair once we get data from our future
crypto.AsymmetricKeyPair keyPair;
Future<crypto.AsymmetricKeyPair<crypto.PublicKey, crypto.PrivateKey>> getKeyPair()
{
var helper = RsaKeyHelper();
return helper.computeRSAKeyPair(helper.getSecureRandom());
}
Now I want to get the keyPair.publicKey in string format but if i print keyPair.publicKey, it shows "Instance of RSA publicKey" . How can I get it in string format??
It is always best to use standardized formats when saving public keys. For RSA public keys you can store them in layers, much like a Matroesjka doll.
Encode the public key in the ASN.1 / DER format specified in the PKCS#1 RSA standard;
Encode that public key in a format called SubjectPublicKeyInfo which is part of the X.509 specifications - it indicates that this is indeed an RSA key;
Apply so called PEM "ASCII armor", which consists of a header & footer line indicating the generic SubjectPublicKeyFormat (just PUBLIC KEY), with a multi-line base 64 encoding of the public key from step 2 in between.
Sounds like a lot of work, but if you look here you'll find handy methods called encodePublicKeyToPem and parsePublicKeyFromPem that do these 3 steps for you (it actually does both 1 and 2 in the same function, which is a bit of a shame but not that important).
These keys are rather portable and are also usable by e.g. OpenSSL or PGP.

authlib: some client_kwargs in config are not used

Love authlib overall. Question about client_kwargs described in
https://docs.authlib.org/en/latest/client/frameworks.html
and https://docs.authlib.org/en/latest/client/django.html
Problem statement: I tried to pass "scope" and "audience" key/value pairs in the client_kwargs dict, but only "scope" key/value is used for generating URI for authorization.
I need to pass "audience" for Atlassian OAuth2.0 https://developer.atlassian.com/cloud/jira/platform/oauth-2-authorization-code-grants-3lo-for-apps/
Workaround found after some tinkering by passing "audience"="api.atlassian.com" to oauth.atlassian.authorize_redirect.
Question: Is client_kwargs in oauth.register/AUTHLIB_OAUTH_CLIENTS intended only for certain keyword arguments? If so, would be great to share it in the documentation; otherwise it would be convenient to set it in config together with everything else.
This behavior was found in 0.12.1 and 0.13.dev0.
Thanks!
Because OAuth 1.0 and OAuth 2.0 are different, this client_kwargs are designed to pass extra parameters to either OAuth1Client/OAuth1Session or OAuth2Client/OAuth2Session.
For your case, there is a authorize_params. You can put audience in your authorize_params:
oauth.register(
....
authorize_params={'audience': '...'},
....
)

Getting Keycloak's public key

I realized there are many iterations of this questions. But I can't seem to understand the answer correctly.
We have secured our rabbitmq and rest endpoints with a oauth2 spring server similar to this post. But it doesn't have all of the features we need and want. So we would like to use Keycloak. I have been successful with securing the rest endpoint by just going to the new version of spring security 5.1 and specifing the security.oauth2.resource.jwk.key-set-uri and setting the necessary dependencies and configuration.
While trying to secure the RabbitMQ, I have been running into problems checking the bearer token from the message header because the keycloak jwks endpoint isn't returning the true RSA public key.
RabbitMQ uses the CustomMessageListenerContainer to get the token from the message header and uses the DefaultTokenServices to check the token.
From my understanding, the endpoint that responds with the key is https://keycloak-server/auth/realms/my-realm/protocol/openid-connect/certs
Doing a HttpGet on this endpoint, I get a response that looks like the following
{
"keys": [{
"kid": "7JUbcl_96GNk2zNh4MAORuEz3YBuprXilmTXjm0gmRE",
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"n": "nE9gEtzZvV_XisnAY8Hung399hwBM_eykZ9J57euboEsKra8JvDmE6w7SSrk-aTVjdNpjdzOyrFd4V7tFqev1vVJu8MJGIyQlbPv07MTsgYE5EPM4DxdQ7H6_f3vQjq0hznkFvC-hyCqUhxPTXM5NgvH86OekL2C170xnd50RLWw8FbrprP2oRjgBnXMAif1Dd8kwbKKgf5m3Ou0yTVGfsCRG1_LSj6gIEFglxNHvGz0RejoQql0rGMxcW3MzCvc-inF3FCafQTrG5eWHqp5xXEeMHz0JosQ7BcT8MVp9lHT_utiazhQ1uKZEb4uoYOyy6mDDkx-wExpZkOx76bk_Yu-N25ljY18hNllnV_8gVMkX46_vcc-eN3DRZGNJ-Asd_sZrjbXbAvBbKwVxZeOTaXiUdvl8O0G5xX2xPnS_WA_1U4b_V1t28WtnX4bqGlOejW2kkjLvNrpfQ5fnvLjkl9I2B16Mbh9nS0LJD0RR-AkBsv3rKEnMyEkW9UsfgYKLFKuH32x_CXi9uyvNDas_q8WS3QvYwAGEMRO_4uICDAqupCVb1Jcs9dvd1w-tUfj5MQOXB-srnQYf5DbFENTNM1PK390dIjdLJh4k2efCJ21I1kYw2Qr9lHI4X2peTinViaoOykykJiol6LMujUcfqaZ1qPKDy_UnpAwGg9NyFU",
"e": "AQAB"
}
]
}
From my understanding, the field with key "n" is supposed to be an RSA256 key. Adding it to a RSAVerifier eventually gets an error of "Caused by: org.springframework.security.jwt.codec.InvalidBase64CharacterException: Bad Base64 input character decimal 95 in array position 2."
However, if I login to keycloak admin page and go into the realm settings-> keys and click the public key, a popup shows the public key minus the "-----BEGIN PUBLIC KEY-----" and "-----END PUBLIC KEY-----" headers and footers. Hard coding this enables everything to work.
Is the key encoded?
I've tried doing a Base64Utils.decodeFromUrlSafeString and a Base64Utils.decodeFromString. The first returning something smaller and doesn't lool like the key and the later creating an Illegal argument exception Illegal base64 character 5f.
Update:
The n being returned is the modulous and e is the public exponent of the public key. But how does one get the actual key string?
The keys are also directly on https://keycloak-server/auth/realms/my-realm, in a format directly exploitable with your code:
{
"realm": "my-realm",
"public_key": "MIIBI...",
"token-service": "https://keycloak-server/auth/realms/my-realm/protocol/openid-connect",
"account-service": "https://keycloak-server/auth/realms/my-realm/account",
"tokens-not-before": 0
}
I'll found it also on:
open admin console
choose realm
choose Realm Settings
open tab 'Keys'
open tab 'active'
in the column 'Public keys' press 'Public Key
a popup with the public key appears.
There is toIntegerBytes before base64 encode, so it is not just base64 decode. Try:
BigInteger modulus = new BigInteger(1, Base64.decodeBase64("n-value-here"));
BigInteger exponent = new BigInteger(1, Base64.decodeBase64("e-value-here"));
JWKS endpoints are designed to have their keys changed over time (in a process called key rotation), so retrieving the public key as per the accepted answer is not a good idea. What you should opt for instead is to use a JWKS client. I use node-jwks-rsa, but the same creators also have a java implementation (jwks-rsa-java).

Invalid JWT signature after upgrading jhipster

I builded two microservices applications with jhipster (4.14.5), today i updated the both to 5.1.0. With jhister-registry last docker image (4.0.0)
All work as expected but the API Calls with jwt signature doesnt work anymore.
MyRequestInterceptor
#Override
public void apply(RequestTemplate requestTemplate) {
String secret= Jwts.builder()
.setSubject("admin")
.claim("auth", AuthoritiesConstants.ADMIN)
.signWith(SignatureAlgorithm.HS512, properties.getSecurity().getAuthentication().getJwt().getSecret())
.compact();
requestTemplate.header(JWTConfigurer.AUTHORIZATION_HEADER, "Bearer " + secret);
}
What is new in jhipster 5.1.0 with JWT? should i change the algorithm signature or how to fix this?
Yes we changed the way the secret key is handled, have a look at the source code here.
The difference is that now the JWT secret key is encoded in Base64 (that's why we create the encoder here).
This is originally my fault: the .signWith() method from JJWT accepts a String, so I was just giving the secret key (which is a String). But if you look at the documentation of the method, you'll notice that this String should be encoded in Base64. So now you have to use the encoded version of the secret key everywhere. It doesn't change anything in the end, in fact, but it's just to use the API correctly.