2

私は JWT を初めて使用し、スタンドアロン コードを通じて JWT API を理解することを学んでいます。以下のコードは、送信側の JWT トークンに署名して暗号化し、受信側で検証されます。

ライブラリ: JOSE 0.4.1

package com.one00bytes.jwt;

public class JWTSignEncryption {

public static void main(String[] args) throws Exception {

    /***************************SENDER'S END ***********************************/

    JwtClaims claims = new JwtClaims();
    claims.setAudience("Admins");
    claims.setIssuer("CA");
    claims.setSubject("users");
    claims.setClaim("email", "users@test.com");
    claims.setClaim("Country", "Antartica");
    System.out.println(claims.toJson());

    //SIGNING
    RsaJsonWebKey jsonSignKey = RsaJwkGenerator.generateJwk(2048);
    JsonWebSignature jws = new JsonWebSignature();
    jws.setKey(jsonSignKey.getPrivateKey());
    jws.setPayload(claims.toJson());
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA512);
    String signedJwt = jws.getCompactSerialization();
    System.out.println("Signed ::" + signedJwt);


    //ENCRYPTING
    RsaJsonWebKey keyEncrypt = RsaJwkGenerator.generateJwk(2048);
    KeyGenerator keyGen = KeyGenerator.getInstance("AES");
    keyGen.init(256);
    SecretKey contentEncryptKey = keyGen.generateKey();

    JsonWebEncryption jwe = new JsonWebEncryption();
    jwe.setKey(keyEncrypt.getPublicKey());
    jwe.setPayload(signedJwt);
    jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.RSA_OAEP_256);
    jwe.setContentEncryptionKey(contentEncryptKey.getEncoded());
    jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_256_GCM);
    SecureRandom iv = SecureRandom.getInstance("SHA1PRNG");
    jwe.setIv(iv.generateSeed(32));
    String encryptedJwt = jwe.getCompactSerialization();
    System.out.println("Encrypted ::" + encryptedJwt);


    /***************************RECEIVER'S END ***********************************/ 

    JwtConsumer consumer = new JwtConsumerBuilder()
                            .setExpectedAudience("Admins")
                            .setExpectedIssuer("CA")
                            .setRequireSubject()
                            .setDecryptionKey(keyEncrypt.getPrivateKey())
                            .setVerificationKey(jsonSignKey.getPublicKey())
                            .build();
    JwtClaims receivedClaims = consumer.processToClaims(encryptedJwt);
    System.out.println("SUCESS :: JWT Validation :: " + receivedClaims);

}

}

このプログラムの実行時に以下の例外を観察します。

Exception in thread "main" org.jose4j.jwt.consumer.InvalidJwtException: Unable to parse JWT Claim Set JSON: eyJhbGciOiJSUzUxMiJ9.eyJhdWQiOiJBZG1pbnMiLCJpc3MiOiJDQSIsInN1YiI6InVzZXJzIiwiaWF0IjoxNDM0NTM0MDgxLCJleHAiOjE0MzQ1MzQ2ODEsImp0aSI6IjJxUUpuMDVGY3RrLWF1VG1vVktuWXciLCJuYmYiOjE0MzQ1MzM5NjEsImVtYWlsIjoidXNlcnNAMTAwYnl0ZXMuY29tIiwiQ291bnRyeSI6IkFudGFydGljYSIsImhvYmJpZXMiOlsiQmxvZ2dpbmciLCJQbGF5aW5nIGNhcmRzIiwiR2FtZXMiXX0.soY_5Hbam569I-CnUW1F4GWdaqprh-XAOtAMOcb7zZSiRcIhXYUdJjEslrDbwphAP135SvmoXO4nVaVmo-d8oWREFYUeXEDzHbrqHNp7pp5pH6hGTJ5C4uE1UVzZ4bis3g_KEgZvEn31NnV4RcU_oRn2Q4inkrTlYKY-juEtCmpPQ0sSP4GiDbwVIfCj-kxZsKh_i9n28SSK890K3DIGiFWOUDwrnY4Yfr1UffsUS9ovyhtqrOcN4YsJR4XzGPaLehlR-qD7eOdAdmVb8RDtGKufNuCd7Q9OFfeKzBmGITHsvd6IPVYLLCfSCzO6PqQSIzkupl5D6HqoOqID8JZLxA
    at org.jose4j.jwt.JwtClaims.<init>(JwtClaims.java:50)
    at org.jose4j.jwt.JwtClaims.parse(JwtClaims.java:56)
    at org.jose4j.jwt.consumer.JwtConsumer.process(JwtConsumer.java:267)
    at org.jose4j.jwt.consumer.JwtConsumer.processToClaims(JwtConsumer.java:115)
    at com.one00bytes.jwt.JWTSignEncryption.main(JWTSignEncryption.java:76)
