【问题标题】:How to encode jwtToken from es256 pem files java如何从 es256 pem 文件 java 中编码 jwtToken
【发布时间】:2019-06-10 13:29:53
【问题描述】:

我有在 ES256 算法中创建的私钥和公钥 .pem 文件。我想用私钥签署 JWT 令牌,以后可以用公钥检查。

jwt.io我发现有多个库支持ES256:jose4j、nimbus-jose-jwt、jjwt、fusionauth-jwt、vertx-auth-jwt。不幸的是,我找不到任何从 pem 文件加载密钥并创建 JWT 令牌的示例。

示例 N1:

我将 pem 文件导入到 .keystore 中

openssl pkcs12 -export -in ES256-public-key.pem -inkey ES256-private-key.pem -out ~/keystore.p12 -name selfsigned -nocerts

我用以下代码尝试了 jose4j:

KeyStore store = KeyStore.getInstance("PKCS12");

store.load(new FileInputStream("/home/andrew/keystore.p12"), "test".toCharArray());
Key key = store.getKey("selfsigned", "test".toCharArray());

JsonWebEncryption jwe = new JsonWebEncryption();
jwe.setPayload("Hello World!");
jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW);
jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256);
jwe.setKey(key);
String serializedJwe = jwe.getCompactSerialization();
System.out.println("Serialized Encrypted JWE: " + serializedJwe);
jwe = new JsonWebEncryption();
jwe.setAlgorithmConstraints(new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST,
    KeyManagementAlgorithmIdentifiers.ECDH_ES_A256KW));
jwe.setContentEncryptionAlgorithmConstraints(new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST,
    ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256));
jwe.setKey(key);
jwe.setCompactSerialization(serializedJwe);
System.out.println("Payload: " + jwe.getPayload());

抛出异常:

Exception in thread "main" org.jose4j.lang.InvalidKeyException: Invalid key java.lang.ClassCastException: Cannot cast sun.security.ec.ECPrivateKeyImpl to java.security.interfaces.ECPublicKey
    at org.jose4j.jwx.KeyValidationSupport.castKey(KeyValidationSupport.java:64)
    at org.jose4j.jwe.EcdhKeyAgreementAlgorithm.validateEncryptionKey(EcdhKeyAgreementAlgorithm.java:188)
    at org.jose4j.jwe.EcdhKeyAgreementWithAesKeyWrapAlgorithm.validateEncryptionKey(EcdhKeyAgreementWithAesKeyWrapAlgorithm.java:73)
    at org.jose4j.jwe.JsonWebEncryption.getCompactSerialization(JsonWebEncryption.java:264)
    at com.icthh.A.main(A.java:30)

我什至不明白为什么它需要公钥来创建 JWT 令牌。

示例 N2

    private static void nimbus() throws IOException, JOSEException {
        JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.ES256),
            new Payload("Hello, world!"));

// We need a 256-bit key for HS256 which must be pre-shared

        byte[] sharedKey = IOUtils.toByteArray(new FileInputStream("/home/andrew/ES256-private-key.pem"));
// Apply the HMAC to the JWS object
        jwsObject.sign(new MACSigner(sharedKey));

// Output in URL-safe format
        System.out.println(jwsObject.serialize());
    }

这会抛出:

Exception in thread "main" com.nimbusds.jose.JOSEException: The "ES256" algorithm is not supported by the JWS signer
    at com.nimbusds.jose.JWSObject.ensureJWSSignerSupport(JWSObject.java:269)
    at com.nimbusds.jose.JWSObject.sign(JWSObject.java:318)
    at com.icthh.A.main(A.java:57)

示例 N3

jjwt - 这个库似乎对 android 很好我什至不确定它是否能够签署令牌,因为 android 是一个客户端。

我想找到的是如何从 ES256 私钥和公钥创建签名 JWT 令牌的完整示例。

【问题讨论】:

    标签: java jwt


    【解决方案1】:

    我可以使用 auth0-java-jwt 解决这个问题

    import com.auth0.jwt.JWT;
    import com.auth0.jwt.algorithms.Algorithm;
    import lombok.SneakyThrows;
    
    import java.io.FileInputStream;
    import java.security.KeyStore;
    import java.security.interfaces.ECPrivateKey;
    import java.util.Date;
    
    
        KeyStore store = KeyStore.getInstance("PKCS12");
        //
        store.load(new FileInputStream("/home/andrew/keystore.p12"), "test".toCharArray());
        ECPrivateKey pk = (ECPrivateKey) store.getKey("selfsigned", "test".toCharArray());
    
        Algorithm algorithmHS = Algorithm.ECDSA256(null, pk);
        String token = JWT.create()
            .withSubject("")
            .withExpiresAt(new Date())
            .withNotBefore(new Date())
            .withIssuer("issuer")
            .withClaim("roles", "b")
            .withClaim("keys", "b")
            .sign(algorithmHS);
    

    【讨论】:

    • 我对你真正想要的东西有点困惑。在您的问题中创建一个加密令牌(JWE)并在您的答案中创建一个签名令牌(JWS)
    • 对不起,我对这一切的实际运作方式了解甚少。我的意思大概是签字。我需要与spring-security-jwt:JwtHelper.encode 方法相同的方法。它说编码,这是我最初的问题。
    • 这就是为什么我在原始问题中写了encode 并且有人为加密进行了编辑;)
    • 是的,我编辑了它,因为尽管谈到了编码,但您的代码包含 JsonWebEncryption jwe = new JsonWebEncryption();,这足以让您有理由认为您需要加密令牌 (JWE)
    猜你喜欢
    • 1970-01-01
    • 2012-11-13
    • 2016-11-02
    • 2022-10-06
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    相关资源
    最近更新 更多