【问题标题】:Verify Signature using JWT ( java-jwt)使用 JWT (java-jwt) 验证签名
【发布时间】:2018-09-16 12:26:34
【问题描述】:

我必须使用 java-jwt 库验证签名,我有令牌和公钥,公钥从 ssh-rsa AA 开始...... 而且我必须使用 RSA256 算法,当我检查 github 时,我发现如下

Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);
JWTVerifier verifier = JWT.require(algorithm)
    .withIssuer("auth0")
    .build(); //Reusable verifier instance
DecodedJWT jwt = verifier.verify(token);

但是我的公钥是字符串形式的,我没有私钥。请建议我如何验证签名。

【问题讨论】:

    标签: java jwt


    【解决方案1】:

    当使用非对称密钥加密时,我们需要私钥来创建签名和公钥来验证。 来回答你的问题

    1.私人不存在

    没关系,你不需要私钥来验证签名。关于您正在使用的库,它的变量 args 。这意味着您可以根据签名/验证仅通过一个。下面是只使用公钥的java方法。

        public boolean verifyToken(String token,RSAPublicKey publicKey){
        try {
            Algorithm algorithm = Algorithm.RSA256(publicKey, null);
            JWTVerifier verifier = JWT.require(algorithm)
                    //more validations if needed
                    .build();
            verifier.verify(token);
            return true;
        } catch (Exception e){
            System.out.println("Exception in verifying "+e.toString());
            return false;
        }
    }
    

    2。公钥是字符串格式,不是 java PublicKey 格式。

    您需要一种机制将您的公钥字符串文件转换为 Java PublicKey 格式。以下是我可以建议的一种方法。

        public static RSAPublicKey getPublicKeyFromString(String key) throws 
        IOException, GeneralSecurityException {
    
        String publicKeyPEM = key;
    
        /**replace headers and footers of cert, if RSA PUBLIC KEY in your case, change accordingly*/
        publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----\n", "");
        publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
    
        byte[] encoded = Base64.decodeBase64(publicKeyPEM);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(new X509EncodedKeySpec(encoded));
    
        return pubKey;
        }
    

    【讨论】:

      【解决方案2】:

      这似乎是https://github.com/auth0/java-jwt 的缺陷/限制,您似乎需要公钥和私钥来验证签名。使用 RSA256 算法验证 JWT 时不需要私钥。

      这个用于处理 JWT 的备用 java 库:https://github.com/jwtk/jjwt#reading-a-jws 没有相同的限制,因此我建议改用它。

      Jwts.parser()    
        .setSigningKey(publicKey) // <---- publicKey, not privateKey  
        .parseClaimsJws(jwsString);
      

      【讨论】:

      • 来自java-jwt docs:“当使用 RSA 或 ECDSA 算法并且您只需要签署 JWT 时,您可以避免通过传递空值来指定公钥。在以下情况下使用私钥也可以这样做您只需要验证 JWT。”
      【解决方案3】:

      如果您是令牌生成器,您必须拥有用于生成令牌的私钥。

      除非您拥有私钥,否则您无法验证令牌。

      如果您在客户端使用 Token,则无需验证。

      如果您只想在编写功能之前验证令牌,您可以转到:

      https://jwt.io/

      如果你经历这个会很有帮助:

      https://github.com/jwtk/jjwt

      如果有人在服务器上请求资源,你可以这样做:

      try {
      
          Jwts.parser().setSigningKey(key).parseClaimsJws(compactJws);
      
          //OK, we can trust this JWT
      
      } catch (SignatureException e) {
      
          //don't trust the JWT!
      }
      

      我希望这会有所帮助...

      【讨论】:

      • 这个回答是正确的。如果您需要验证 JWT 客户端,则说明您使用了错误的技术。 JWT 包含一个 backend 状态,但请求客户端保持该状态。这使得后端无状态,并且任何虚拟后端服务器都可以处理任何请求,因为后端状态包含在每个请求中(在 JWT 中)。如果您需要来自后端的数据,并且需要验证并确保特定后端提供了该数据,那么 https 就足够了。
      • @AndreasLundgren 谢谢。
      • 基于公钥/私钥的签名算法的全部意义不是任何人都应该能够在没有私钥的情况下验证签名吗?!不明白为什么没有私钥就无法验证令牌。这可以在 node.js lib github.com/auth0/… 中完成,这似乎是 OP 中引用的特定 java lib 实现 github.com/auth0/java-jwt 的缺陷/限制。
      猜你喜欢
      • 2016-08-28
      • 2018-11-25
      • 2019-11-14
      • 2021-11-16
      • 2016-12-27
      • 2020-05-11
      • 2020-11-26
      • 2017-12-30
      相关资源
      最近更新 更多