Caused by: org.jose4j.lang.JoseException: Parsing error: org.jose4j.json.internal.json_simple.parser.ParseException: Unexpected character (e) at position 0.
    at org.jose4j.json.JsonUtil.parseJson(JsonUtil.java:66)
    at org.jose4j.jwt.JwtClaims.<init>(JwtClaims.java:45)
    ... 4 more
Caused by: org.jose4j.json.internal.json_simple.parser.ParseException: Unexpected character (e) at position 0.
    at org.jose4j.json.internal.json_simple.parser.Yylex.yylex(Yylex.java:612)
    at org.jose4j.json.internal.json_simple.parser.JSONParser.nextToken(JSONParser.java:269)
    at org.jose4j.json.internal.json_simple.parser.JSONParser.parse(JSONParser.java:118)
    at org.jose4j.json.internal.json_simple.parser.JSONParser.parse(JSONParser.java:81)
    at org.jose4j.json.JsonUtil.parseJson(JsonUtil.java:62)
    ... 5 more

署名付き JWT

eyJhbGciOiJSUzUxMiJ9.eyJhdWQiOiJBZG1pbnMiLCJpc3MiOiJDQSIsInN1YiI6InVzZXJzIiwiZW1haWwiOiJ1c2Vyc0B0ZXN0LmNvbSIsIkNvdW50cnkiOiJBbnRhcnRpY2EifQ.5Xu7v2MosIQmtAOlqfM2PE9eJeT0iZzL9x6RIvqx_PAHKer0ylo-0wT9eON_qX1H_QZekTWMf8ok4fxdZNv2KP_AkNqSKLXYJ65TjPnfcX8-dooDJM9txfRWOFqJWx4yj4CTMPNR6rNhizkC9jUaLisPIjogc_a_61qTSnvHXFnuaYmkovN2Y3WfuXjhUZCH98hodRL_ATg1_SpO0bPb7_N1Z76yrcv0RYQan0Y5kICWYdhHlk8Dw6I2fLMVsl3HiYiRq4XBJE8AY_g742Uq5kTS62PKohg3IjfRa-g2rjgKo1XW2sRLVc7vnns2L3TqESo5vgvorTjKnCTQKuHpIg

暗号化された JWT

eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIn0.lZ2nqCeiPzsPmJShsrDD3uA55-06A649CMtwOyuY9nNzMtUGyzV-G8qc4w4ui1uWrtzypBs5Eyq4GfjnTtVHbcDVkS1HVc3tfxNAPY8dfjVrWNz59HyKt4bCjBdqqhBOdZezLtWB9aoWIwZoHLf4D8aUcVUtDsFELVcScmiQNtzHwvpDHZb4oxRfPl-OuOTkKA23C8lnnDMO1KUy8ZXHD4p0jQKAcaV877gYm8NbHDwOBEf-ItWJOGx2jV60apWd0hKqwfFR2QKD9wmGgXpbFZ08ro7X2fj8rTgKWhDgoBT_JVZdVFhVI4T4RLRDrCJqkyeciXhLm7W_xNhWBXAMrA.94SuB596ZLuUtw53wrofwN5jZXfT5f-ZarJhQc9Mj0M.0Ow5DXfilYX3ty49H4lNMNPljlWAFASc49zljhRSIIUSlmUHLZo0SAezn-n_FdxexAIYLk_FtRgnkMHDEyxJ1V1yHhqa1Jvdb36lTYyptqCJhMkOV1XGn58L4Z9QQmdrIZnn5iHxZ9-N1Jfjs0eoKiLBgR9O7ZEcs7QrWZVT6n_HrGrIloYQu_lFgmk5O7k47_15CVXaFqIohpHXETejoHEwjQj-iTToNRaHWNFAKvlpUBz4mUgk9RSIQCxK1GxxS8wxP44w5G4HdOIjFNwTsRDXeSZy0mU9zTNUCmDEUT9MFESfmVU1nPurdT-VoiPvVklbJZW8Sas0hWgqQkdQdP35nFY1sjCgfMB9iYUeEU-TCE219wkm1XXrLJwLEYZclL_4ckl4zExo2wb3Czwd8f5iO9fBQQWZ4mdwThK4VtZaPs1JEkxwGLI0SHA8Jr-e2PsDrkGEnxs74FsJ5MKluU2ZKvKcGXyQPaaTRa0ecJLD5-YYBuTtxOnU3gM_5aZm97pd_wiPk_h81r5aiwjSfRF3Ihxp37KNPfNOMJoA9xe2F51m1AvmjrOUgSM156LwmFyJFebVfarb9NPtJ_q1wU891sCu2Vmv520BR4QfIc-ayIwTVxLgZSN-BP7PhEJb_x8.XhZpINBxRdFFEgwPTcAgJg

