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

Posted 胡金水

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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();
    

以上是关于The signing key‘s size is 1024 bits which is not secure enough for the RS256 algorithm.的主要内容,如果未能解决你的问题,请参考以下文章

The server's host key is not cached in the registry. You have no guarantee that the server……(示例

The identity used to sign the executable is no longer valid.

the identity used to sign the executable is no longer valid.解决方法

打包的时候出现 Embedded binary is not signed with the same certificate as the parent app. Verify the embedd

Sourcetree git 出现 The server‘s host key is not cached in the registry问题的解决办法

Xcode真机调试失败:The identity used to sign the executable is no longer valid