Reputation: 849
I need to convert a RSA PublicKey into a valid JWK. Especially the values "n" an "e" of the JWK are the ones I'm struggling with. The encoding does not seem to be correct, when looking at example JWK's at https://www.rfc-editor.org/rfc/rfc7517#page-25
Currently my code looks basically like this:
private Map<String, Object> generateJWK(PublicKey publicKey){
RSAPublicKey rsa = (RSAPublicKey) publicKey;
Map<String, Object> values = new HashMap<>();
values.put("kty", rsa.getAlgorithm()); // getAlgorithm() returns kty not algorithm
values.put("kid", "someuniqueid");
values.put("n", Base64.encode(rsa.getModulus().toString()));
values.put("e", Base64.encode(rsa.getPublicExponent().toString()));
values.put("alg", "RS256");
values.put("use", "sig");
return values;
}
The output however does not seem to be correctly encoded or something, e
for example looks like this: NjU1Mzc=
n
does not include special characters like -
, _
and +
. :
jMzk1MNT0xTk2NED1xzzgNyQ00IykADzMAM0c0wz0M0MONj2z5TgNzI3yAM0OONYzzMjzwNzDxgAzxDxzMMAjTwNNDYMINMgNQDOEAkIM2jMQzkjUTDUYONNg1A00Tw1Nx4YEzAzjUT1MTNMjDjMM1MNNAjyTMIzxNADDINQANwT5yTDEMjEzNz2z2gOgjDDDNyNDjTzz43ETOYMI35gDjE00MYYM2DzDjDgww53Mwz0ME1NMgOM3MIzYTzMwzOMIQU5MjOzUjMNQNNg50U5NIDNzw2DMMOggNcQQM21TI5NMzDTN5Mj123O33MNNMkyNTNONxMM5wMMc04jTgAUE3MM1zMg4NNMT4MNDMM5yTO2j4jNDEMy1yNANNAzOIEUDzNwzExwTIkNjUjkN54Uz0DT5x0zM51k2MxYkx0zMNzxMkDUDTTQN3gAYODATQDDwMDMjMMcONjxMNTYMT5kgxNkMjNMQU0jzMEwIIMzTzUD4MgYDkDNzcAzN0TN4yNTz11DMxDUjDM2MyDMy4DEINMwT22QxjNNEzNDATy1OM1NNDxYgz5TxDkj3gQ32kIwNNkDO3xczDAENcTMNO0MOjTDwE3g11wNUcgNTwQk30kjjNNzTz4jTj4OOjQNYzMzcMjTQMkyzNNNUQOTOMMkMMMNzwNxDOEkg4xADIT4DNxMz2TENT4yN4z2I2zjyMU3DTOEQN4MIQjNDMU5Y11QkccwMNI0kNzyNjMMN4NMTTNMzMwxMjjDzgAANO1zwjYIEUjM1ADgDNjxTITMNNkIYxzyzzEEDMzDzNjzM4NjNNjc3ITTD0T5jzN=
Am I assuming right that both values n and e are not properly encoded? How should I convert the PublicKey to JWK? (Can not use 3rd party libraries)
Upvotes: 12
Views: 16490
Reputation: 1
code below works fine, use Apache Base64, search by phrases
RFC 4648 vs RFC 2045 codec difference
and
java biginteger to byte array leading zero
private static byte[] toByteArray(BigInteger bigInteger)
{
byte[] bytes = bigInteger.toByteArray();
byte[] result;
if ((bigInteger.bitLength() % 8 == 0) && (bytes[0] == 0) && bytes.length > 1)
{
result = new byte[bytes.length - 1];
System.arraycopy(bytes, 1, result, 0, result.length);
}
else {result = bytes;}
return result;
}
...
import org.apache.commons.codec.binary.Base64;
...
jwk.put("n", Base64.encodeBase64URLSafeString(toByteArray(publicKey.getModulus()) ) );
jwk.put("e", Base64.encodeBase64URLSafeString(publicKey.getPublicExponent().toByteArray()) );
Upvotes: 0
Reputation: 39261
JWK uses base64url encoding which is slighly different to base64. Additionally, do not use toString()
method on BigInteger
values. Get directly the data as byte array
Change
Base64.encode(rsa.getModulus().toString())
Base64.encode(rsa.getPublicExponent().toString())
To
Base64.getUrlEncoder().encodeToString(rsa.getModulus().toByteArray())
Base64.getUrlEncoder().encodeToString(rsa.getPublicExponent().toByteArray())
Upvotes: 18