Reputation: 153
We had written small API using java-jwt. It works fine when i create a token and verify the token in Java code.
Then provided the public key to client and we started invoking their REST services using generated tokens. Client side using https://www.npmjs.com/package/jsonwebtoken to verify the tokens. They came back saying that the token and public key provided saying Invalid Signature in jwt.io debugger. They requested to make it work in jwt.io debugger first. I don't understand when it is working in Java code with the same public why is it saying that way in jwt.io. Am i missing something?
public void createPemFiles(String absoluteFilePath) throws Exception {
logger.log(Level.INFO, "Received request to create Key pair : " + absoluteFilePath);
PemWriter pemWriter = new PemWriter();
// create key pair
final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
generator.initialize(KEY_SIZE);
final KeyPair keyPair = generator.generateKeyPair();
// write private key
final RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
privateKeyPem = new File(absoluteFilePath);
pemWriter.writePrivateKey(privateKey, "RSA PRIVATE KEY", privateKeyPem.getAbsolutePath());
logger.log(Level.INFO, "Created private key : " + privateKeyPem.getAbsolutePath());
// write public key
publicKeyPem = new File(absoluteFilePath+".pub");
final RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
pemWriter.writePublicKey(publicKey, "RSA PUBLIC KEY", publicKeyPem.getAbsolutePath());
logger.log(Level.INFO, "Created public key : " + publicKeyPem.getAbsolutePath());
}
public String createJWTToken(String [] keyValues) {
final HashMap<String, Object> claims = new HashMap<String, Object>();
String [] nameValue;
for(String keyValue : keyValues) {
nameValue = keyValue.split("##");
claims.put(nameValue[0],nameValue[1]);
}
return JWTSIGNER.sign(claims, OPTIONS);
}
public String verifyJWTToken(String token) throws Exception{
logger.log(Level.DEBUG, "Received request for verify JWT token");
Map<String, Object> claims = JWTVERIFIER.verify(token);
String claimString = "";
String key = "";
String value = "";
for(Map.Entry<String, Object> entry : claims.entrySet()) {
key = entry.getKey();
value = (String) entry.getValue().toString();
claimString = claimString + key +":"+ value + "##";
}
claimString = replaceLast(claimString, "##", "");
logger.log(Level.DEBUG, "Successfully verified : "+claimString);
return claimString;
}
Input
iccid:4454788545885968585##
nonce:5e452610c9f9decd:-404fb717:157fd6fc54e:-7ffe##
timestamp:2016-10-25T16:16:36.036Z
Created Token Output
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpY2NpZCI6IjQ0NTQ3ODg1NDU4ODU5Njg1ODUiLCJub25jZSI6IjVlNDUyNjEwYzlmOWRlY2Q6LTQwNGZiNzE3OjE1N2ZkNmZjNTRlOi03ZmZlIiwidGltZXN0YW1wIjoiMjAxNi0xMC0yNVQxNjoxNjozNi4wMzZaIn0.PlWVn1jlkvjRpw34-fsjJGQVVd74sFdg7SS2UgA4HUx4vBMYMA4b-Zzg5VxyzYkhzSsQqjKn7UBw04fXIwsmaP9A7Pc3-MjHjbmYT3Yv52qvH4yNy6X_M0z41UHuuLaWVQN3eck5BKIoO2cy4ihb8OOISkzF1Cf-Udx1GB-bVY4C4JtIvGpMflVW4hS9ZpWzKz26qlva7Y9KMEmvW24tviNcy8aVNyC55MS_KS_Ab7YWQ-MERRiNTCDIqUG7YVSN2Ap_SsNMab687GknQh78ibAowUdpLbGRU4N5EHZyG2lg-u-oL594fRA2anr-JunSxtpkI8-tKzR9NG5dt4F79Q
Verify Token Output
iccid:4454788545885968585##
nonce:5e452610c9f9decd:-404fb717:157fd6fc54e:-7ffe##
timestamp:2016-10-25T16:16:36.036Z
Public Key
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx58WGD/wRFnwe64sl/9V
KuNOQChYUy8GfhQU66M2XSnx/UpjPCqhGYRmpUXT+rQAamUDsarGt8Kbw1DtlvLT
p2UTvSWiCJNQzi53CRa6iDbk213Ps7zuAFhuXB7s0ZqdOZbeJnXFFM/wMJbM6kdB
yAdCwj8/kCKCjSt3Q0CLdxaToTucRJuO7/V4wbJIDMfLt3LPlry/PsHQAx0RKXco
TO1JsSGWg99dHBEqpxLMBtZyhyd8++PrMrtQ4pPVAmXoJODKY2NZkiLl3h4Ai48z
FhBNHsWQDTJKA8skb2JQER9i1a1/ip/cgkR6FG6G65DbhrMElcL0mgdst49PF26p
pwIDAQAB
-----END RSA PUBLIC KEY-----
Upvotes: 2
Views: 5586
Reputation: 57728
It seems jwt.io expects a Public Key file (PKCS#8):
-----BEGIN PUBLIC KEY-----
BASE64 DATA
-----END PUBLIC KEY-----
instead of the RSA Public Key file (PKCS#1) you're passing:
-----BEGIN RSA PUBLIC KEY-----
BASE64 DATA
-----END RSA PUBLIC KEY-----
The interesting bit is that if you manually edit your file to replace the RSA PUBLIC KEY
marker with just PUBLIC KEY
marker then you'll get a verified signature. This is curious because the BASE64 data would be different according to the format, however, I didn't look into the details to find how if there's any culprit so don't ask me why, but that will work.
Upvotes: 5