为什么带有ECDH加密算法的JsonWebSignature每次都给出不同的签名?

时间:2019-06-12 15:05:19

标签: java push-notification jwt progressive-web-apps ecdh

我想向Google FCM发送请求,以向浏览器发送推送请求以显示通知。

主要目标是使用带有SHA256的ECDH算法对带有私钥的JWT有效负载进行签名,以获得JWT令牌。

我尝试使用ECDH算法对令牌进行签名,但是每次获得相同有效负载的Deffirent签名时。

这是我的代码的简短内容

预先感谢

    JwtClaims claims = new JwtClaims();
    claims.setAudience("https://fcm.googleapis.com");
    claims.setExpirationTime(NumericDate.fromSeconds(1560388318));
    claims.setSubject("mailto:admin@example.com");

    JsonWebSignature jws = new JsonWebSignature();
    jws.setHeader("typ", "JWT");
    jws.setHeader("alg", "ES256");
    jws.setPayload(claims.toJson());
    try {
        Key key = loadPrivateKey("-kmhPYsH6JKiFjG8C1cS9vx4bCz594yofAwTLa_SOEE");
        jws.setKey(key);
    } catch (NoSuchProviderException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (InvalidKeySpecException e) {
        e.printStackTrace();
    }
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.ECDSA_USING_P256_CURVE_AND_SHA256);

    try {
        System.out.println(jws.getCompactSerialization());
    } catch (JoseException e) {
        e.printStackTrace();
    }

 public static PrivateKey loadPrivateKey(String encodedPrivateKey) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException {
    byte[] decodedPrivateKey = base64Decode(encodedPrivateKey);

    // prime256v1 is NIST P-256
    ECParameterSpec params = ECNamedCurveTable.getParameterSpec("prime256v1");
    ECPrivateKeySpec prvkey = new ECPrivateKeySpec(new BigInteger(decodedPrivateKey), params);
    KeyFactory kf = KeyFactory.getInstance("ECDH");

    return kf.generatePrivate(prvkey);
   }

public static byte[] base64Decode(String base64Encoded) {
    if (base64Encoded.contains("+") || base64Encoded.contains("/")) {
        return BaseEncoding.base64().decode(base64Encoded);
    } else {
        return BaseEncoding.base64Url().decode(base64Encoded);
    }
}

第一次尝试:

eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL2ZjbS5nb29nbGVhcGlzLmNvbSIsImV4cCI6MTU2MDM4ODMxOCwic3ViIjoibWFpbHRvOmFkbWluQGV4YW1wbGUuY29tIn0.MpGc0pKvXtDb94Ruq5lkQjqCqxFMkVAwzVervnH90RLArvGHUAZ_kO4VcecLhGfIXTCitBKb5M-EKsYR35IT0A

第二次获得:

eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL2ZjbS5nb29nbGVhcGlzLmNvbSIsImV4cCI6MTU2MDM4ODMxOCwic3ViIjoibWFpbHRvOmFkbWluQGV4YW1wbGUuY29tIn0.qEW0ci1BnXXUUjkfsQkdReznAyIDEPtygxV3B58Sl8v_gTlh8O4HHGzRtxsqdvL5UIJV06e_UJHYPOUDK_MF9A

2 个答案:

答案 0 :(得分:1)

ECDH加密算法使用不同的安全随机数来为每个签名生成计算签名。 您可以指定此“安全随机”以每次都获得相同的签名。 对于您的情况:

ProviderContext context = new ProviderContext();
context.setSecureRandom(new SecureRandom(SecureRandom.getSeed(0)));
jws.setProviderContext(context);

答案 1 :(得分:0)

根据设计,数字密码签名应仅满足以下条件

  

应通过相应的公钥进行验证。

如果您查看Signature Generation algorithm步骤3,它会显示GetHashCode,其中Select a cryptographically secure random integer k from [1,n-1].是曲线的顺序(您现在可以忽略此事实)。

然后计算n,其中(x1, y1) = k * G是椭圆曲线的生成点。然后,G。这是签名的一部分。因此,通过更改r = x1 mod nk也将更改,因此签名也会更改。

因此,对于每个签名生成,算法都会选择一个不同的参数,然后使用is计算签名。 例如:

r

每次签名都不同。

参考:

相关问题