同じコードが署名と暗号化のために別々に実行されますが、両方を含めると実行されませんでした。

私が間違っていることを理解するのを手伝ってください。

前もって感謝します

4

2 に答える 2

2

ネストされた JWT (つまり、あなたがドンしている JWE[JWS[JSON Claims]]) の場合、JWE の「cty」(コンテンツ タイプ) ヘッダーは、「JWT」の値を持ち、ペイロード自体が JWT です。JWT 仕様の「cty」の定義であるRFC 7519では、それについてもう少し詳しく説明されています。消費者/受信者が物事を処理する方法を知るのに役立ちます.

表示されている例外は、ライブラリが JWE のペイロードである JWS コンパクト シリアル化を JSON として解析しようとした結果です。

仕様によると、JWE の cty ヘッダーを「JWT」に設定する必要があります。これは、JWE ペイロード自体が JWT であることを示します。これは、v0.4.2 以降でjwe.setHeader(HeaderParameterNames.CONTENT_TYPE, "JWT");実行できます。jwe.setContentTypeHeaderValue("JWT")

JwtConsumerまた、cty ヘッダーが存在せず、ペイロードが JSON として解析されないが、JOSE オブジェクトに解析できる場合は、処理をもう少し自由に行い、最善を尽くすように に指示することもできます。.setEnableLiberalContentTypeHandling()これは、で実行できますJwtConsumerBuilder

さらにいくつかの観察結果を示します。

JWE でコンテンツ暗号化キーまたは IV を設定する必要はありません。ライブラリは安全なランダムを使用して、適切な長さでそれらを生成します。したがって、以下で十分なはずです。

JsonWebEncryption jwe = new JsonWebEncryption();
jwe.setHeader(HeaderParameterNames.CONTENT_TYPE, "JWT");
jwe.setKey(keyEncrypt.getPublicKey());
jwe.setPayload(signedJwt);
jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.RSA_OAEP_256);
jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_256_GCM);
String encryptedJwt = jwe.getCompactSerialization();
System.out.println("Encrypted ::" + encryptedJwt);

また、RSA_OAEP_256 と AES_256_GCM の使用から、Bouncy Castle を使用していると推測しています。Bouncy Castle セキュリティ プロバイダでライブラリを使用したときに特定されたセキュリティの脆弱性のため、jose4j 0.4.4 にアップグレードすることを強くお勧めします。詳細については、v 0.4.4 のリリース ノートを参照してください https://bitbucket.org/b_c/jose4j/wiki/Release%20Notes#!jose4j-044-july-24-2015

于 2015-10-21T18:58:50.420 に答える
0

JWT は、そのペイロードまたはMessageとして、 Claims Setの UTF-8 表現を持っています。RFC 7519から:

Message を JWT Claims Set の UTF-8 表現のオクテットとします。

これは、署名付き JWT (JWS オブジェクト) と暗号化 JWT (JWE を使用) の両方に当てはまります。

JWT が JWE の場合、メッセージを JWE の平文として使用して JWE を作成します。JWE を作成するために JWE で指定されているすべての手順に従う必要があります。

したがって、暗号化された JWT を検証するために、ペイロードはクレーム セットとして解釈されます。

それ以外の場合、JWT が JWE の場合は、JWE で指定されている手順に従って JWE を検証します。Message を結果の平文にします。

プログラムで犯した間違いは、署名付き JWT のシリアル化を JWE のペイロードとして使用し、結果のオブジェクトを暗号化されたJWE として処理しようとしたことです。したがって、ライブラリは、シリアル化された署名付き JWT ( JWS Flattened Serialization ) をシリアル化された JWT Claims Set (JSON オブジェクト) として解釈しようとします。これは、あなたが得ている例外を説明しています:

Caused by: org.jose4j.lang.JoseException: Parsing error:
    org.jose4j.json.internal.json_simple.parser.ParseException:
    Unexpected character (e) at position 0.

暗号化および認証された JWT を作成しようとしているようです。すべての JWE アルゴリズムは認証された暗号化アルゴリズムであるため、これを実現するために JWS で何もする必要はありません。暗号化された JWT で十分です。

于 2015-06-17T12:40:32.313 に答える