验证 JsonWebToken 签名

Tho*_*ley 6 java digital-signature jwt

我收到了 JWT,想验证它的签名。它未加密,基于 64 编码并使用 HmacSha256 签名。它是用我知道的秘密签署的。

我似乎找不到任何如何在不使用https://jwt.io/上列出的第三方库(即 java-jwt、jpose4j 等)来验证签名的示例。

是否有可能做到这一点?

到目前为止我所拥有的:

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...
}
Run Code Online (Sandbox Code Playgroud)

根据 @pedrofb 和 @jps 的答案,以下是解决方案:

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 );
}
Run Code Online (Sandbox Code Playgroud)

ped*_*ofb 6

JWT 具有以点分隔的 base64url 编码的三个部分

header.payload.signature
Run Code Online (Sandbox Code Playgroud)

签名计算完毕header.payload

假设你的方法接收到了base64url中的元素,需要计算HMAC header + "." + data,将结果编码为base64url,并与签名字段进行比较

像这样的东西:

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...
}
Run Code Online (Sandbox Code Playgroud)