The signing key‘s size is 1024 bits which is not secure enough for the RS256 algorithm.

场景:

  最近在对接JWT中的RS256加密api,但是第三方给的私钥里面长度只有1024,由于JWT从0.10.0开始公私钥长度最低只能是2048,导致无法使用第三方的私钥进行加密。经过一番折腾,我改动了里面的源码,把jar包放到自己公司的私服。

报错信息:

"The signing key's size is 1024 bits which is not secure enough for the RS256 algorithm.  The JWT JWA Specification (RFC 7518, Section 3.3) states that keys used with RS256 MUST have a size >= 2048 bits.  Consider using the io.jsonwebtoken.security.Keys class's 'keyPairFor(SignatureAlgorithm.RS256)' method to create a key pair guaranteed to be secure enough for RS256.  See https://tools.ietf.org/html/rfc7518#section-3.3 for more information."

解决方案:

  修改后的jar,下载地址:https://download.csdn.net/download/qq_17555933/19920616
  修改io.jsonwebtoken.SignatureAlgorithm#assertValid这个方法,可以阅读以下改动点。

	/**
     * @since 0.10.0
     */
    private void assertValid(Key key, boolean signing, int keyLength) throws InvalidKeyException {
        // 如果用户有传key的长度,则使用用户的,否则使用默认 【修改的地方】
        keyLength = keyLength == 0 ? this.minKeyLength : keyLength;
        if (this == NONE) {

            String msg = "The 'NONE' signature algorithm does not support cryptographic keys.";
            throw new InvalidKeyException(msg);

        } else if (isHmac()) {

            if (!(key instanceof SecretKey)) {
                String msg = this.familyName + " " + keyType(signing) + " keys must be SecretKey instances.";
                throw new InvalidKeyException(msg);
            }
            SecretKey secretKey = (SecretKey) key;

            byte[] encoded = secretKey.getEncoded();
            if (encoded == null) {
                throw new InvalidKeyException("The " + keyType(signing) + " key's encoded bytes cannot be null.");
            }

            String alg = secretKey.getAlgorithm();
            if (alg == null) {
                throw new InvalidKeyException("The " + keyType(signing) + " key's algorithm cannot be null.");
            }

            // These next checks use equalsIgnoreCase per https://github.com/jwtk/jjwt/issues/381#issuecomment-412912272
            if (!HS256.jcaName.equalsIgnoreCase(alg) &&
                !HS384.jcaName.equalsIgnoreCase(alg) &&
                !HS512.jcaName.equalsIgnoreCase(alg)) {
                throw new InvalidKeyException("The " + keyType(signing) + " key's algorithm '" + alg +
                    "' does not equal a valid HmacSHA* algorithm name and cannot be used with " + name() + ".");
            }


            int size = encoded.length * 8; //size in bits
            if (size < keyLength) { // 【修改的地方】
                String msg = "The " + keyType(signing) + " key's size is " + size + " bits which " +
                    "is not secure enough for the " + name() + " algorithm.  The JWT " +
                    "JWA Specification (RFC 7518, Section 3.2) states that keys used with " + name() + " MUST have a " +
                    "size >= " + minKeyLength + " bits (the key size must be greater than or equal to the hash " +
                    "output size).  Consider using the " + Keys.class.getName() + " class's " +
                    "'secretKeyFor(SignatureAlgorithm." + name() + ")' method to create a key guaranteed to be " +
                    "secure enough for " + name() + ".  See " +
                    "https://tools.ietf.org/html/rfc7518#section-3.2 for more information.";
                throw new WeakKeyException(msg);
            }

        } else { //EC or RSA

            if (signing) {
                if (!(key instanceof PrivateKey)) {
                    String msg = familyName + " signing keys must be PrivateKey instances.";
                    throw new InvalidKeyException(msg);
                }
            }

            if (isEllipticCurve()) {

                if (!(key instanceof ECKey)) {
                    String msg = familyName + " " + keyType(signing) + " keys must be ECKey instances.";
                    throw new InvalidKeyException(msg);
                }

                ECKey ecKey = (ECKey) key;
                int size = ecKey.getParams().getOrder().bitLength();
                if (size < keyLength) { // 【修改的地方】
                    String msg = "The " + keyType(signing) + " key's size (ECParameterSpec order) is " + size +
                        " bits which is not secure enough for the " + name() + " algorithm.  The JWT " +
                        "JWA Specification (RFC 7518, Section 3.4) states that keys used with " +
                        name() + " MUST have a size >= " + keyLength +
                        " bits.  Consider using the " + Keys.class.getName() + " class's " +
                        "'keyPairFor(SignatureAlgorithm." + name() + ")' method to create a key pair guaranteed " +
                        "to be secure enough for " + name() + ".  See " +
                        "https://tools.ietf.org/html/rfc7518#section-3.4 for more information.";
                    throw new WeakKeyException(msg);
                }

            } else { //RSA

                if (!(key instanceof RSAKey)) {
                    String msg = familyName + " " + keyType(signing) + " keys must be RSAKey instances.";
                    throw new InvalidKeyException(msg);
                }

                RSAKey rsaKey = (RSAKey) key;
                int size = rsaKey.getModulus().bitLength();
                if (size < keyLength) { // 【修改的地方】

                    String section = name().startsWith("P") ? "3.5" : "3.3";

                    String msg = "The " + keyType(signing) + " key's size is " + size + " bits which is not secure " +
                        "enough for the " + name() + " algorithm.  The JWT JWA Specification (RFC 7518, Section " +
                        section + ") states that keys used with " + name() + " MUST have a size >= " +
                            keyLength + " bits.  Consider using the " + Keys.class.getName() + " class's " +
                        "'keyPairFor(SignatureAlgorithm." + name() + ")' method to create a key pair guaranteed " +
                        "to be secure enough for " + name() + ".  See " +
                        "https://tools.ietf.org/html/rfc7518#section-" + section + " for more information.";
                    throw new WeakKeyException(msg);
                }
            }
        }
    }

