Verify JsonWebToken signature

Thomas Buckley :

I'm receiving a JWT and would like to verify it's signature. It's not encrypted, is based64 encoded and is signed using HmacSha256. It is signed with a secret that I know.

I can't seem to find any example of how to verify the signature without using third part libraries listed on https://jwt.io/ i.e. java-jwt, jpose4j, etc....

Is it possible to do this?

What I have so far:

private boolean validateSignature( String header, String data, String signature, String secretKey ) throws Exception {
    Base64 base64 = new Base64( true );
    SecretKeySpec secret = new SecretKeySpec( secretKey.getBytes(), "HmacSHA256" );
    Mac mac = Mac.getInstance( "HmacSHA256" );
    mac.init( secret );

    byte[] hmacDataBytes = mac.doFinal( data.getBytes( StandardCharsets.UTF_8.name()) );
    String hmacData = new String( hmacDataBytes );

    return hmacData.equals( signature ); // Compare signatures here...
}

Based on @pedrofb and @jps answers, here is solution:

private boolean validToken( String authToken, String key ) throws Exception {
    String[] token = authToken.split( "\\." );
    String header = token[0];
    String payload = token[1];
    String originalSignature = token[2];

    SecretKeySpec secret = new SecretKeySpec( Base64.getDecoder().decode( key ), ALGORITM_HMACSHA256 );
    Mac mac = Mac.getInstance( ALGORITM_HMACSHA256 );
    mac.init( secret );

    StringBuilder headerAndPayload = new StringBuilder( header ).append( "." ).append( payload );

    byte[] signatureBytes = mac.doFinal( headerAndPayload.toString().getBytes( StandardCharsets.UTF_8.name() ) );
    String calculatedSignature = Base64.getUrlEncoder().withoutPadding().encodeToString( signatureBytes );

    return calculatedSignature.equals( originalSignature );
}
pedrofb :

A JWT have three parts encoded in base64url separated by dots

header.payload.signature

The signature is calculated over header.payload

Assuming that your method receives the elements in base64url, you need to calculate HMAC on header + "." + data, encode the result to base64url, and compare with the signature field

Something like this:

private boolean validateSignature( String header, String data, String signature, String secretKey ) throws Exception {

    SecretKeySpec secret = new SecretKeySpec( secretKey.getBytes(), "HmacSHA256" );
    Mac mac = Mac.getInstance( "HmacSHA256" );
    mac.init( secret );

    String body = header + "." + data;
    byte[] hmacDataBytes = mac.doFinal( body.getBytes( StandardCharsets.UTF_8.name()) );
    String hmacData = Base64.getUrlEncoder().encodeToString( hmacDataBytes );

    return hmacData.equals( signature ); // Compare signatures here...
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=91794&siteId=1