【问题标题】:Validate JWT signature with ECDSA public key - Error decoding signature bytes使用 ECDSA 公钥验证 JWT 签名 - 解码签名字节时出错
【发布时间】:2019-09-06 16:44:29
【问题描述】:

我需要一些帮助来使用 ECDSA 公钥验证 jwt 签名。我正在使用充气城堡从 .pem 文件中读取密钥并使用 jjwt 进行验证。我在验证签名时遇到错误。

Security.addProvider(new BouncyCastleProvider());
String jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJtc2kiOiI5NzE1NTA5ODc2NTUiLCJmZWEiOiJzaWdudXAtZGF0YSIsImlzcyI6IkNEUCIsImV4cCI6MTU1NDU2NjMzNiwiaWF0IjoxNTU0MzkzNTM2LCJzaWQiOiIwNDI0MDMwMDg5NzI4MTg3QG5haS5lcGMubW5jMTMwLm1jYzMxMC4zZ3BwbmV0d29yay5vcmcifQ.RwxoGmFd1_dQPeGN-0gnWIW79xXvGHoyJKBbCKajgO75UooceS6tskxwqViEuP1gZD66UE8Bd2L0FaeI2aS_IA";
PemReader pemReader = new PemReader(new FileReader("/publickey.pem"));
X509EncodedKeySpec spec = new X509EncodedKeySpec(pemReader.readPemObject().getContent());
KeyFactory kf = KeyFactory.getInstance("ECDSA","BC");
PublicKey publicKey = kf.generatePublic(spec);
Jws<Claims> claims = Jwts.parser().setSigningKey(publicKey).parseClaimsJws(jwt);

我收到签名异常:无法使用配置的 ECPublicKey 验证椭圆曲线签名。错误解码签名字节。

【问题讨论】:

  • jwt 字符串是否没有使用与公钥匹配的私钥加密?将私钥与原始 jwt 令牌一起发布,以便人们可以验证您在做什么。也许还有用于加密的客户端代码/命令。
  • 我只有公钥。原来的 jwt 是什么意思?
  • 如果我理解这里发生了什么,您的 jwt 字符串是由客户端通过私钥签名的。通过与私钥匹配的公钥验证签名将揭示两件事:1)原始 jwt 有效,2)验证私钥的所有者发送了请求。该错误表示以下两种情况之一:未通过私钥正确创建签名,或者您拥有的公钥与使用的私钥不匹配。我认为这里没有足够的信息来帮助你(也许我错了!)
  • 甚至有可能客户端没有使用相同的椭圆曲线算法进行签名...

标签: java jwt bouncycastle ecdsa


【解决方案1】:

无需提及任何算法,这同样适用。

public boolean isTokenValid(String token) {
    try {
        String certificate = "GET_YOUR_PUBLIC_CERTIFICATE_HERE"; //Either from REST call or reading from a cert file.
        getPublicKeyAndParseToken(token, certificate);
        return true;
    } catch (IOException e) {
        log.error("", e);
    } catch (Exception e) {
        log.error("", e);
        log.error("JWT Not-Verified");
    }
    return false;
}

private void getPublicKeyAndParseToken(String token, String certificate) throws IOException, CertificateException {
    log.debug("Certificate:: " + certificate); //Only for debugging purpose
    InputStream is = new ByteArrayInputStream(certificate.getBytes(StandardCharsets.UTF_8));
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    Certificate cert = cf.generateCertificate(is);
    PublicKey publicKey = cert.getPublicKey();

    Jws parsedClaimsJws = Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    log.debug("Header:: " + parsedClaimsJws.getHeader()); //Only for debugging purpose
    log.debug("Body:: " + parsedClaimsJws.getBody()); //Only for debugging purpose
}

不要忘记使用 jjwt 库的 '0.9.x' 版本。我的 build.gradle 中有以下依赖项:

compile('io.jsonwebtoken:jjwt:0.9.1')

【讨论】:

    【解决方案2】:

    发现问题,我使用的是旧的 jjwt lib (0.6)。使用相同的代码更改为 0.9,它可以按预期工作。

    谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-14
      • 1970-01-01
      • 2017-11-22
      • 2020-03-23
      • 1970-01-01
      • 2020-06-11
      • 1970-01-01
      • 2022-01-07
      相关资源
      最近更新 更多