扩展JwtBuilder :

  io.jsonwebtoken.JwtBuilder#signWith(java.security.Key, io.jsonwebtoken.SignatureAlgorithm, int)


public interface JwtBuilder extends ClaimsMutator<JwtBuilder> {

    JwtBuilder signWith(Key key, SignatureAlgorithm alg) throws InvalidKeyException;
	// 扩展的方法
    JwtBuilder signWith(Key key, SignatureAlgorithm alg, int keyLength) throws InvalidKeyException;

}

使用方法:
/**
     * 生成token
     *
     * @param claims 用户信息
     * @return token
     */
    public String generateToken(Map<String, Object> claims, Map<String, Object> headers) {
        Date createdTime = new Date();
        Date expirationTime = this.getExpirationTime();

        SignatureAlgorithm signatureAlgorithm = StringUtils.equalsIgnoreCase((String) headers.get("alg"), ALG_HEADER_HS256) ? SignatureAlgorithm.HS256 : SignatureAlgorithm.RS256;
        int keyLength = StringUtils.equalsIgnoreCase((String) headers.get("alg"), ALG_HEADER_HS256) ? 0 : 1024;
        return Jwts.builder()
                .setHeaderParam("typ", TYP_HEADER)
                .setHeader(headers)
                .setClaims(claims) // 其它payload值
                .setIssuedAt(createdTime) // token签发生成时间,一般是当前时间,单位:秒
                .setExpiration(expirationTime) // token过期时间,单位:秒
                .setAudience(AUD_PAYLOAD) // 受众,固定值
                .setIssuer(sdkId) // 腾讯申请的SDK ID
                // 你也可以改用你喜欢的算法
                // 支持的算法详见:https://github.com/jwtk/jjwt#features
                .signWith(getSecretKey(headers), signatureAlgorithm, keyLength)
                .compact();
    }
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨润泽林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值