diff --git a/analysis_options.yaml b/analysis_options.yaml index 97d4b47..a686c1b 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,14 +1,14 @@ +# Defines a default set of lint rules enforced for +# projects at Google. For details and rationale, +# see https://github.com/dart-lang/pedantic#enabled-lints. +include: package:pedantic/analysis_options.yaml + +# For lint rules and documentation, see http://dart-lang.github.io/linter/lints. +# Uncomment to specify additional rules. +# linter: +# rules: +# - camel_case_types + analyzer: # exclude: # - path/to/excluded/files/** - -# Lint rules and documentation, see http://dart-lang.github.io/linter/lints -linter: - rules: - - cancel_subscriptions - - hash_and_equals - - iterable_contains_unrelated_type - - list_remove_unrelated_type - - test_types_in_equals - - unrelated_type_equality_checks - - valid_regexps diff --git a/example/jose_example.dart b/example/jose_example.dart index a0db254..6097fc9 100644 --- a/example/jose_example.dart +++ b/example/jose_example.dart @@ -1,6 +1,6 @@ import 'package:jose/jose.dart'; -main() async { +void main() async { await example1(); await example2(); await example3(); @@ -10,12 +10,12 @@ main() async { } // decode and verify a JWS -example1() async { - var encoded = "eyJhbGciOiJFUzUxMiJ9." - "UGF5bG9hZA." - "AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZq" - "wqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8Kp" - "EHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn"; +void example1() async { + var encoded = 'eyJhbGciOiJFUzUxMiJ9.' + 'UGF5bG9hZA.' + 'AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZq' + 'wqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8Kp' + 'EHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn'; // create a JsonWebSignature from the encoded string var jws = JsonWebSignature.fromCompactSerialization(encoded); @@ -23,234 +23,234 @@ example1() async { // extract the payload var payload = jws.unverifiedPayload; - print("content of jws: ${payload.stringContent}"); - print("protected parameters: ${payload.protectedHeader.toJson()}"); + print('content of jws: ${payload.stringContent}'); + print('protected parameters: ${payload.protectedHeader.toJson()}'); // create a JsonWebKey for verifying the signature - var jwk = new JsonWebKey.fromJson({ - "kty": "EC", - "crv": "P-521", - "x": "AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_" - "NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk", - "y": "ADSmRA43Z1DSNx_RvcLI87cdL07l6jQyyBXMoxVg_l2Th-x3S1WDhjDl" - "y79ajL4Kkd0AZMaZmh9ubmf63e3kyMj2", - "d": "AY5pb7A0UFiB3RELSD64fTLOSV_jazdF7fLYyuTw8lOfRhWg6Y6rUrPA" - "xerEzgdRhajnu0ferB0d53vM9mE15j2C" + var jwk = JsonWebKey.fromJson({ + 'kty': 'EC', + 'crv': 'P-521', + 'x': 'AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_' + 'NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk', + 'y': 'ADSmRA43Z1DSNx_RvcLI87cdL07l6jQyyBXMoxVg_l2Th-x3S1WDhjDl' + 'y79ajL4Kkd0AZMaZmh9ubmf63e3kyMj2', + 'd': 'AY5pb7A0UFiB3RELSD64fTLOSV_jazdF7fLYyuTw8lOfRhWg6Y6rUrPA' + 'xerEzgdRhajnu0ferB0d53vM9mE15j2C' }); - var keyStore = new JsonWebKeyStore()..addKey(jwk); + var keyStore = JsonWebKeyStore()..addKey(jwk); // verify the signature var verified = await jws.verify(keyStore); - print("signature verified: $verified"); + print('signature verified: $verified'); } // create a JWS -example2() async { +void example2() async { // create a builder - var builder = new JsonWebSignatureBuilder(); + var builder = JsonWebSignatureBuilder(); // set the content - builder.stringContent = "It is me"; + builder.stringContent = 'It is me'; // set some protected header - builder.setProtectedHeader("createdAt", new DateTime.now().toIso8601String()); + builder.setProtectedHeader('createdAt', DateTime.now().toIso8601String()); // add a key to sign, you can add multiple keys for different recipients builder.addRecipient( - new JsonWebKey.fromJson({ - "kty": "oct", - "k": - "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow" + JsonWebKey.fromJson({ + 'kty': 'oct', + 'k': + 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow' }), - algorithm: "HS256"); + algorithm: 'HS256'); // build the jws var jws = builder.build(); // output the compact serialization - print("jws compact serialization: ${jws.toCompactSerialization()}"); + print('jws compact serialization: ${jws.toCompactSerialization()}'); // output the json serialization - print("jws json serialization: ${jws.toJson()}"); + print('jws json serialization: ${jws.toJson()}'); } // decode and decrypt a JWE -example3() async { - var encoded = "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0." - "UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm" - "1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7Pc" - "HALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIF" - "NPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPhcCdZ6XDP0_F8" - "rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPgwCp6X-nZZd9OHBv" - "-B3oWh2TbqmScqXMR4gp_A." - "AxY8DCtDaGlsbGljb3RoZQ." - "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY." - "9hH0vgRfYgPnAHOd8stkvw"; +void example3() async { + var encoded = 'eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.' + 'UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm' + '1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7Pc' + 'HALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIF' + 'NPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPhcCdZ6XDP0_F8' + 'rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPgwCp6X-nZZd9OHBv' + '-B3oWh2TbqmScqXMR4gp_A.' + 'AxY8DCtDaGlsbGljb3RoZQ.' + 'KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.' + '9hH0vgRfYgPnAHOd8stkvw'; // create a JsonWebEncryption from the encoded string var jwe = JsonWebEncryption.fromCompactSerialization(encoded); // create a JsonWebKey for decrypting the signature - var jwk = new JsonWebKey.fromJson( + var jwk = JsonWebKey.fromJson( { - "kty": "RSA", - "n": "sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl" - "UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre" - "cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_" - "7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI" - "Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU" - "7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw", - "e": "AQAB", - "d": "VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq" - "1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry" - "nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_" - "0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj" - "-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj" - "T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ", - "p": "9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68" - "ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP" - "krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM", - "q": "uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y" - "BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN" - "-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0", - "dp": "w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv" - "ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra" - "Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs", - "dq": "o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff" - "7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_" - "odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU", - "qi": "eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC" - "tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ" - "B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo" + 'kty': 'RSA', + 'n': 'sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl' + 'UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre' + 'cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_' + '7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI' + 'Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU' + '7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw', + 'e': 'AQAB', + 'd': 'VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq' + '1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry' + 'nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_' + '0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj' + '-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj' + 'T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ', + 'p': '9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68' + 'ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP' + 'krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM', + 'q': 'uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y' + 'BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN' + '-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0', + 'dp': 'w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv' + 'ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra' + 'Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs', + 'dq': 'o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff' + '7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_' + 'odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU', + 'qi': 'eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC' + 'tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ' + 'B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo' }, ); - var keyStore = new JsonWebKeyStore()..addKey(jwk); + var keyStore = JsonWebKeyStore()..addKey(jwk); // decrypt the payload var payload = await jwe.getPayload(keyStore); - print("decrypted content: ${payload.stringContent}"); + print('decrypted content: ${payload.stringContent}'); } // create a JWE -example4() async { +void example4() async { // create a builder - var builder = new JsonWebEncryptionBuilder(); + var builder = JsonWebEncryptionBuilder(); // set the content - builder.stringContent = "This is my bigest secret"; + builder.stringContent = 'This is my bigest secret'; // set some protected header - builder.setProtectedHeader("createdAt", new DateTime.now().toIso8601String()); + builder.setProtectedHeader('createdAt', DateTime.now().toIso8601String()); // add a key to encrypt the Content Encryption Key - var jwk = new JsonWebKey.fromJson( + var jwk = JsonWebKey.fromJson( { - "kty": "RSA", - "n": "sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl" - "UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre" - "cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_" - "7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI" - "Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU" - "7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw", - "e": "AQAB", - "d": "VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq" - "1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry" - "nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_" - "0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj" - "-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj" - "T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ", - "p": "9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68" - "ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP" - "krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM", - "q": "uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y" - "BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN" - "-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0", - "dp": "w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv" - "ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra" - "Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs", - "dq": "o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff" - "7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_" - "odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU", - "qi": "eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC" - "tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ" - "B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo" + 'kty': 'RSA', + 'n': 'sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl' + 'UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre' + 'cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_' + '7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI' + 'Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU' + '7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw', + 'e': 'AQAB', + 'd': 'VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq' + '1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry' + 'nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_' + '0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj' + '-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj' + 'T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ', + 'p': '9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68' + 'ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP' + 'krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM', + 'q': 'uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y' + 'BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN' + '-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0', + 'dp': 'w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv' + 'ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra' + 'Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs', + 'dq': 'o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff' + '7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_' + 'odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU', + 'qi': 'eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC' + 'tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ' + 'B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo' }, ); - builder.addRecipient(jwk, algorithm: "RSA1_5"); + builder.addRecipient(jwk, algorithm: 'RSA1_5'); // set the content encryption algorithm to use - builder.encryptionAlgorithm = "A128CBC-HS256"; + builder.encryptionAlgorithm = 'A128CBC-HS256'; // build the jws var jwe = builder.build(); // output the compact serialization - print("jwe compact serialization: ${jwe.toCompactSerialization()}"); + print('jwe compact serialization: ${jwe.toCompactSerialization()}'); // output the json serialization - print("jwe json serialization: ${jwe.toJson()}"); + print('jwe json serialization: ${jwe.toJson()}'); } // decode and verify and validate a JWT -example5() async { - var encoded = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9." - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt" - "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ." - "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"; +void example5() async { + var encoded = 'eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.' + 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt' + 'cGxlLmNvbS9pc19yb290Ijp0cnVlfQ.' + 'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk'; // decode the jwt, note: this constructor can only be used for JWT inside JWS // structures - var jwt = new JsonWebToken.unverified(encoded); + var jwt = JsonWebToken.unverified(encoded); // output the claims - print("claims: ${jwt.claims}"); + print('claims: ${jwt.claims}'); // create key store to verify the signature - var keyStore = new JsonWebKeyStore() - ..addKey(new JsonWebKey.fromJson({ - "kty": "oct", - "k": - "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow" + var keyStore = JsonWebKeyStore() + ..addKey(JsonWebKey.fromJson({ + 'kty': 'oct', + 'k': + 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow' })); var verified = await jwt.verify(keyStore); - print("verified: $verified"); + print('verified: $verified'); // alternatively, create and verify the JsonWebToken together, this is also // applicable for JWT inside JWE jwt = await JsonWebToken.decodeAndVerify(encoded, keyStore); // validate the claims - var violations = jwt.claims.validate(issuer: Uri.parse("alice")); - print("violations: $violations"); + var violations = jwt.claims.validate(issuer: Uri.parse('alice')); + print('violations: $violations'); } // create a JWT -example6() async { - var claims = new JsonWebTokenClaims.fromJson({ - "exp": new Duration(hours: 4).inSeconds, - "iss": "alice", +void example6() async { + var claims = JsonWebTokenClaims.fromJson({ + 'exp': Duration(hours: 4).inSeconds, + 'iss': 'alice', }); // create a builder, decoding the JWT in a JWS, so using a // JsonWebSignatureBuilder - var builder = new JsonWebSignatureBuilder(); + var builder = JsonWebSignatureBuilder(); // set the content builder.jsonContent = claims.toJson(); // add a key to sign, can only add one for JWT builder.addRecipient( - new JsonWebKey.fromJson({ - "kty": "oct", - "k": - "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow" + JsonWebKey.fromJson({ + 'kty': 'oct', + 'k': + 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow' }), - algorithm: "HS256"); + algorithm: 'HS256'); // build the jws var jws = builder.build(); // output the compact serialization - print("jwt compact serialization: ${jws.toCompactSerialization()}"); + print('jwt compact serialization: ${jws.toCompactSerialization()}'); } diff --git a/lib/src/jose.dart b/lib/src/jose.dart index dcd9e36..f5141dc 100644 --- a/lib/src/jose.dart +++ b/lib/src/jose.dart @@ -23,21 +23,21 @@ class JoseHeader extends JsonObject { /// Identifies the cryptographic algorithm used to secure a [JsonWebSignature] /// or to encrypt or determine the value of a Content Encryption Key with /// [JsonWebEncryption]. - String get algorithm => getTyped("alg"); + String get algorithm => getTyped('alg'); /// Refers to a resource for a set of JSON-encoded public keys, one of which /// corresponds to the key used to digitally sign the [JsonWebSignature] or /// encrypt the [JsonWebEncryption]. - Uri get jwkSetUrl => getTyped("jku"); + Uri get jwkSetUrl => getTyped('jku'); /// The public key that corresponds to the key used to digitally sign the /// [JsonWebSignature] or encrypt the [JsonWebEncryption]. JsonWebKey get jsonWebKey => - getTyped("jwk", factory: (v) => new JsonWebKey.fromJson(v)); + getTyped('jwk', factory: (v) => JsonWebKey.fromJson(v)); /// A hint indicating which key was used to secure the [JsonWebSignature] or /// encrypt the [JsonWebEncryption]. - String get keyId => getTyped("kid"); + String get keyId => getTyped('kid'); /* TODO: implement X.509 @@ -45,48 +45,48 @@ class JoseHeader extends JsonObject { /// Refers to a resource for the X.509 public key certificate or certificate /// chain corresponding to the key used to digitally sign the /// [JsonWebSignature] or encrypt the [JsonWebEncryption]. - Uri get x509Url => this["x5u"] == null ? null : Uri.parse(this["x5u"]); + Uri get x509Url => this['x5u'] == null ? null : Uri.parse(this['x5u']); /// The X.509 public key certificate or certificate chain [RFC5280] /// corresponding to the key used to digitally sign the /// [JsonWebSignature] or encrypt the [JsonWebEncryption]. - dynamic get x509CertificateChain => this["x5c"]; + dynamic get x509CertificateChain => this['x5c']; /// A base64url-encoded SHA-1 thumbprint (a.k.a. digest) of the DER /// encoding of the X.509 certificate corresponding to the key used to /// digitally sign the [JsonWebSignature] or encrypt the [JsonWebEncryption]. - String get x509CertificateSha1Thumbprint => this["x5t"]; + String get x509CertificateSha1Thumbprint => this['x5t']; /// A base64url-encoded SHA-256 thumbprint (a.k.a. digest) of the DER /// encoding of the X.509 certificate corresponding to the key used to /// digitally sign the [JsonWebSignature] or encrypt the [JsonWebEncryption]. - String get x509CertificateSha256Thumbprint => this["x5t#S256"]; + String get x509CertificateSha256Thumbprint => this['x5t#S256']; */ /// Declares the media type [IANA.MediaTypes](https://www.iana.org/assignments /// /media-types/media-types.xhtml) of the complete [JsonWebSignature] or /// [JsonWebEncryption]. - String get type => getTyped("typ"); + String get type => getTyped('typ'); /// Declares the media type [IANA.MediaTypes](https://www.iana.org/assignments /// /media-types/media-types.xhtml) the secured content (the payload) of the /// [JsonWebSignature] or [JsonWebEncryption]. - String get contentType => getTyped("cty"); + String get contentType => getTyped('cty'); /// Indicates that extensions to this specification and/or [JsonWebAlgoritm] /// are being used that MUST be understood and processed. - List get critical => getTyped("crit"); + List get critical => getTyped('crit'); /// The content encryption algorithm used to perform authenticated encryption /// on the plaintext to produce the ciphertext and the Authentication Tag. /// /// Only for [JsonWebEncryption] objects - String get encryptionAlgorithm => getTyped("enc"); + String get encryptionAlgorithm => getTyped('enc'); /// Compression algorithm applied to the plaintext before encryption, if any. /// /// Only for [JsonWebEncryption] objects - String get compressionAlgorithm => getTyped("zip"); + String get compressionAlgorithm => getTyped('zip'); } /// Base class for [JsonWebSignature] and [JsonWebEncryption]. @@ -118,25 +118,24 @@ abstract class JoseObject { /// Constructs a [JsonWebSignature] or [JsonWebEncryption] from its json /// representation. factory JoseObject.fromJson(Map json) { - if (json.containsKey("payload")) return new JsonWebSignature.fromJson(json); - if (json.containsKey("ciphertext")) - return new JsonWebEncryption.fromJson(json); - throw new ArgumentError.value( - json, "json", "Not a valid `JsonWebSignature` or `JsonWebEncryption`"); + if (json.containsKey('payload')) return JsonWebSignature.fromJson(json); + if (json.containsKey('ciphertext')) return JsonWebEncryption.fromJson(json); + throw ArgumentError.value( + json, 'json', 'Not a valid `JsonWebSignature` or `JsonWebEncryption`'); } /// Constructs a [JsonWebSignature] or [JsonWebEncryption] from its compact /// serialization. factory JoseObject.fromCompactSerialization(String serialization) { - var parts = serialization.split("."); + var parts = serialization.split('.'); switch (parts.length) { case 3: - return new JsonWebSignature.fromCompactSerialization(serialization); + return JsonWebSignature.fromCompactSerialization(serialization); case 5: - return new JsonWebEncryption.fromCompactSerialization(serialization); + return JsonWebEncryption.fromCompactSerialization(serialization); default: - throw new ArgumentError.value(serialization, "serialization", - "Not a valid `JsonWebSignature` or `JsonWebEncryption`"); + throw ArgumentError.value(serialization, 'serialization', + 'Not a valid `JsonWebSignature` or `JsonWebEncryption`'); } } @@ -162,7 +161,7 @@ abstract class JoseObject { JoseHeader get commonHeader { var sharedHeader = safeUnion( [sharedProtectedHeader?.toJson(), sharedUnprotectedHeader?.toJson()]); - return new JoseHeader.fromJson(commonUnion(recipients.map((r) => safeUnion([ + return JoseHeader.fromJson(commonUnion(recipients.map((r) => safeUnion([ sharedHeader, r.protectedHeader?.toJson(), r.unprotectedHeader?.toJson() @@ -178,7 +177,7 @@ abstract class JoseObject { /// parameters. JoseHeader get commonProtectedHeader { var sharedHeader = sharedProtectedHeader?.toJson(); - return new JoseHeader.fromJson(commonUnion(recipients.map((r) => safeUnion([ + return JoseHeader.fromJson(commonUnion(recipients.map((r) => safeUnion([ sharedHeader, r.protectedHeader?.toJson(), ])))); @@ -206,20 +205,23 @@ abstract class JoseObject { var header = _headerFor(r); if (allowedAlgorithms != null && !allowedAlgorithms.contains(header.algorithm)) continue; - if (allowedAlgorithms == null && header.algorithm == "none") continue; + if (allowedAlgorithms == null && header.algorithm == 'none') continue; await for (var key in keyStore.findJsonWebKeys( header, this is JsonWebSignature - ? "verify" - : header.algorithm == "dir" ? "decrypt" : "unwrapKey")) { + ? 'verify' + : header.algorithm == 'dir' ? 'decrypt' : 'unwrapKey')) { try { var payload = getPayloadFor(key, header, r); - if (payload != null) - return new JosePayload(payload, _protectedHeaderFor(r)); - } catch (e) {} + if (payload != null) { + return JosePayload(payload, _protectedHeaderFor(r)); + } + } catch (e) { + // ignore + } } } - throw new JoseException("Could not decrypt/verify payload"); + throw JoseException('Could not decrypt/verify payload'); } @protected @@ -227,7 +229,7 @@ abstract class JoseObject { JsonWebKey key, JoseHeader header, JoseRecipient recipient); JoseHeader _headerFor(JoseRecipient recipient) { - return new JoseHeader.fromJson(safeUnion([ + return JoseHeader.fromJson(safeUnion([ sharedProtectedHeader?.toJson(), sharedUnprotectedHeader?.toJson(), recipient.header?.toJson() @@ -235,7 +237,7 @@ abstract class JoseObject { } JoseHeader _protectedHeaderFor(JoseRecipient recipient) { - return new JoseHeader.fromJson(safeUnion([ + return JoseHeader.fromJson(safeUnion([ sharedProtectedHeader?.toJson(), recipient.protectedHeader?.toJson() ])); @@ -269,7 +271,7 @@ abstract class JoseRecipient { final List data; JoseRecipient({this.data, this.protectedHeader, this.unprotectedHeader}) - : header = new JoseHeader.fromJson(safeUnion( + : header = JoseHeader.fromJson(safeUnion( [protectedHeader?.toJson(), unprotectedHeader?.toJson()])); Map toJson(); @@ -296,8 +298,8 @@ class JosePayload { /// The media type [IANA.MediaTypes](https://www.iana.org/assignments/ /// media-types/media-types.xhtml) of the payload. /// - /// This is the "cty" header parameter - String get mediaType => protectedHeader["cty"]; + /// This is the 'cty' header parameter + String get mediaType => protectedHeader['cty']; } /// Base class for [JsonWebSignatureBuilder] and [JsonWebEncryptionBuilder] @@ -324,12 +326,13 @@ abstract class JoseObjectBuilder { /// Sets the set content(dynamic v) { - if (v is String) + if (v is String) { stringContent = v; - else if (v is List) + } else if (v is List) { data = v; - else + } else { jsonContent = v; + } } /// Sets a shared protected header parameter @@ -344,18 +347,18 @@ abstract class JoseObjectBuilder { /// The media type [IANA.MediaTypes](https://www.iana.org/assignments/ /// media-types/media-types.xhtml) of the payload. /// - /// This is the "cty" header parameter - String get mediaType => _protectedHeaderParameters["cty"]; + /// This is the 'cty' header parameter + String get mediaType => _protectedHeaderParameters['cty']; - set mediaType(String v) => _protectedHeaderParameters["cty"] = v; + set mediaType(String v) => _protectedHeaderParameters['cty'] = v; /// Returns the protected header parameters as a [JoseHeader] object JoseHeader get protectedHeader => - new JoseHeader.fromJson(_protectedHeaderParameters); + JoseHeader.fromJson(_protectedHeaderParameters); /// Returns the payload and protected headers as a [JosePayload] object JosePayload get payload => - data == null ? null : new JosePayload(data, protectedHeader); + data == null ? null : JosePayload(data, protectedHeader); /// Adds a [key] and [algorithm] to sign or encrypt this object /// @@ -363,7 +366,7 @@ abstract class JoseObjectBuilder { /// that use different keys. The compact serialization as a string can only /// have one recipient however. void addRecipient(JsonWebKey key, {String algorithm}) { - recipients.add({"_jwk": key, "alg": algorithm}); + recipients.add({'_jwk': key, 'alg': algorithm}); } /// Build the [JsonWebSignature] or [JsonWebEncryption] @@ -374,8 +377,9 @@ class JoseException implements Exception { final String message; JoseException(this.message); + @override String toString() { - if (message == null) return "JoseException"; - return "JoseException: $message"; + if (message == null) return 'JoseException'; + return 'JoseException: $message'; } } diff --git a/lib/src/jwe.dart b/lib/src/jwe.dart index f0abb34..1a05f64 100644 --- a/lib/src/jwe.dart +++ b/lib/src/jwe.dart @@ -44,17 +44,17 @@ class JsonWebEncryption extends JoseObject { /// Constructs a [JsonWebEncryption] from its compact serialization factory JsonWebEncryption.fromCompactSerialization(String serialization) { - var parts = serialization.split("."); + var parts = serialization.split('.'); if (parts.length != 5) { - throw new ArgumentError.value( - serialization, "Compact serialization should have 5 parts."); + throw ArgumentError.value( + serialization, 'Compact serialization should have 5 parts.'); } - return new JsonWebEncryption._( + return JsonWebEncryption._( decodeBase64EncodedBytes(parts[3]), - new List.unmodifiable([ - new _JweRecipient._(encryptedKey: decodeBase64EncodedBytes(parts[1])) + List.unmodifiable([ + _JweRecipient._(encryptedKey: decodeBase64EncodedBytes(parts[1])) ]), - protectedHeader: new JsonObject.decode(parts[0]), + protectedHeader: JsonObject.decode(parts[0]), initializationVector: decodeBase64EncodedBytes(parts[2]), authenticationTag: decodeBase64EncodedBytes(parts[4])); } @@ -63,80 +63,80 @@ class JsonWebEncryption extends JoseObject { /// representation JsonWebEncryption.fromJson(Map json) : this._( - decodeBase64EncodedBytes(json["ciphertext"]), - new List.unmodifiable(json.containsKey("recipients") - ? (json["recipients"] as List).map((v) => new _JweRecipient._( - header: new JsonObject.from(v["header"]), - encryptedKey: decodeBase64EncodedBytes(v["encrypted_key"]))) + decodeBase64EncodedBytes(json['ciphertext']), + List.unmodifiable(json.containsKey('recipients') + ? (json['recipients'] as List).map((v) => _JweRecipient._( + header: JsonObject.from(v['header']), + encryptedKey: decodeBase64EncodedBytes(v['encrypted_key']))) : [ - new _JweRecipient._( - header: new JsonObject.from(json["header"]), + _JweRecipient._( + header: JsonObject.from(json['header']), encryptedKey: - decodeBase64EncodedBytes(json["encrypted_key"])) + decodeBase64EncodedBytes(json['encrypted_key'])) ]), - protectedHeader: new JsonObject.decode(json["protected"]), - unprotectedHeader: new JsonObject.from(json["unprotected"]), - initializationVector: decodeBase64EncodedBytes(json["iv"]), - additionalAuthenticatedData: decodeBase64EncodedBytes(json["aad"]), - authenticationTag: decodeBase64EncodedBytes(json["tag"]), + protectedHeader: JsonObject.decode(json['protected']), + unprotectedHeader: JsonObject.from(json['unprotected']), + initializationVector: decodeBase64EncodedBytes(json['iv']), + additionalAuthenticatedData: decodeBase64EncodedBytes(json['aad']), + authenticationTag: decodeBase64EncodedBytes(json['tag']), ); @override String toCompactSerialization() { if (recipients.length != 1) { - throw new StateError( - "Compact serialization does not support multiple recipients"); + throw StateError( + 'Compact serialization does not support multiple recipients'); } if (sharedUnprotectedHeader != null) { - throw new StateError( - "Compact serialization does not support shared unprotected header"); + throw StateError( + 'Compact serialization does not support shared unprotected header'); } var recipient = recipients.first; if (recipient.unprotectedHeader != null) { - throw new StateError( - "Compact serialization does not support unprotected header parameters"); + throw StateError( + 'Compact serialization does not support unprotected header parameters'); } - return "${sharedProtectedHeader.toBase64EncodedString()}." - "${encodeBase64EncodedBytes(recipient.data)}." - "${encodeBase64EncodedBytes(initializationVector)}." - "${encodeBase64EncodedBytes(data)}." - "${encodeBase64EncodedBytes(authenticationTag)}"; + return '${sharedProtectedHeader.toBase64EncodedString()}.' + '${encodeBase64EncodedBytes(recipient.data)}.' + '${encodeBase64EncodedBytes(initializationVector)}.' + '${encodeBase64EncodedBytes(data)}.' + '${encodeBase64EncodedBytes(authenticationTag)}'; } @override Map toJson() { var v = { - "protected": sharedProtectedHeader?.toBase64EncodedString(), - "unprotected": sharedUnprotectedHeader?.toJson(), - "iv": encodeBase64EncodedBytes(initializationVector), - "aad": encodeBase64EncodedBytes(additionalAuthenticatedData), - "ciphertext": encodeBase64EncodedBytes(data), - "tag": encodeBase64EncodedBytes(authenticationTag), + 'protected': sharedProtectedHeader?.toBase64EncodedString(), + 'unprotected': sharedUnprotectedHeader?.toJson(), + 'iv': encodeBase64EncodedBytes(initializationVector), + 'aad': encodeBase64EncodedBytes(additionalAuthenticatedData), + 'ciphertext': encodeBase64EncodedBytes(data), + 'tag': encodeBase64EncodedBytes(authenticationTag), }; if (recipients.length == 1) { v.addAll(recipients.first.toJson()); } else { - v["recipients"] = recipients.map((r) => r.toJson()).toList(); + v['recipients'] = recipients.map((r) => r.toJson()).toList(); } - return new Map.fromEntries(v.entries.where((e) => e.value != null)); + return Map.fromEntries(v.entries.where((e) => e.value != null)); } @override List getPayloadFor( JsonWebKey key, JoseHeader header, JoseRecipient recipient) { - var aad = sharedProtectedHeader?.toBase64EncodedString() ?? ""; + var aad = sharedProtectedHeader?.toBase64EncodedString() ?? ''; if (additionalAuthenticatedData != null) { - aad += ".${new String.fromCharCodes(additionalAuthenticatedData)}"; + aad += '.${String.fromCharCodes(additionalAuthenticatedData)}'; } - if (header.encryptionAlgorithm == "none") { - throw new JoseException("Encryption algorithm cannot be `none`"); + if (header.encryptionAlgorithm == 'none') { + throw JoseException('Encryption algorithm cannot be `none`'); } - var cek = header.algorithm == "dir" + var cek = header.algorithm == 'dir' ? key : key.unwrapKey(recipient.data, algorithm: header.algorithm); return cek.decrypt(data, initializationVector: initializationVector, - additionalAuthenticatedData: new Uint8List.fromList(aad.codeUnits), + additionalAuthenticatedData: Uint8List.fromList(aad.codeUnits), authenticationTag: authenticationTag, algorithm: header.encryptionAlgorithm); } @@ -146,9 +146,10 @@ class _JweRecipient extends JoseRecipient { _JweRecipient._({JsonObject header, List encryptedKey}) : super(unprotectedHeader: header, data: encryptedKey); + @override Map toJson() => { - "header": unprotectedHeader?.toJson(), - "encrypted_key": encodeBase64EncodedBytes(data) + 'header': unprotectedHeader?.toJson(), + 'encrypted_key': encodeBase64EncodedBytes(data) }; } @@ -161,78 +162,77 @@ class JsonWebEncryptionBuilder extends JoseObjectBuilder { /// The content encryption algorithm to be used to perform authenticated /// encryption on the plaintext to produce the ciphertext and the /// Authentication Tag. - String encryptionAlgorithm = "A128CBC-HS256"; + String encryptionAlgorithm = 'A128CBC-HS256'; @override JsonWebEncryption build() { if (encryptionAlgorithm == null) { - throw new StateError("No encryption algorithm set"); + throw StateError('No encryption algorithm set'); } - if (encryptionAlgorithm == "none") { - throw new StateError("Encryption algorithm cannot be `none`"); + if (encryptionAlgorithm == 'none') { + throw StateError('Encryption algorithm cannot be `none`'); } if (recipients.isEmpty) { - throw new StateError("Need at least one recipient"); + throw StateError('Need at least one recipient'); } var payload = this.payload; if (payload == null) { - throw new StateError("No payload set"); + throw StateError('No payload set'); } var compact = recipients.length == 1 && additionalAuthenticatedData == null; - var cek = new JsonWebKey.generate(encryptionAlgorithm); + var cek = JsonWebKey.generate(encryptionAlgorithm); var sharedUnprotectedHeaderParams = { - "enc": encryptionAlgorithm + 'enc': encryptionAlgorithm }; var _recipients = recipients.map((r) { - var key = r["_jwk"] as JsonWebKey; + var key = r['_jwk'] as JsonWebKey; var algorithm = - r["alg"] ?? key?.algorithmForOperation("wrapKey") ?? "dir"; - if (algorithm == "dir") { + r['alg'] ?? key?.algorithmForOperation('wrapKey') ?? 'dir'; + if (algorithm == 'dir') { if (recipients.length > 1) { - throw new StateError( - "JWE can only have one recipient when using direct encryption with a shared symmetric key."); + throw StateError( + 'JWE can only have one recipient when using direct encryption with a shared symmetric key.'); } cek = key; } - var encryptedKey = algorithm == "dir" + var encryptedKey = algorithm == 'dir' ? null : key.wrapKey( cek, algorithm: algorithm, ); - var unprotectedHeaderParams = {"alg": algorithm}; + var unprotectedHeaderParams = {'alg': algorithm}; if (key?.keyId != null) { - unprotectedHeaderParams["kid"] = key.keyId; + unprotectedHeaderParams['kid'] = key.keyId; } if (compact) { sharedUnprotectedHeaderParams.addAll(unprotectedHeaderParams); } - return new _JweRecipient._( + return _JweRecipient._( encryptedKey: encryptedKey, - header: - compact ? null : new JsonObject.from(unprotectedHeaderParams)); + header: compact ? null : JsonObject.from(unprotectedHeaderParams)); }).toList(); var protectedHeader = payload.protectedHeader; if (compact) { - protectedHeader = new JsonObject.from(safeUnion( + protectedHeader = JsonObject.from(safeUnion( [protectedHeader?.toJson(), sharedUnprotectedHeaderParams])); } var aad = protectedHeader.toBase64EncodedString(); if (additionalAuthenticatedData != null) { - aad += ".${new String.fromCharCodes(additionalAuthenticatedData)}"; + aad += '.${String.fromCharCodes(additionalAuthenticatedData)}'; } - var encryptedData = cek.encrypt(this.data, - additionalAuthenticatedData: new Uint8List.fromList(aad.codeUnits)); - return new JsonWebEncryption._(encryptedData.data, _recipients, + var encryptedData = cek.encrypt(data, + additionalAuthenticatedData: Uint8List.fromList(aad.codeUnits)); + return JsonWebEncryption._(encryptedData.data, _recipients, protectedHeader: protectedHeader, unprotectedHeader: - compact ? null : new JsonObject.from(sharedUnprotectedHeaderParams), + compact ? null : JsonObject.from(sharedUnprotectedHeaderParams), initializationVector: encryptedData.initializationVector, authenticationTag: encryptedData.authenticationTag, additionalAuthenticatedData: additionalAuthenticatedData); diff --git a/lib/src/jwk.dart b/lib/src/jwk.dart index d5d20d4..797556a 100644 --- a/lib/src/jwk.dart +++ b/lib/src/jwk.dart @@ -16,42 +16,43 @@ class JsonWebKey extends JsonObject { /// Constructs a [JsonWebKey] from its JSON representation JsonWebKey.fromJson(Map json) - : _keyPair = new KeyPair.fromJwk(json), + : _keyPair = KeyPair.fromJwk(json), super.from(json) { - if (keyType == null) throw new ArgumentError.notNull("keyType"); - if (json.containsKey("x5u") || - json.containsKey("x5c") || - json.containsKey("x5t") || - json.containsKey("x5t#S256")) - throw new UnimplementedError("X.509 keys not implemented"); + if (keyType == null) throw ArgumentError.notNull('keyType'); + if (json.containsKey('x5u') || + json.containsKey('x5c') || + json.containsKey('x5t') || + json.containsKey('x5t#S256')) { + throw UnimplementedError('X.509 keys not implemented'); + } } static const _keyBitLengthByEncAlg = { - "A128CBC-HS256": 256, - "A192CBC-HS384": 384, - "A256CBC-HS512": 512, - "A128GCM": 256, - "A192GCM": 384, - "A256GCM": 512 + 'A128CBC-HS256': 256, + 'A192CBC-HS384': 384, + 'A256CBC-HS512': 512, + 'A128GCM': 256, + 'A192GCM': 384, + 'A256GCM': 512 }; /// Generates a random symmetric key suitable for the specified [algorithm] factory JsonWebKey.generate(String algorithm) { var bitLength = _keyBitLengthByEncAlg[algorithm]; - var keyPair = new KeyPair.generateSymmetric(bitLength); - return new JsonWebKey.fromJson({ - "kty": "oct", - "k": encodeBase64EncodedBytes( + var keyPair = KeyPair.generateSymmetric(bitLength); + return JsonWebKey.fromJson({ + 'kty': 'oct', + 'k': encodeBase64EncodedBytes( (keyPair.publicKey as SymmetricKey).keyValue), - "alg": algorithm, - "use": "enc", - "keyOperations": ["encrypt", "decrypt"] + 'alg': algorithm, + 'use': 'enc', + 'keyOperations': ['encrypt', 'decrypt'] }); } /// The cryptographic algorithm family used with the key, such as `RSA` or /// `EC`. - String get keyType => this["kty"]; + String get keyType => this['kty']; /// The intended use of the public key. /// @@ -62,7 +63,7 @@ class JsonWebKey extends JsonObject { /// /// Other values MAY be used. /// - String get publicKeyUse => this["use"]; + String get publicKeyUse => this['use']; /// The operation(s) that the key is intended to be used for. /// @@ -78,38 +79,38 @@ class JsonWebKey extends JsonObject { /// * `deriveBits` (derive bits not to be used as a key) /// /// Other values MAY be used. - Set get keyOperations => getTypedList("key_ops")?.toSet(); + Set get keyOperations => getTypedList('key_ops')?.toSet(); /// The algorithm intended for use with the key. - String get algorithm => this["alg"]; + String get algorithm => this['alg']; /// Key ID used to match a specific key. /// /// This is used, for instance, to choose among a set of keys within a JWK Set /// during key rollover. - String get keyId => this["kid"]; + String get keyId => this['kid']; /* TODO: implement X.509 /// A resource for an X.509 public key certificate or certificate chain. - Uri get x509Url => _json["x5u"]==null ? null : Uri.parse(_json["x5u"]); + Uri get x509Url => _json['x5u']==null ? null : Uri.parse(_json['x5u']); /// A chain of one or more PKIX certificates. - dynamic get x509CertificateChain => _json["x5c"]; + dynamic get x509CertificateChain => _json['x5c']; /// A base64url encoded SHA-1 thumbprint (a.k.a. digest) of the DER encoding /// of an X.509 certificate. - String get x509CertificateThumbprint => _json["x5t"]; + String get x509CertificateThumbprint => _json['x5t']; /// A base64url encoded SHA-256 thumbprint (a.k.a. digest) of the DER encoding /// of an X.509 certificate. - String get x509CertificateSha256Thumbprint => _json["x5t#S256"]; + String get x509CertificateSha256Thumbprint => _json['x5t#S256']; */ /// Compute digital signature or MAC List sign(List data, {String algorithm}) { - _assertCanDo("sign"); + _assertCanDo('sign'); var signer = _keyPair.privateKey.createSigner(_getAlgorithm(algorithm)); var signature = signer.sign(data); return signature.data; @@ -117,9 +118,9 @@ class JsonWebKey extends JsonObject { /// Verify digital signature or MAC bool verify(List data, List signature, {String algorithm}) { - _assertCanDo("verify"); + _assertCanDo('verify'); var verifier = _keyPair.publicKey.createVerifier(_getAlgorithm(algorithm)); - return verifier.verify(data, new Signature(signature)); + return verifier.verify(data, Signature(signature)); } /// Encrypt content @@ -127,7 +128,7 @@ class JsonWebKey extends JsonObject { {List initializationVector, List additionalAuthenticatedData, String algorithm}) { - _assertCanDo("encrypt"); + _assertCanDo('encrypt'); algorithm ??= this.algorithm; var encrypter = _keyPair.publicKey.createEncrypter(_getAlgorithm(algorithm)); @@ -142,11 +143,11 @@ class JsonWebKey extends JsonObject { List authenticationTag, List additionalAuthenticatedData, String algorithm}) { - _assertCanDo("decrypt"); + _assertCanDo('decrypt'); algorithm ??= this.algorithm; var decrypter = _keyPair.privateKey.createEncrypter(_getAlgorithm(algorithm)); - return decrypter.decrypt(new EncryptionResult(data, + return decrypter.decrypt(EncryptionResult(data, initializationVector: initializationVector, authenticationTag: authenticationTag, additionalAuthenticatedData: additionalAuthenticatedData)); @@ -154,28 +155,29 @@ class JsonWebKey extends JsonObject { /// Encrypt key List wrapKey(JsonWebKey key, {String algorithm}) { - _assertCanDo("wrapKey"); - if (key.keyType != "oct") - throw new UnsupportedError("Can only wrap symmetric keys"); + _assertCanDo('wrapKey'); + if (key.keyType != 'oct') { + throw UnsupportedError('Can only wrap symmetric keys'); + } algorithm ??= this.algorithm; var encrypter = _keyPair.publicKey.createEncrypter(_getAlgorithm(algorithm)); - var v = encrypter.encrypt(decodeBase64EncodedBytes(key["k"])); + var v = encrypter.encrypt(decodeBase64EncodedBytes(key['k'])); return v.data; } /// Decrypt key and validate decryption, if applicable JsonWebKey unwrapKey(List data, {String algorithm}) { - _assertCanDo("unwrapKey"); + _assertCanDo('unwrapKey'); algorithm ??= this.algorithm; var decrypter = _keyPair.privateKey.createEncrypter(_getAlgorithm(algorithm)); - var v = decrypter.decrypt(new EncryptionResult(data)); - return new JsonWebKey.fromJson({ - "kty": "oct", - "k": encodeBase64EncodedBytes(v), - "use": "enc", - "keyOperations": ["encrypt", "decrypt"] + var v = decrypter.decrypt(EncryptionResult(data)); + return JsonWebKey.fromJson({ + 'kty': 'oct', + 'k': encodeBase64EncodedBytes(v), + 'use': 'enc', + 'keyOperations': ['encrypt', 'decrypt'] }); } @@ -187,123 +189,123 @@ class JsonWebKey extends JsonObject { // Algorithms for JWS /// HMAC using SHA-256 - case "HS256": + case 'HS256': /// HMAC using SHA-384 - case "HS384": + case 'HS384': /// HMAC using SHA-512 - case "HS512": - return keyType == "oct"; + case 'HS512': + return keyType == 'oct'; /// RSASSA-PKCS1-v1_5 using SHA-256 - case "RS256": + case 'RS256': /// RSASSA-PKCS1-v1_5 using SHA-384 - case "RS384": + case 'RS384': /// RSASSA-PKCS1-v1_5 using SHA-512 - case "RS512": - return keyType == "RSA"; + case 'RS512': + return keyType == 'RSA'; /// ECDSA using P-256 and SHA-256 - case "ES256": + case 'ES256': /// ECDSA using P-384 and SHA-384 - case "ES384": + case 'ES384': /// ECDSA using P-521 and SHA-512 - case "ES512": - return keyType == "EC"; + case 'ES512': + return keyType == 'EC'; /// RSASSA-PSS using SHA-256 and MGF1 with SHA-256 - case "PS256": + case 'PS256': /// RSASSA-PSS using SHA-384 and MGF1 with SHA-384 - case "PS384": + case 'PS384': /// RSASSA-PSS using SHA-512 and MGF1 with SHA-512 - case "PS512": + case 'PS512': return null; /// No digital signature or MAC - case "none": + case 'none': return null; // Algorithms for JWE /// RSAES-PKCS1-v1_5 - case "RSA1_5": + case 'RSA1_5': /// RSAES OAEP using default parameters - case "RSA-OAEP": + case 'RSA-OAEP': /// RSAES OAEP using SHA-256 and MGF1 with SHA-256 - case "RSA-OAEP-256": - return keyType == "RSA"; + case 'RSA-OAEP-256': + return keyType == 'RSA'; /// AES Key Wrap with default initial value using 128-bit key - case "A128KW": + case 'A128KW': /// AES Key Wrap with default initial value using 192-bit key - case "A192KW": + case 'A192KW': /// AES Key Wrap with default initial value using 256-bit key - case "A256KW": - return keyType == "oct"; + case 'A256KW': + return keyType == 'oct'; /// Direct use of a shared symmetric key as the CEK - case "dir": + case 'dir': return null; /// Elliptic Curve Diffie-Hellman Ephemeral Static key agreement using Concat KDF - case "ECDH-ES": + case 'ECDH-ES': - /// ECDH-ES using Concat KDF and CEK wrapped with "A128KW" - case "ECDH-ES+A128KW": + /// ECDH-ES using Concat KDF and CEK wrapped with 'A128KW' + case 'ECDH-ES+A128KW': - /// ECDH-ES using Concat KDF and CEK wrapped with "A192KW" - case "ECDH-ES+A192KW": + /// ECDH-ES using Concat KDF and CEK wrapped with 'A192KW' + case 'ECDH-ES+A192KW': - /// ECDH-ES using Concat KDF and CEK wrapped with "A256KW" - case "ECDH-ES+A256KW": + /// ECDH-ES using Concat KDF and CEK wrapped with 'A256KW' + case 'ECDH-ES+A256KW': /// Key wrapping with AES GCM using 128-bit key - case "A128GCMKW": + case 'A128GCMKW': /// Key wrapping with AES GCM using 192-bit key - case "A192GCMKW": + case 'A192GCMKW': /// Key wrapping with AES GCM using 256-bit key - case "A256GCMKW": + case 'A256GCMKW': - /// PBES2 with HMAC SHA-256 and "A128KW" wrapping - case "PBES2-HS256+A128KW": + /// PBES2 with HMAC SHA-256 and 'A128KW' wrapping + case 'PBES2-HS256+A128KW': - /// PBES2 with HMAC SHA-384 and "A192KW" wrapping - case "PBES2-HS384+A192KW": + /// PBES2 with HMAC SHA-384 and 'A192KW' wrapping + case 'PBES2-HS384+A192KW': - /// PBES2 with HMAC SHA-512 and "A256KW" wrapping - case "PBES2-HS512+A256KW": + /// PBES2 with HMAC SHA-512 and 'A256KW' wrapping + case 'PBES2-HS512+A256KW': return null; // Encryption Algorithms for JWE /// AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm - case "A128CBC-HS256": + case 'A128CBC-HS256': /// AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm - case "A192CBC-HS384": + case 'A192CBC-HS384': /// AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm - case "A256CBC-HS512": + case 'A256CBC-HS512': /// AES GCM using 128-bit key - case "A128GCM": + case 'A128GCM': /// AES GCM using 192-bit key - case "A192GCM": + case 'A192GCM': /// AES GCM using 256-bit key - case "A256GCM": - return keyType == "oct"; + case 'A256GCM': + return keyType == 'oct'; } return false; } @@ -317,26 +319,26 @@ class JsonWebKey extends JsonObject { if (ops != null && !ops.contains(operation)) return false; if (publicKeyUse != null) { switch (operation) { - case "sign": - case "verify": - if (publicKeyUse != "sig") return false; + case 'sign': + case 'verify': + if (publicKeyUse != 'sig') return false; break; - case "encrypt": - case "decrypt": - case "wrapKey": - case "unwrapKey": - if (publicKeyUse != "enc") return false; + case 'encrypt': + case 'decrypt': + case 'wrapKey': + case 'unwrapKey': + if (publicKeyUse != 'enc') return false; break; } } switch (operation) { - case "sign": - case "unwrapKey": - case "decrypt": + case 'sign': + case 'unwrapKey': + case 'decrypt': return _keyPair.privateKey != null; - case "verify": - case "wrapKey": - case "encrypt": + case 'verify': + case 'wrapKey': + case 'encrypt': return _keyPair.publicKey != null; } return false; @@ -348,37 +350,37 @@ class JsonWebKey extends JsonObject { if (!usableForOperation(operation)) return null; if (algorithm != null) return algorithm; switch (operation) { - case "sign": - case "verify": + case 'sign': + case 'verify': // TODO: use key length switch (keyType) { - case "oct": - return "HS256"; - case "RSA": - return "RS256"; - case "EC": - return "ES256"; + case 'oct': + return 'HS256'; + case 'RSA': + return 'RS256'; + case 'EC': + return 'ES256'; } return null; - case "wrapKey": - case "unwrapKey": + case 'wrapKey': + case 'unwrapKey': // TODO: use key length switch (keyType) { - case "oct": - return "A128KW"; - case "RSA": - return "RSA1_5"; - case "EC": + case 'oct': + return 'A128KW'; + case 'RSA': + return 'RSA1_5'; + case 'EC': return null; } return null; - case "encrypt": - case "decrypt": + case 'encrypt': + case 'decrypt': switch (keyType) { - case "oct": - return "A128CBC-HS256"; - case "RSA": - case "EC": + case 'oct': + return 'A128CBC-HS256'; + case 'RSA': + case 'EC': return null; } return null; @@ -387,13 +389,13 @@ class JsonWebKey extends JsonObject { } AlgorithmIdentifier _getAlgorithm(String algorithm) { - if (this["alg"] != null) { - if (this["alg"] != algorithm) { - throw new ArgumentError.value(algorithm, "algorithm", - "Algorithm should match key algorithm '${this["alg"]}'"); + if (this['alg'] != null) { + if (this['alg'] != algorithm) { + throw ArgumentError.value(algorithm, 'algorithm', + "Algorithm should match key algorithm '${this['alg']}'"); } } - algorithm ??= this["alg"]; + algorithm ??= this['alg']; return algorithm == null ? null : AlgorithmIdentifier.getByJwaName(algorithm); @@ -401,8 +403,7 @@ class JsonWebKey extends JsonObject { void _assertCanDo(String op) { if (!usableForOperation(op)) { - throw new StateError( - "This JsonWebKey does not support the '$op' operation."); + throw StateError("This JsonWebKey does not support the '$op' operation."); } } } @@ -411,12 +412,11 @@ class JsonWebKey extends JsonObject { class JsonWebKeySet extends JsonObject { /// An array of JWK values List get keys => - getTypedList("keys", factory: (v) => new JsonWebKey.fromJson(v)); + getTypedList('keys', factory: (v) => JsonWebKey.fromJson(v)); /// Constructs a [JsonWebKeySet] from the list of [keys] factory JsonWebKeySet.fromKeys(Iterable keys) => - new JsonWebKeySet.fromJson( - {"keys": keys.map((v) => v.toJson()).toList()}); + JsonWebKeySet.fromJson({'keys': keys.map((v) => v.toJson()).toList()}); /// Constructs a [JsonWebKeySet] from its JSON representation JsonWebKeySet.fromJson(Map json) : super.from(json); @@ -443,26 +443,26 @@ class JsonWebKeyStore { /// /// See also [https://tools.ietf.org/html/rfc7515#appendix-D] Stream findJsonWebKeys(JoseHeader header, String operation) { - if (header.algorithm == "none") return new Stream.fromIterable([null]); + if (header.algorithm == 'none') return Stream.fromIterable([null]); return _allKeys(header) .where((key) => _isValidKeyFor(key, header, operation)); } Stream _allKeys(JoseHeader header) async* { - // The key provided by the "jwk" + // The key provided by the 'jwk' if (header.jsonWebKey != null) yield header.jsonWebKey; // Other applicable keys available to the application - yield* new Stream.fromIterable(_keys); + yield* Stream.fromIterable(_keys); for (var s in _keySets) { - yield* new Stream.fromIterable(s.keys); + yield* Stream.fromIterable(s.keys); } /* // TODO trust keys from header? - // Keys referenced by the "jku" + // Keys referenced by the 'jku' if (header.jwkSetUrl != null) yield* _keysFromSet(header.jwkSetUrl); - // The key referenced by the "x5u" + // The key referenced by the 'x5u' // TODO - // The key provided by the "x5c" + // The key provided by the 'x5c' // TODO */ // Other applicable keys available to the application @@ -474,7 +474,7 @@ class JsonWebKeyStore { bool _isValidKeyFor(JsonWebKey key, JoseHeader header, String operation) { if (header.keyId != key.keyId) return false; return key.usableForAlgorithm( - operation == "encrypt" || operation == "decrypt" + operation == 'encrypt' || operation == 'decrypt' ? header.encryptionAlgorithm : header.algorithm) && key.usableForOperation(operation); @@ -484,15 +484,15 @@ class JsonWebKeyStore { var set = _findKeySetFromCache(uri); if (set == null) { try { - var v = await new Resource(uri).readAsString(); + var v = await Resource(uri).readAsString(); set = _addKeySetToCache( - uri, new JsonWebKeySet.fromJson(convert.json.decode(v))); + uri, JsonWebKeySet.fromJson(convert.json.decode(v))); } catch (e) { // TODO log return; } } - yield* new Stream.fromIterable(set.keys); + yield* Stream.fromIterable(set.keys); } JsonWebKeySet _addKeySetToCache(Uri uri, JsonWebKeySet set) => diff --git a/lib/src/jws.dart b/lib/src/jws.dart index 44fd5c0..ce56ec6 100644 --- a/lib/src/jws.dart +++ b/lib/src/jws.dart @@ -14,16 +14,16 @@ class JsonWebSignature extends JoseObject { /// Constructs a [JsonWebSignature] from its compact serialization factory JsonWebSignature.fromCompactSerialization(String serialization) { - var parts = serialization.split("."); + var parts = serialization.split('.'); if (parts.length != 3) { - throw new ArgumentError.value( - serialization, "Compact serialization should have 3 parts."); + throw ArgumentError.value( + serialization, 'Compact serialization should have 3 parts.'); } - return new JsonWebSignature._( + return JsonWebSignature._( decodeBase64EncodedBytes(parts[1]), - new List.unmodifiable([ - new _JwsRecipient( - protectedHeader: new JsonObject.decode(parts[0]), + List.unmodifiable([ + _JwsRecipient( + protectedHeader: JsonObject.decode(parts[0]), data: parts[2].isNotEmpty ? decodeBase64EncodedBytes(parts[2]) : null) @@ -34,22 +34,22 @@ class JsonWebSignature extends JoseObject { /// representation factory JsonWebSignature.fromJson(Map json) { var signatures; - if (json.containsKey("signatures")) { - signatures = json["signatures"].map((v) => new _JwsRecipient.fromJson(v)); + if (json.containsKey('signatures')) { + signatures = json['signatures'].map((v) => _JwsRecipient.fromJson(v)); } else { - signatures = [new _JwsRecipient.fromJson(json)]; + signatures = [_JwsRecipient.fromJson(json)]; } - return new JsonWebSignature._(decodeBase64EncodedBytes(json["payload"]), - new List.unmodifiable(signatures)); + return JsonWebSignature._(decodeBase64EncodedBytes(json['payload']), + List.unmodifiable(signatures)); } @override Map toJson() { - var v = {"payload": encodeBase64EncodedBytes(data)}; + var v = {'payload': encodeBase64EncodedBytes(data)}; if (recipients.length == 1) { v..addAll(recipients.first.toJson()); } else { - v["signatures"] = recipients.map((v) => v.toJson()).toList(); + v['signatures'] = recipients.map((v) => v.toJson()).toList(); } return v; } @@ -57,32 +57,32 @@ class JsonWebSignature extends JoseObject { @override String toCompactSerialization() { if (recipients.length != 1) { - throw new StateError( - "Compact serialization does not support multiple signatures"); + throw StateError( + 'Compact serialization does not support multiple signatures'); } var signature = recipients.first; if (signature.unprotectedHeader != null) { - throw new StateError( - "Compact serialization does not support unprotected header parameters"); + throw StateError( + 'Compact serialization does not support unprotected header parameters'); } - return "${signature.protectedHeader.toBase64EncodedString()}.${encodeBase64EncodedBytes(data)}." - "${signature.data == null ? "" : encodeBase64EncodedBytes(signature.data)}"; + return '${signature.protectedHeader.toBase64EncodedString()}.${encodeBase64EncodedBytes(data)}.' + '${signature.data == null ? '' : encodeBase64EncodedBytes(signature.data)}'; } /// Returns the unverified payload (with the protected header parameters from /// the first signature) - JosePayload get unverifiedPayload => new JosePayload(data, commonHeader); + JosePayload get unverifiedPayload => JosePayload(data, commonHeader); @override List getPayloadFor( JsonWebKey key, JoseHeader header, JoseRecipient recipient) { - if (header.algorithm == "none") { + if (header.algorithm == 'none') { return key == null && recipient.data == null ? this.data : null; } // verify header var encodedHeader = recipient.protectedHeader.toBase64EncodedString(); var encodedPayload = encodeBase64EncodedBytes(this.data); - var data = convert.utf8.encode("$encodedHeader.$encodedPayload"); + var data = convert.utf8.encode('$encodedHeader.$encodedPayload'); return key.verify(data, recipient.data, algorithm: header.algorithm) ? this.data : null; @@ -101,27 +101,26 @@ class _JwsRecipient extends JoseRecipient { _JwsRecipient.fromJson(Map json) : this( - protectedHeader: json["protected"] == null + protectedHeader: json['protected'] == null ? null - : new JsonObject.decode(json["protected"]), - unprotectedHeader: json["header"] == null + : JsonObject.decode(json['protected']), + unprotectedHeader: + json['header'] == null ? null : JsonObject.from(json['header']), + data: json['signature'] == null ? null - : new JsonObject.from(json["header"]), - data: json["signature"] == null - ? null - : decodeBase64EncodedBytes(json["signature"])); + : decodeBase64EncodedBytes(json['signature'])); factory _JwsRecipient._sign( List payload, JsonObject protectedHeader, JsonWebKey key, - {String algorithm, bool protectAll: false}) { + {String algorithm, bool protectAll = false}) { // Compute the encoded payload value BASE64URL(JWS Payload) var encodedPayload = encodeBase64EncodedBytes(payload); // Assemble the unprotected header - algorithm ??= key?.algorithmForOperation("sign") ?? "none"; - var unprotectedHeaderParams = {"alg": algorithm}; + algorithm ??= key?.algorithmForOperation('sign') ?? 'none'; + var unprotectedHeaderParams = {'alg': algorithm}; if (key?.keyId != null) { - unprotectedHeaderParams["kid"] = key.keyId; + unprotectedHeaderParams['kid'] = key.keyId; } var commonKeys = protectedHeader .toJson() @@ -130,7 +129,7 @@ class _JwsRecipient extends JoseRecipient { .intersection(unprotectedHeaderParams.keys.toSet()); for (var k in commonKeys) { if (unprotectedHeaderParams[k] != protectedHeader[k]) { - throw new ArgumentError( + throw ArgumentError( "Protected and unprotected have non-equal parameter '$k'"); } unprotectedHeaderParams.remove(k); @@ -138,20 +137,20 @@ class _JwsRecipient extends JoseRecipient { // Compute the encoded header value BASE64URL(UTF8(JWS Protected Header)) if (protectAll) { - protectedHeader = new JsonObject.from( + protectedHeader = JsonObject.from( unprotectedHeaderParams..addAll(protectedHeader.toJson())); } var unprotectedHeader = - protectAll ? null : new JsonObject.from(unprotectedHeaderParams); + protectAll ? null : JsonObject.from(unprotectedHeaderParams); var encodedHeader = protectedHeader.toBase64EncodedString(); - var data = convert.utf8.encode("$encodedHeader.$encodedPayload"); + var data = convert.utf8.encode('$encodedHeader.$encodedPayload'); var signature = - algorithm == "none" ? null : key.sign(data, algorithm: algorithm); + algorithm == 'none' ? null : key.sign(data, algorithm: algorithm); - return new _JwsRecipient( + return _JwsRecipient( protectedHeader: protectedHeader, unprotectedHeader: unprotectedHeader, data: signature); @@ -160,10 +159,11 @@ class _JwsRecipient extends JoseRecipient { @override Map toJson() { var o = {}; - if (protectedHeader != null) - o["protected"] = protectedHeader.toBase64EncodedString(); - if (unprotectedHeader != null) o["header"] = unprotectedHeader.toJson(); - if (data != null) o["signature"] = encodeBase64EncodedBytes(data); + if (protectedHeader != null) { + o['protected'] = protectedHeader.toBase64EncodedString(); + } + if (unprotectedHeader != null) o['header'] = unprotectedHeader.toJson(); + if (data != null) o['signature'] = encodeBase64EncodedBytes(data); return o; } } @@ -173,20 +173,20 @@ class JsonWebSignatureBuilder extends JoseObjectBuilder { @override JsonWebSignature build() { if (recipients.isEmpty) { - throw new StateError("Need at least one recipient"); + throw StateError('Need at least one recipient'); } var payload = this.payload; if (payload == null) { - throw new StateError("No payload set"); + throw StateError('No payload set'); } var _signatures = recipients.map((r) { - var key = r["_jwk"]; - var algorithm = r["alg"]; - return new _JwsRecipient._sign(payload.data, payload.protectedHeader, key, + var key = r['_jwk']; + var algorithm = r['alg']; + return _JwsRecipient._sign(payload.data, payload.protectedHeader, key, algorithm: algorithm, protectAll: recipients.length == 1); }).toList(); - return new JsonWebSignature._(payload.data, _signatures); + return JsonWebSignature._(payload.data, _signatures); } } diff --git a/lib/src/jwt.dart b/lib/src/jwt.dart index aa67892..683b4cb 100644 --- a/lib/src/jwt.dart +++ b/lib/src/jwt.dart @@ -13,7 +13,7 @@ class JsonWebTokenClaims extends JsonObject { JsonWebTokenClaims.fromJson(Map json) : super.from(json); /// Identifies the principal that issued the JWT. - Uri get issuer => getTyped("iss"); + Uri get issuer => getTyped('iss'); /// Identifies the principal that is the subject of the JWT. /// @@ -21,34 +21,34 @@ class JsonWebTokenClaims extends JsonObject { /// /// The subject value MUST either be scoped to be locally unique in the /// context of the issuer or be globally unique. - String get subject => this["sub"]; + String get subject => this['sub']; /// Identifies the recipients that the JWT is intended for. /// /// Each principal intended to process the JWT MUST identify itself with a /// value in the audience claim. If the principal processing the claim does - /// not identify itself with a value in the "aud" claim when this claim is + /// not identify itself with a value in the 'aud' claim when this claim is /// present, then the JWT MUST be rejected. - List get audience => getTypedList("aud"); + List get audience => getTypedList('aud'); /// Identifies the expiration time on or after which the JWT MUST NOT be /// accepted for processing. /// /// Implementers MAY provide for some small leeway, usually no more than a few /// minutes, to account for clock skew. - DateTime get expiry => getTyped("exp"); + DateTime get expiry => getTyped('exp'); /// Identifies the time before which the JWT MUST NOT be accepted for /// processing. /// /// Implementers MAY provide for some small leeway, usually no more than a few /// minutes, to account for clock skew. - DateTime get notBefore => getTyped("nbf"); + DateTime get notBefore => getTyped('nbf'); /// Identifies the time at which the JWT was issued. /// /// This claim can be used to determine the age of the JWT. - DateTime get issuedAt => getTyped("iat"); + DateTime get issuedAt => getTyped('iat'); /// Provides a unique identifier for the JWT. /// @@ -58,29 +58,28 @@ class JsonWebTokenClaims extends JsonObject { /// issuers, collisions MUST be prevented among values produced by different /// issuers as well. /// - /// The "jti" claim can be used to prevent the JWT from being replayed. - String get jwtId => this["jti"]; + /// The 'jti' claim can be used to prevent the JWT from being replayed. + String get jwtId => this['jti']; Iterable validate( - {Duration expiryTolerance: const Duration(), + {Duration expiryTolerance = const Duration(), Uri issuer, String clientId}) sync* { if (expiryTolerance != null) { - final now = new DateTime.now(); + final now = DateTime.now(); final diff = now.difference(expiry); if (diff > expiryTolerance) { - yield new JoseException( + yield JoseException( 'JWT expired. Expiry ($expiry) is more than tolerance ' '(${expiryTolerance}) before now ($now)'); } } if (issuer != null && this.issuer != issuer) { - yield new JoseException('Issuer does not match. Expected ' + yield JoseException('Issuer does not match. Expected ' '`${issuer}`, was `${this.issuer}`'); } - if (clientId != null && !this.audience.contains(clientId)) { - yield new JoseException( - 'Audiences does not contain clientId `$clientId`.'); + if (clientId != null && !audience.contains(clientId)) { + yield JoseException('Audiences does not contain clientId `$clientId`.'); } } } @@ -99,32 +98,31 @@ class JsonWebToken { JsonWebToken._fromJws(JsonWebSignature jws) : this._( jws, - new JsonWebTokenClaims.fromJson(jws.unverifiedPayload.jsonContent), + JsonWebTokenClaims.fromJson(jws.unverifiedPayload.jsonContent), null); /// Decodes a JWT string from a JWS compact serialization, without verifying /// the integrity JsonWebToken.unverified(String serialization) - : this._fromJws( - new JsonWebSignature.fromCompactSerialization(serialization)); + : this._fromJws(JsonWebSignature.fromCompactSerialization(serialization)); /// Decodes and verifies/decrypts a JWT string from a JWE or JWS compact /// serialization static Future decodeAndVerify( String serialization, JsonWebKeyStore keyStore, {List allowedArguments}) async { - var joseObject = new JoseObject.fromCompactSerialization(serialization); + var joseObject = JoseObject.fromCompactSerialization(serialization); var content = await joseObject.getPayload(keyStore, allowedAlgorithms: allowedArguments); var claims; - if (content.mediaType == "JWT") { + if (content.mediaType == 'JWT') { claims = (await decodeAndVerify(content.stringContent, keyStore, allowedArguments: allowedArguments)) .claims; } else { - claims = new JsonWebTokenClaims.fromJson(content.jsonContent); + claims = JsonWebTokenClaims.fromJson(content.jsonContent); } - return new JsonWebToken._(joseObject, claims, true); + return JsonWebToken._(joseObject, claims, true); } /// Serializes the [JsonWebToken] to a string diff --git a/lib/src/resource/io_html.dart b/lib/src/resource/io_html.dart index 1d1a2dc..c51b0f4 100644 --- a/lib/src/resource/io_html.dart +++ b/lib/src/resource/io_html.dart @@ -2,41 +2,41 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import "dart:async" show Future, Stream; -import "dart:convert" show Encoding; -import "dart:html"; -import "dart:typed_data" show ByteBuffer; +import 'dart:async' show Future, Stream; +import 'dart:convert' show Encoding; +import 'dart:html'; +import 'dart:typed_data' show ByteBuffer; /// Reads the bytes of a URI as a stream of bytes. Stream> readAsStream(Uri uri) async* { // TODO(lrn): Should file be run through XmlHTTPRequest too? - if (uri.scheme == "http" || uri.scheme == "https") { + if (uri.scheme == 'http' || uri.scheme == 'https') { // TODO: Stream in chunks if DOM has a way to do so. - List response = await _httpGetBytes(uri); + var response = await _httpGetBytes(uri); yield response; return; } - if (uri.scheme == "data") { + if (uri.scheme == 'data') { yield uri.data.contentAsBytes(); return; } - throw new UnsupportedError("Unsupported scheme: $uri"); + throw UnsupportedError('Unsupported scheme: $uri'); } /// Reads the bytes of a URI as a list of bytes. Future> readAsBytes(Uri uri) async { - if (uri.scheme == "http" || uri.scheme == "https") { + if (uri.scheme == 'http' || uri.scheme == 'https') { return _httpGetBytes(uri); } - if (uri.scheme == "data") { + if (uri.scheme == 'data') { return uri.data.contentAsBytes(); } - throw new UnsupportedError("Unsupported scheme: $uri"); + throw UnsupportedError('Unsupported scheme: $uri'); } /// Reads the bytes of a URI as a string. Future readAsString(Uri uri, Encoding encoding) async { - if (uri.scheme == "http" || uri.scheme == "https") { + if (uri.scheme == 'http' || uri.scheme == 'https') { // Fetch as string if the encoding is expected to be understood, // otherwise fetch as bytes and do decoding using the encoding. if (encoding != null) { @@ -44,14 +44,14 @@ Future readAsString(Uri uri, Encoding encoding) async { } return HttpRequest.getString(uri.toString()); } - if (uri.scheme == "data") { + if (uri.scheme == 'data') { return uri.data.contentAsString(encoding: encoding); } - throw new UnsupportedError("Unsupported scheme: $uri"); + throw UnsupportedError('Unsupported scheme: $uri'); } Future> _httpGetBytes(Uri uri) { - return HttpRequest.request(uri.toString(), responseType: "arraybuffer") + return HttpRequest.request(uri.toString(), responseType: 'arraybuffer') .then((request) { ByteBuffer data = request.response; return data.asUint8List(); diff --git a/lib/src/resource/io_io.dart b/lib/src/resource/io_io.dart index 818dafa..76826fc 100644 --- a/lib/src/resource/io_io.dart +++ b/lib/src/resource/io_io.dart @@ -2,111 +2,110 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import "dart:async" show Future, Stream; -import "dart:convert" show Encoding, latin1, utf8; -import "dart:io" +import 'dart:async' show Future, Stream; +import 'dart:convert' show Encoding, latin1, utf8; +import 'dart:io' show File, HttpStatus, HttpClient, HttpClientResponse, - HttpClientRequest, HttpException, HttpHeaders; -import "package:typed_data/typed_buffers.dart" show Uint8Buffer; +import 'package:typed_data/typed_buffers.dart' show Uint8Buffer; /// Read the bytes of a URI as a stream of bytes. Stream> readAsStream(Uri uri) async* { - if (uri.scheme == "file") { - yield* new File.fromUri(uri).openRead(); + if (uri.scheme == 'file') { + yield* File.fromUri(uri).openRead(); return; } - if (uri.scheme == "http" || uri.scheme == "https") { - HttpClientResponse response = await _httpGetBytes(uri); + if (uri.scheme == 'http' || uri.scheme == 'https') { + var response = await _httpGetBytes(uri); _throwIfFailed(response, uri); yield* response; return; } - if (uri.scheme == "data") { + if (uri.scheme == 'data') { yield uri.data.contentAsBytes(); return; } - throw new UnsupportedError("Unsupported scheme: $uri"); + throw UnsupportedError('Unsupported scheme: $uri'); } /// Read the bytes of a URI as a list of bytes. Future> readAsBytes(Uri uri) async { - if (uri.scheme == "file") { - return new File.fromUri(uri).readAsBytes(); + if (uri.scheme == 'file') { + return File.fromUri(uri).readAsBytes(); } - if (uri.scheme == "http" || uri.scheme == "https") { - HttpClientResponse response = await _httpGetBytes(uri); + if (uri.scheme == 'http' || uri.scheme == 'https') { + var response = await _httpGetBytes(uri); _throwIfFailed(response, uri); - int length = response.contentLength; + var length = response.contentLength; if (length < 0) length = 0; // Create empty buffer with capacity matching contentLength. - var buffer = new Uint8Buffer(length)..length = 0; + var buffer = Uint8Buffer(length)..length = 0; await for (var bytes in response) { buffer.addAll(bytes); } return buffer.toList(); } - if (uri.scheme == "data") { + if (uri.scheme == 'data') { return uri.data.contentAsBytes(); } - throw new UnsupportedError("Unsupported scheme: $uri"); + throw UnsupportedError('Unsupported scheme: $uri'); } /// Read the bytes of a URI as a string. Future readAsString(Uri uri, Encoding encoding) async { - if (uri.scheme == "file") { - if (encoding == null) encoding = utf8; - return new File.fromUri(uri).readAsString(encoding: encoding); + if (uri.scheme == 'file') { + encoding ??= utf8; + return File.fromUri(uri).readAsString(encoding: encoding); } - if (uri.scheme == "http" || uri.scheme == "https") { - HttpClientRequest request = await new HttpClient().getUrl(uri); + if (uri.scheme == 'http' || uri.scheme == 'https') { + var request = await HttpClient().getUrl(uri); // Prefer text/plain, text/* if possible, otherwise take whatever is there. - request.headers.set(HttpHeaders.acceptHeader, "text/plain, text/*, */*"); + request.headers.set(HttpHeaders.acceptHeader, 'text/plain, text/*, */*'); if (encoding != null) { request.headers.set(HttpHeaders.acceptCharsetHeader, encoding.name); } - HttpClientResponse response = await request.close(); + var response = await request.close(); _throwIfFailed(response, uri); encoding ??= Encoding.getByName(response.headers.contentType?.charset); if (encoding == null || encoding == latin1) { // Default to LATIN-1 if no encoding found. // Special case LATIN-1 since it is common and doesn't need decoding. - int length = response.contentLength; + var length = response.contentLength; if (length < 0) length = 0; // Create empty buffer with capacity matching contentLength. - var buffer = new Uint8Buffer(length)..length = 0; + var buffer = Uint8Buffer(length)..length = 0; await for (var bytes in response) { buffer.addAll(bytes); } var byteList = buffer.buffer.asUint8List(0, buffer.length); - return new String.fromCharCodes(byteList); + return String.fromCharCodes(byteList); } return response.transform(encoding.decoder).join(); } - if (uri.scheme == "data") { + if (uri.scheme == 'data') { return uri.data.contentAsString(encoding: encoding); } - throw new UnsupportedError("Unsupported scheme: $uri"); + throw UnsupportedError('Unsupported scheme: $uri'); } -HttpClient _sharedHttpClient = new HttpClient()..maxConnectionsPerHost = 6; +HttpClient _sharedHttpClient = HttpClient()..maxConnectionsPerHost = 6; Future _httpGetBytes(Uri uri) async { - HttpClientRequest request = await _sharedHttpClient.getUrl(uri); + var request = await _sharedHttpClient.getUrl(uri); request.headers - .set(HttpHeaders.acceptHeader, "application/octet-stream, */*"); + .set(HttpHeaders.acceptHeader, 'application/octet-stream, */*'); return request.close(); } void _throwIfFailed(HttpClientResponse response, Uri uri) { var statusCode = response.statusCode; if (statusCode < HttpStatus.ok || statusCode > HttpStatus.noContent) { - throw new HttpException(response.reasonPhrase, uri: uri); + throw HttpException(response.reasonPhrase, uri: uri); } } diff --git a/lib/src/resource/io_none.dart b/lib/src/resource/io_none.dart index 3c67eb6..db22297 100644 --- a/lib/src/resource/io_none.dart +++ b/lib/src/resource/io_none.dart @@ -2,30 +2,30 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import "dart:async" show Future, Stream; -import "dart:convert" show Encoding; +import 'dart:async' show Future, Stream; +import 'dart:convert' show Encoding; /// Read the bytes of a URI as a stream of bytes. Stream> readAsStream(Uri uri) async* { - if (uri.scheme == "data") { + if (uri.scheme == 'data') { yield uri.data.contentAsBytes(); return; } - throw new UnsupportedError("Unsupported scheme: $uri"); + throw UnsupportedError('Unsupported scheme: $uri'); } /// Read the bytes of a URI as a list of bytes. Future> readAsBytes(Uri uri) async { - if (uri.scheme == "data") { + if (uri.scheme == 'data') { return uri.data.contentAsBytes(); } - throw new UnsupportedError("Unsupported scheme: $uri"); + throw UnsupportedError('Unsupported scheme: $uri'); } /// Read the bytes of a URI as a string. Future readAsString(Uri uri, Encoding encoding) async { - if (uri.scheme == "data") { + if (uri.scheme == 'data') { return uri.data.contentAsString(encoding: encoding); } - throw new UnsupportedError("Unsupported scheme: $uri"); + throw UnsupportedError('Unsupported scheme: $uri'); } diff --git a/lib/src/resource/isolate_html.dart b/lib/src/resource/isolate_html.dart index b4dda2c..ef0032f 100644 --- a/lib/src/resource/isolate_html.dart +++ b/lib/src/resource/isolate_html.dart @@ -5,8 +5,8 @@ import 'dart:async'; Future resolveUri(Uri uri) { - if (uri.scheme == "package") { - uri = Uri.parse("packages/${uri.path}"); + if (uri.scheme == 'package') { + uri = Uri.parse('packages/${uri.path}'); } - return new Future.value(Uri.base.resolveUri(uri)); + return Future.value(Uri.base.resolveUri(uri)); } diff --git a/lib/src/resource/isolate_isolate.dart b/lib/src/resource/isolate_isolate.dart index 053899a..50cd642 100644 --- a/lib/src/resource/isolate_isolate.dart +++ b/lib/src/resource/isolate_isolate.dart @@ -2,18 +2,18 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import "dart:async" show Future; -import "dart:isolate" show Isolate; +import 'dart:async' show Future; +import 'dart:isolate' show Isolate; /// Helper function for resolving to a non-relative, non-package URI. Future resolveUri(Uri uri) { - if (uri.scheme == "package") { + if (uri.scheme == 'package') { return Isolate.resolvePackageUri(uri).then((resolvedUri) { if (resolvedUri == null) { - throw new ArgumentError.value(uri, "uri", "Unknown package"); + throw ArgumentError.value(uri, 'uri', 'Unknown package'); } return resolvedUri; }); } - return new Future.value(Uri.base.resolveUri(uri)); + return Future.value(Uri.base.resolveUri(uri)); } diff --git a/lib/src/resource/isolate_none.dart b/lib/src/resource/isolate_none.dart index fb7208e..0781aa7 100644 --- a/lib/src/resource/isolate_none.dart +++ b/lib/src/resource/isolate_none.dart @@ -5,8 +5,8 @@ import 'dart:async'; Future resolveUri(Uri uri) { - if (uri.scheme == "package") { - throw new UnsupportedError("Unsupported scheme: $uri"); + if (uri.scheme == 'package') { + throw UnsupportedError('Unsupported scheme: $uri'); } - return new Future.value(Uri.base.resolveUri(uri)); + return Future.value(Uri.base.resolveUri(uri)); } diff --git a/lib/src/resource/package_loader.dart b/lib/src/resource/package_loader.dart index 2e39d8c..1fce196 100644 --- a/lib/src/resource/package_loader.dart +++ b/lib/src/resource/package_loader.dart @@ -2,11 +2,11 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import "dart:async" show Future, Stream; -import "dart:convert" show Encoding; +import 'dart:async' show Future, Stream; +import 'dart:convert' show Encoding; -import "resolve.dart"; -import "resource_loader.dart"; +import 'resolve.dart'; +import 'resource_loader.dart'; /// Implementation of [ResourceLoader] that accepts relative and package: URIs. /// @@ -19,13 +19,16 @@ class PackageLoader implements ResourceLoader { final ResourceLoader _loader; const PackageLoader(ResourceLoader loader) : _loader = loader; + @override Stream> openRead(Uri uri) async* { yield* _loader.openRead(await resolveUri(uri)); } + @override Future> readAsBytes(Uri uri) async => _loader.readAsBytes(await resolveUri(uri)); + @override Future readAsString(Uri uri, {Encoding encoding}) async => _loader.readAsString(await resolveUri(uri), encoding: encoding); } diff --git a/lib/src/resource/resolve.dart b/lib/src/resource/resolve.dart index e873212..8610942 100644 --- a/lib/src/resource/resolve.dart +++ b/lib/src/resource/resolve.dart @@ -2,6 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -export "isolate_none.dart" - if (dart.library.html) "isolate_html.dart" - if (dart.library.isolate) "isolate_isolate.dart"; +export 'isolate_none.dart' + if (dart.library.html) 'isolate_html.dart' + if (dart.library.isolate) 'isolate_isolate.dart'; diff --git a/lib/src/resource/resource.dart b/lib/src/resource/resource.dart index d5c4208..83f8a77 100644 --- a/lib/src/resource/resource.dart +++ b/lib/src/resource/resource.dart @@ -2,11 +2,11 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import "dart:async" show Future, Stream; -import "dart:convert" show Encoding; +import 'dart:async' show Future, Stream; +import 'dart:convert' show Encoding; -import "resolve.dart"; -import "resource_loader.dart"; +import 'resolve.dart'; +import 'resource_loader.dart'; /// Base resource implementation. class Resource { @@ -55,13 +55,13 @@ class Resource { /// Reads the resource content as a stream of bytes. Stream> openRead() async* { - Uri uri = await resolveUri(this.uri); + var uri = await resolveUri(this.uri); yield* _loader.openRead(uri); } /// Reads the resource content as a single list of bytes. Future> readAsBytes() async { - Uri uri = await resolveUri(this.uri); + var uri = await resolveUri(this.uri); return _loader.readAsBytes(uri); } @@ -71,7 +71,7 @@ class Resource { /// If no encoding is provided, an encoding is chosen depending on the /// protocol and/or available metadata. Future readAsString({Encoding encoding}) async { - Uri uri = await resolveUri(this.uri); + var uri = await resolveUri(this.uri); return _loader.readAsString(uri, encoding: encoding); } } diff --git a/lib/src/resource/resource_loader.dart b/lib/src/resource/resource_loader.dart index 3f282e8..7b3ace9 100644 --- a/lib/src/resource/resource_loader.dart +++ b/lib/src/resource/resource_loader.dart @@ -2,13 +2,13 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import "dart:async" show Future, Stream; -import "dart:convert" show Encoding; +import 'dart:async' show Future, Stream; +import 'dart:convert' show Encoding; -import "io_none.dart" - if (dart.library.html) "io_html.dart" - if (dart.library.io) "io_io.dart" as io; -import "package_loader.dart"; +import 'io_none.dart' + if (dart.library.html) 'io_html.dart' + if (dart.library.io) 'io_io.dart' as io; +import 'package_loader.dart'; /// Resource loading strategy. /// @@ -31,7 +31,7 @@ abstract class ResourceLoader { /// This loader is automatically used by the [Resource] class /// if no other loader is specified. static ResourceLoader get defaultLoader => - const PackageLoader(const DefaultLoader()); + const PackageLoader(DefaultLoader()); /// Reads the file located by [uri] as a stream of bytes. Stream> openRead(Uri uri); @@ -61,10 +61,13 @@ abstract class ResourceLoader { class DefaultLoader implements ResourceLoader { const DefaultLoader(); + @override Stream> openRead(Uri uri) => io.readAsStream(uri); + @override Future> readAsBytes(Uri uri) => io.readAsBytes(uri); + @override Future readAsString(Uri uri, {Encoding encoding}) => io.readAsString(uri, encoding); } diff --git a/lib/src/util.dart b/lib/src/util.dart index 8a3acee..599b628 100644 --- a/lib/src/util.dart +++ b/lib/src/util.dart @@ -37,12 +37,13 @@ class JsonObject { toBase64EncodedString() == other.toBase64EncodedString(); static dynamic _clone(dynamic v) { - if (v is Map) - return new Map.unmodifiable( - new Map.fromIterables(v.keys, v.values.map(_clone))); - if (v is List) return new List.unmodifiable(v.map(_clone)); + if (v is Map) { + return Map.unmodifiable( + Map.fromIterables(v.keys, v.values.map(_clone))); + } + if (v is List) return List.unmodifiable(v.map(_clone)); if (v == null || v is num || v is bool || v is String) return v; - throw new ArgumentError.value(v, "Not a json value"); + throw ArgumentError.value(v, 'Not a json value'); } /// Returns the bytes representing the encoded JSON @@ -56,35 +57,35 @@ class JsonObject { dynamic operator [](String key) => _json[key]; /// Returns the property [key] as a typed object - T getTyped(String key, {T factory(dynamic v)}) { + T getTyped(String key, {T Function(dynamic v) factory}) { return _typedMap.putIfAbsent( key, () => _convert(this[key], factory: factory)); } /// Returns the property [key] as a typed list - List getTypedList(String key, {T factory(dynamic v)}) { + List getTypedList(String key, {T Function(dynamic v) factory}) { return _typedMap.putIfAbsent(key, () { var v = this[key]; if (v == null) return null; if (v is List) { - return new List.unmodifiable( + return List.unmodifiable( v.map((i) => _convert(i, factory: factory))); } - return new List.unmodifiable([_convert(v, factory: factory)]); + return List.unmodifiable([_convert(v, factory: factory)]); }); } final Map _typedMap = {}; - T _convert(dynamic v, {T factory(dynamic v)}) { + T _convert(dynamic v, {T Function(dynamic v) factory}) { if (v == null) return null; switch (T) { case Uri: return Uri.parse(v) as T; case DateTime: - return new DateTime.fromMillisecondsSinceEpoch(v * 1000) as T; + return DateTime.fromMillisecondsSinceEpoch(v * 1000) as T; case Duration: - return new Duration(seconds: v) as T; + return Duration(seconds: v) as T; case String: case num: case bool: @@ -102,10 +103,10 @@ List decodeBase64EncodedBytes(String encodedString) => encodedString == null ? null : convert.base64Url.decode(encodedString + - new List.filled((4 - encodedString.length % 4) % 4, "=").join()); + List.filled((4 - encodedString.length % 4) % 4, '=').join()); String encodeBase64EncodedBytes(List data) => - data == null ? null : convert.base64Url.encode(data).replaceAll("=", ""); + data == null ? null : convert.base64Url.encode(data).replaceAll('=', ''); Map safeUnion(Iterable> items) { var out = {}; @@ -113,7 +114,7 @@ Map safeUnion(Iterable> items) { if (i == null) continue; for (var k in out.keys.toSet().intersection(i.keys.toSet())) { if (out[k] != i[k]) { - throw new ArgumentError("Dublicate key `$k`"); + throw ArgumentError('Dublicate key `$k`'); } } out.addAll(i); diff --git a/pubspec.yaml b/pubspec.yaml index f1e3e8b..8792622 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: jose description: Javascript Object Signing and Encryption (JOSE) library supporting JWE, JWS, JWK and JWT -version: 0.1.2 +version: 0.1.2+1 author: Rik Bellens homepage: https://github.com/appsup-dart/jose @@ -14,4 +14,5 @@ dependencies: dev_dependencies: test: ^1.0.0 + pedantic: ^1.9.0 diff --git a/test/jose_test.dart b/test/jose_test.dart index 19cfcd9..ba0e6b9 100644 --- a/test/jose_test.dart +++ b/test/jose_test.dart @@ -3,7 +3,7 @@ import 'tests/jws_test.dart' as jws; import 'tests/jwe_test.dart' as jwe; import 'tests/jwt_test.dart' as jwt; -main() { +void main() { jwk.main(); jws.main(); jwe.main(); diff --git a/test/tests/jwe_test.dart b/test/tests/jwe_test.dart index f7a194a..a501aba 100644 --- a/test/tests/jwe_test.dart +++ b/test/tests/jwe_test.dart @@ -1,215 +1,212 @@ import 'package:test/test.dart'; import 'package:jose/src/jwe.dart'; import 'package:jose/src/jwk.dart'; -import 'package:jose/src/jose.dart'; -main() { +void main() { group('JWE Examples from RFC7516', () { group('Example JWE using RSAES-OAEP and AES GCM', () { _doTests( - "The true sign of intelligence is not knowledge but imagination.", - new JsonWebKey.fromJson({ - "kty": "RSA", - "n": "oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW" - "cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S" - "psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a" - "sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS" - "tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj" - "YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw", - "e": "AQAB", - "d": "kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N" - "WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9" - "3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk" - "qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl" - "t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd" - "VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ", - "p": "1r52Xk46c-LsfB5P442p7atdPUrxQSy4mti_tZI3Mgf2EuFVbUoDBvaRQ-" - "SWxkbkmoEzL7JXroSBjSrK3YIQgYdMgyAEPTPjXv_hI2_1eTSPVZfzL0lf" - "fNn03IXqWF5MDFuoUYE0hzb2vhrlN_rKrbfDIwUbTrjjgieRbwC6Cl0", - "q": "wLb35x7hmQWZsWJmB_vle87ihgZ19S8lBEROLIsZG4ayZVe9Hi9gDVCOBm" - "UDdaDYVTSNx_8Fyw1YYa9XGrGnDew00J28cRUoeBB_jKI1oma0Orv1T9aX" - "IWxKwd4gvxFImOWr3QRL9KEBRzk2RatUBnmDZJTIAfwTs0g68UZHvtc", - "dp": "ZK-YwE7diUh0qR1tR7w8WHtolDx3MZ_OTowiFvgfeQ3SiresXjm9gZ5KL" - "hMXvo-uz-KUJWDxS5pFQ_M0evdo1dKiRTjVw_x4NyqyXPM5nULPkcpU827" - "rnpZzAJKpdhWAgqrXGKAECQH0Xt4taznjnd_zVpAmZZq60WPMBMfKcuE", - "dq": "Dq0gfgJ1DdFGXiLvQEZnuKEN0UUmsJBxkjydc3j4ZYdBiMRAy86x0vHCj" - "ywcMlYYg4yoC4YZa9hNVcsjqA3FeiL19rk8g6Qn29Tt0cj8qqyFpz9vNDB" - "UfCAiJVeESOjJDZPYHdHY8v1b-o-Z2X5tvLx-TCekf7oxyeKDUqKWjis", - "qi": "VIMpMYbPf47dT1w_zDUXfPimsSegnMOA1zTaX7aGk_8urY6R8-ZW1FxU7" - "AlWAyLWybqq6t16VFd7hQd0y6flUK4SlOydB61gwanOsXGOAOv82cHq0E3" - "eL4HrtZkUuKvnPrMnsUUFlfUdybVzxyjz9JF_XyaY14ardLSjf4L_FNY" + 'The true sign of intelligence is not knowledge but imagination.', + JsonWebKey.fromJson({ + 'kty': 'RSA', + 'n': 'oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW' + 'cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S' + 'psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a' + 'sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS' + 'tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj' + 'YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw', + 'e': 'AQAB', + 'd': 'kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N' + 'WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9' + '3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk' + 'qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl' + 't3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd' + 'VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ', + 'p': '1r52Xk46c-LsfB5P442p7atdPUrxQSy4mti_tZI3Mgf2EuFVbUoDBvaRQ-' + 'SWxkbkmoEzL7JXroSBjSrK3YIQgYdMgyAEPTPjXv_hI2_1eTSPVZfzL0lf' + 'fNn03IXqWF5MDFuoUYE0hzb2vhrlN_rKrbfDIwUbTrjjgieRbwC6Cl0', + 'q': 'wLb35x7hmQWZsWJmB_vle87ihgZ19S8lBEROLIsZG4ayZVe9Hi9gDVCOBm' + 'UDdaDYVTSNx_8Fyw1YYa9XGrGnDew00J28cRUoeBB_jKI1oma0Orv1T9aX' + 'IWxKwd4gvxFImOWr3QRL9KEBRzk2RatUBnmDZJTIAfwTs0g68UZHvtc', + 'dp': 'ZK-YwE7diUh0qR1tR7w8WHtolDx3MZ_OTowiFvgfeQ3SiresXjm9gZ5KL' + 'hMXvo-uz-KUJWDxS5pFQ_M0evdo1dKiRTjVw_x4NyqyXPM5nULPkcpU827' + 'rnpZzAJKpdhWAgqrXGKAECQH0Xt4taznjnd_zVpAmZZq60WPMBMfKcuE', + 'dq': 'Dq0gfgJ1DdFGXiLvQEZnuKEN0UUmsJBxkjydc3j4ZYdBiMRAy86x0vHCj' + 'ywcMlYYg4yoC4YZa9hNVcsjqA3FeiL19rk8g6Qn29Tt0cj8qqyFpz9vNDB' + 'UfCAiJVeESOjJDZPYHdHY8v1b-o-Z2X5tvLx-TCekf7oxyeKDUqKWjis', + 'qi': 'VIMpMYbPf47dT1w_zDUXfPimsSegnMOA1zTaX7aGk_8urY6R8-ZW1FxU7' + 'AlWAyLWybqq6t16VFd7hQd0y6flUK4SlOydB61gwanOsXGOAOv82cHq0E3' + 'eL4HrtZkUuKvnPrMnsUUFlfUdybVzxyjz9JF_XyaY14ardLSjf4L_FNY' }), - "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ." - "OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe" - "ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb" - "Sv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaV" - "mqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8" - "1860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi" - "6UklfCpIMfIjf7iGdXKHzg." - "48V1_ALb6US04U3b." - "5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6ji" - "SdiwkIr3ajwQzaBtQD_A." - "XFBoMYUZodetZdvTiFvSkQ"); - }, skip: "OAEP not implemented"); + 'eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.' + 'OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe' + 'ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb' + 'Sv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaV' + 'mqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8' + '1860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi' + '6UklfCpIMfIjf7iGdXKHzg.' + '48V1_ALb6US04U3b.' + '5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6ji' + 'SdiwkIr3ajwQzaBtQD_A.' + 'XFBoMYUZodetZdvTiFvSkQ'); + }, skip: 'OAEP not implemented'); group('Example JWE using RSAES-PKCS1-v1_5 and AES_128_CBC_HMAC_SHA_256', () { _doTests( - "Live long and prosper.", - new JsonWebKey.fromJson( + 'Live long and prosper.', + JsonWebKey.fromJson( { - "kty": "RSA", - "n": "sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl" - "UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre" - "cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_" - "7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI" - "Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU" - "7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw", - "e": "AQAB", - "d": "VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq" - "1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry" - "nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_" - "0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj" - "-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj" - "T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ", - "p": "9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68" - "ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP" - "krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM", - "q": "uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y" - "BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN" - "-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0", - "dp": "w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv" - "ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra" - "Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs", - "dq": "o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff" - "7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_" - "odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU", - "qi": "eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC" - "tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ" - "B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo" + 'kty': 'RSA', + 'n': 'sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl' + 'UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre' + 'cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_' + '7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI' + 'Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU' + '7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw', + 'e': 'AQAB', + 'd': 'VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq' + '1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry' + 'nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_' + '0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj' + '-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj' + 'T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ', + 'p': '9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68' + 'ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP' + 'krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM', + 'q': 'uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y' + 'BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN' + '-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0', + 'dp': 'w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv' + 'ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra' + 'Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs', + 'dq': 'o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff' + '7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_' + 'odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU', + 'qi': 'eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC' + 'tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ' + 'B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo' }, ), - "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0." - "UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm" - "1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7Pc" - "HALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIF" - "NPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPhcCdZ6XDP0_F8" - "rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPgwCp6X-nZZd9OHBv" - "-B3oWh2TbqmScqXMR4gp_A." - "AxY8DCtDaGlsbGljb3RoZQ." - "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY." - "9hH0vgRfYgPnAHOd8stkvw"); + 'eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.' + 'UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm' + '1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7Pc' + 'HALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIF' + 'NPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPhcCdZ6XDP0_F8' + 'rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPgwCp6X-nZZd9OHBv' + '-B3oWh2TbqmScqXMR4gp_A.' + 'AxY8DCtDaGlsbGljb3RoZQ.' + 'KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.' + '9hH0vgRfYgPnAHOd8stkvw'); }); group('Example JWE Using AES Key Wrap and AES_128_CBC_HMAC_SHA_256', () { _doTests( - "Live long and prosper.", - new JsonWebKey.fromJson( - {"kty": "oct", "k": "GawgguFyGrWKav7AX4VKUg"}), - "eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0." - "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ." - "AxY8DCtDaGlsbGljb3RoZQ." - "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY." - "U0m_YmjN04DJvceFICbCVQ"); + 'Live long and prosper.', + JsonWebKey.fromJson({'kty': 'oct', 'k': 'GawgguFyGrWKav7AX4VKUg'}), + 'eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.' + '6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.' + 'AxY8DCtDaGlsbGljb3RoZQ.' + 'KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.' + 'U0m_YmjN04DJvceFICbCVQ'); }); group('Example JWE Using General JWE JSON Serialization', () { var keys = [ - new JsonWebKey.fromJson( + JsonWebKey.fromJson( { - "kty": "RSA", - "kid": "2011-04-29", - "n": "sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl" - "UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre" - "cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_" - "7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI" - "Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU" - "7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw", - "e": "AQAB", - "d": "VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq" - "1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry" - "nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_" - "0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj" - "-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj" - "T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ", - "p": "9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68" - "ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP" - "krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM", - "q": "uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y" - "BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN" - "-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0", - "dp": "w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv" - "ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra" - "Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs", - "dq": "o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff" - "7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_" - "odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU", - "qi": "eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC" - "tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ" - "B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo" + 'kty': 'RSA', + 'kid': '2011-04-29', + 'n': 'sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl' + 'UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre' + 'cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_' + '7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI' + 'Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU' + '7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw', + 'e': 'AQAB', + 'd': 'VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq' + '1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry' + 'nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_' + '0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj' + '-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj' + 'T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ', + 'p': '9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68' + 'ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP' + 'krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM', + 'q': 'uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y' + 'BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN' + '-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0', + 'dp': 'w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv' + 'ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra' + 'Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs', + 'dq': 'o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff' + '7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_' + 'odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU', + 'qi': 'eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC' + 'tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ' + 'B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo' }, ), - new JsonWebKey.fromJson( - {"kty": "oct", "k": "GawgguFyGrWKav7AX4VKUg", "kid": "7"}), + JsonWebKey.fromJson( + {'kty': 'oct', 'k': 'GawgguFyGrWKav7AX4VKUg', 'kid': '7'}), ]; - var plaintext = "Live long and prosper."; + var plaintext = 'Live long and prosper.'; var encoded = { - "protected": "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0", - "unprotected": {"jku": "https://server.example.com/keys.jwks"}, - "recipients": [ + 'protected': 'eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0', + 'unprotected': {'jku': 'https://server.example.com/keys.jwks'}, + 'recipients': [ { - "header": {"alg": "RSA1_5", "kid": "2011-04-29"}, - "encrypted_key": - "UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-" - "kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKx" - "GHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3" - "YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPh" - "cCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPg" - "wCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A" + 'header': {'alg': 'RSA1_5', 'kid': '2011-04-29'}, + 'encrypted_key': 'UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-' + 'kFm1NJn8LE9XShH59_i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKx' + 'GHZ7PcHALUzoOegEI-8E66jX2E4zyJKx-YxzZIItRzC5hlRirb6Y5Cl_p-ko3' + 'YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8OtvzlV7elprCbuPh' + 'cCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTP-cFPg' + 'wCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A' }, { - "header": {"alg": "A128KW", "kid": "7"}, - "encrypted_key": - "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ" + 'header': {'alg': 'A128KW', 'kid': '7'}, + 'encrypted_key': + '6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ' } ], - "iv": "AxY8DCtDaGlsbGljb3RoZQ", - "ciphertext": "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY", - "tag": "Mz-VPPyU4RlcuYv1IwIvzw" + 'iv': 'AxY8DCtDaGlsbGljb3RoZQ', + 'ciphertext': 'KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY', + 'tag': 'Mz-VPPyU4RlcuYv1IwIvzw' }; - group("Example JWE Using General JWE JSON Serialization: Recipient 1", + group('Example JWE Using General JWE JSON Serialization: Recipient 1', () { _doTests(plaintext, keys[0], encoded); }); - group("Example JWE Using General JWE JSON Serialization: Recipient 2", + group('Example JWE Using General JWE JSON Serialization: Recipient 2', () { _doTests(plaintext, keys[0], encoded); }); }); group('Example JWE Using Flattened JWE JSON Serialization', () { _doTests( - "Live long and prosper.", - new JsonWebKey.fromJson( - {"kty": "oct", "k": "GawgguFyGrWKav7AX4VKUg", "kid": "7"}), + 'Live long and prosper.', + JsonWebKey.fromJson( + {'kty': 'oct', 'k': 'GawgguFyGrWKav7AX4VKUg', 'kid': '7'}), { - "protected": "eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0", - "unprotected": {"jku": "https://server.example.com/keys.jwks"}, - "header": {"alg": "A128KW", "kid": "7"}, - "encrypted_key": - "6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ", - "iv": "AxY8DCtDaGlsbGljb3RoZQ", - "ciphertext": "KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY", - "tag": "Mz-VPPyU4RlcuYv1IwIvzw" + 'protected': 'eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0', + 'unprotected': {'jku': 'https://server.example.com/keys.jwks'}, + 'header': {'alg': 'A128KW', 'kid': '7'}, + 'encrypted_key': + '6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ', + 'iv': 'AxY8DCtDaGlsbGljb3RoZQ', + 'ciphertext': 'KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY', + 'tag': 'Mz-VPPyU4RlcuYv1IwIvzw' }); }); }); group('Special algorithms JWE', () { test('Key wrapping with `dir`', () async { - var payload = "I am disguised"; - var builder = new JsonWebEncryptionBuilder()..content = payload; + var payload = 'I am disguised'; + var builder = JsonWebEncryptionBuilder()..content = payload; - var key = new JsonWebKey.generate(builder.encryptionAlgorithm); - var keyStore = new JsonWebKeyStore()..addKey(key); + var key = JsonWebKey.generate(builder.encryptionAlgorithm); + var keyStore = JsonWebKeyStore()..addKey(key); - builder.addRecipient(key, algorithm: "dir"); + builder.addRecipient(key, algorithm: 'dir'); var jwe = builder.build(); jwe = JsonWebEncryption.fromCompactSerialization( @@ -220,16 +217,16 @@ main() { }); } -_doTests(dynamic payload, dynamic key, dynamic encoded) { +void _doTests(dynamic payload, dynamic key, dynamic encoded) { var jwe = encoded is String - ? new JsonWebEncryption.fromCompactSerialization(encoded) - : new JsonWebEncryption.fromJson(encoded); + ? JsonWebEncryption.fromCompactSerialization(encoded) + : JsonWebEncryption.fromJson(encoded); var keys = key is JsonWebKeySet ? key - : new JsonWebKeySet.fromKeys(key == null ? [] : [key]); - var context = new JsonWebKeyStore()..addKeySet(keys); + : JsonWebKeySet.fromKeys(key == null ? [] : [key]); + var context = JsonWebKeyStore()..addKeySet(keys); - _expectPayload(JsonWebEncryption jwe) async { + void _expectPayload(JsonWebEncryption jwe) async { var content = await jwe.getPayload(context); if (payload is String) { expect(content.stringContent, payload); @@ -241,16 +238,17 @@ _doTests(dynamic payload, dynamic key, dynamic encoded) { } test('decode', () { - if (encoded is String) + if (encoded is String) { expect(jwe.toCompactSerialization(), encoded); - else + } else { expect(jwe.toJson(), encoded); + } }); test('decrypt', () async { await _expectPayload(jwe); }); test('create', () async { - var builder = new JsonWebEncryptionBuilder() + var builder = JsonWebEncryptionBuilder() ..content = payload ..encryptionAlgorithm = jwe.commonHeader.encryptionAlgorithm ..additionalAuthenticatedData = jwe.additionalAuthenticatedData; @@ -259,7 +257,7 @@ _doTests(dynamic payload, dynamic key, dynamic encoded) { p.forEach((k, v) => builder.setProtectedHeader(k, v)); builder.encryptionAlgorithm = jwe.commonHeader.encryptionAlgorithm; if (keys.keys.isEmpty) { - builder.addRecipient(null, algorithm: "none"); + builder.addRecipient(null, algorithm: 'none'); } else { for (var key in keys.keys) { builder.addRecipient(key); diff --git a/test/tests/jwk_test.dart b/test/tests/jwk_test.dart index 4475fc9..82f5891 100644 --- a/test/tests/jwk_test.dart +++ b/test/tests/jwk_test.dart @@ -1,48 +1,48 @@ import 'package:jose/src/jwk.dart'; import 'package:test/test.dart'; -main() { +void main() { group('JWK Examples from RFC7517', () { group('Example JSON Web Key Sets', () { test('Example Public Keys', () { var json = { - "keys": [ + 'keys': [ { - "kty": "EC", - "crv": "P-256", - "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", - "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", - "use": "enc", - "kid": "1" + 'kty': 'EC', + 'crv': 'P-256', + 'x': 'MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4', + 'y': '4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM', + 'use': 'enc', + 'kid': '1' }, { - "kty": "RSA", - "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx" - "4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs" - "tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2" - "QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI" - "SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb" - "w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", - "e": "AQAB", - "alg": "RS256", - "kid": "2011-04-29" + 'kty': 'RSA', + 'n': '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx' + '4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs' + 'tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2' + 'QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI' + 'SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb' + 'w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw', + 'e': 'AQAB', + 'alg': 'RS256', + 'kid': '2011-04-29' } ] }; - var key1 = new JsonWebKey.fromJson(json["keys"][0]); + var key1 = JsonWebKey.fromJson(json['keys'][0]); - expect(key1.keyType, "EC"); - expect(key1.keyId, "1"); - expect(key1.publicKeyUse, "enc"); + expect(key1.keyType, 'EC'); + expect(key1.keyId, '1'); + expect(key1.publicKeyUse, 'enc'); - var key2 = new JsonWebKey.fromJson(json["keys"][1]); + var key2 = JsonWebKey.fromJson(json['keys'][1]); - expect(key2.keyType, "RSA"); - expect(key2.keyId, "2011-04-29"); - expect(key2.algorithm, "RS256"); + expect(key2.keyType, 'RSA'); + expect(key2.keyId, '2011-04-29'); + expect(key2.algorithm, 'RS256'); - var keySet = new JsonWebKeySet.fromJson(json); + var keySet = JsonWebKeySet.fromJson(json); expect(keySet.keys[0], key1); expect(keySet.keys[1], key2); @@ -52,65 +52,65 @@ main() { test('Example Private Keys', () { var json = { - "keys": [ + 'keys': [ { - "kty": "EC", - "crv": "P-256", - "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", - "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", - "d": "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE", - "use": "enc", - "kid": "1" + 'kty': 'EC', + 'crv': 'P-256', + 'x': 'MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4', + 'y': '4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM', + 'd': '870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE', + 'use': 'enc', + 'kid': '1' }, { - "kty": "RSA", - "n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4" - "cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMst" - "n64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2Q" - "vzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbIS" - "D08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw" - "0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw", - "e": "AQAB", - "d": "X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9" - "M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqij" - "wp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d" - "_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBz" - "nbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFz" - "me1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q", - "p": "83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPV" - "nwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqV" - "WlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs", - "q": "3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyum" - "qjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgx" - "kIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk", - "dp": "G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oim" - "YwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_Nmtu" - "YZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0", - "dq": "s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUU" - "vMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9" - "GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk", - "qi": "GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzg" - "UIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rx" - "yR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU", - "alg": "RS256", - "kid": "2011-04-29" + 'kty': 'RSA', + 'n': '0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4' + 'cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMst' + 'n64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2Q' + 'vzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbIS' + 'D08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw' + '0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw', + 'e': 'AQAB', + 'd': 'X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9' + 'M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqij' + 'wp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d' + '_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBz' + 'nbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFz' + 'me1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q', + 'p': '83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPV' + 'nwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqV' + 'WlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs', + 'q': '3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyum' + 'qjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgx' + 'kIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk', + 'dp': 'G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oim' + 'YwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_Nmtu' + 'YZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0', + 'dq': 's9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUU' + 'vMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9' + 'GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk', + 'qi': 'GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzg' + 'UIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rx' + 'yR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU', + 'alg': 'RS256', + 'kid': '2011-04-29' } ] }; - var key1 = new JsonWebKey.fromJson(json["keys"][0]); + var key1 = JsonWebKey.fromJson(json['keys'][0]); - expect(key1.keyType, "EC"); - expect(key1.keyId, "1"); - expect(key1.publicKeyUse, "enc"); + expect(key1.keyType, 'EC'); + expect(key1.keyId, '1'); + expect(key1.publicKeyUse, 'enc'); - var key2 = new JsonWebKey.fromJson(json["keys"][1]); + var key2 = JsonWebKey.fromJson(json['keys'][1]); - expect(key2.keyType, "RSA"); - expect(key2.keyId, "2011-04-29"); - expect(key2.algorithm, "RS256"); + expect(key2.keyType, 'RSA'); + expect(key2.keyId, '2011-04-29'); + expect(key2.algorithm, 'RS256'); - var keySet = new JsonWebKeySet.fromJson(json); + var keySet = JsonWebKeySet.fromJson(json); expect(keySet.keys[0], key1); expect(keySet.keys[1], key2); @@ -120,28 +120,28 @@ main() { test('Example Symmetric Keys', () { var json = { - "keys": [ - {"kty": "oct", "alg": "A128KW", "k": "GawgguFyGrWKav7AX4VKUg"}, + 'keys': [ + {'kty': 'oct', 'alg': 'A128KW', 'k': 'GawgguFyGrWKav7AX4VKUg'}, { - "kty": "oct", - "k": "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75" - "aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow", - "kid": "HMAC key used in JWS spec Appendix A.1 example" + 'kty': 'oct', + 'k': 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75' + 'aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow', + 'kid': 'HMAC key used in JWS spec Appendix A.1 example' } ] }; - var key1 = new JsonWebKey.fromJson(json["keys"][0]); + var key1 = JsonWebKey.fromJson(json['keys'][0]); - expect(key1.keyType, "oct"); - expect(key1.algorithm, "A128KW"); + expect(key1.keyType, 'oct'); + expect(key1.algorithm, 'A128KW'); - var key2 = new JsonWebKey.fromJson(json["keys"][1]); + var key2 = JsonWebKey.fromJson(json['keys'][1]); - expect(key2.keyType, "oct"); - expect(key2.keyId, "HMAC key used in JWS spec Appendix A.1 example"); + expect(key2.keyType, 'oct'); + expect(key2.keyId, 'HMAC key used in JWS spec Appendix A.1 example'); - var keySet = new JsonWebKeySet.fromJson(json); + var keySet = JsonWebKeySet.fromJson(json); expect(keySet.keys[0], key1); expect(keySet.keys[1], key2); @@ -150,46 +150,46 @@ main() { }); }); - test('Example Use of "x5c" (X.509 Certificate Chain) Parameter', () { + test("Example Use of 'x5c' (X.509 Certificate Chain) Parameter", () { var json = { - "kty": "RSA", - "use": "sig", - "kid": "1b94c", - "n": "vrjOfz9Ccdgx5nQudyhdoR17V-IubWMeOZCwX_jj0hgAsz2J_pqYW08" - "PLbK_PdiVGKPrqzmDIsLI7sA25VEnHU1uCLNwBuUiCO11_-7dYbsr4iJmG0Q" - "u2j8DsVyT1azpJC_NG84Ty5KKthuCaPod7iI7w0LK9orSMhBEwwZDCxTWq4a" - "YWAchc8t-emd9qOvWtVMDC2BXksRngh6X5bUYLy6AyHKvj-nUy1wgzjYQDwH" - "MTplCoLtU-o-8SNnZ1tmRoGE9uJkBLdh5gFENabWnU5m1ZqZPdwS-qo-meMv" - "VfJb6jJVWRpl2SUtCnYG2C32qvbWbjZ_jBPD5eunqsIo1vQ", - "e": "AQAB", - "x5c": [ - "MIIDQjCCAiqgAwIBAgIGATz/FuLiMA0GCSqGSIb3DQEBBQUAMGIxCzAJB" - "gNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYD" - "VQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1" - "wYmVsbDAeFw0xMzAyMjEyMzI5MTVaFw0xODA4MTQyMjI5MTVaMGIxCzAJBg" - "NVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDV" - "QQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1w" - "YmVsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64zn8/QnH" - "YMeZ0LncoXaEde1fiLm1jHjmQsF/449IYALM9if6amFtPDy2yvz3YlRij66" - "s5gyLCyO7ANuVRJx1NbgizcAblIgjtdf/u3WG7K+IiZhtELto/A7Fck9Ws6" - "SQvzRvOE8uSirYbgmj6He4iO8NCyvaK0jIQRMMGQwsU1quGmFgHIXPLfnpn" - "fajr1rVTAwtgV5LEZ4Iel+W1GC8ugMhyr4/p1MtcIM42EA8BzE6ZQqC7VPq" - "PvEjZ2dbZkaBhPbiZAS3YeYBRDWm1p1OZtWamT3cEvqqPpnjL1XyW+oyVVk" - "aZdklLQp2Btgt9qr21m42f4wTw+Xrp6rCKNb0CAwEAATANBgkqhkiG9w0BA" - "QUFAAOCAQEAh8zGlfSlcI0o3rYDPBB07aXNswb4ECNIKG0CETTUxmXl9KUL" - "+9gGlqCz5iWLOgWsnrcKcY0vXPG9J1r9AqBNTqNgHq2G03X09266X5CpOe1" - "zFo+Owb1zxtp3PehFdfQJ610CDLEaS9V9Rqp17hCyybEpOGVwe8fnk+fbEL" - "2Bo3UPGrpsHzUoaGpDftmWssZkhpBJKVMJyf/RuP2SmmaIzmnw9JiSlYhzo" - "4tpzd5rFXhjRbg4zW9C+2qok+2+qDM1iJ684gPHMIY8aLWrdgQTxkumGmTq" - "gawR+N5MDtdPTEQ0XfIBc2cJEUyMTY5MPvACWpkA6SdS4xSvdXK3IVfOWA==" + 'kty': 'RSA', + 'use': 'sig', + 'kid': '1b94c', + 'n': 'vrjOfz9Ccdgx5nQudyhdoR17V-IubWMeOZCwX_jj0hgAsz2J_pqYW08' + 'PLbK_PdiVGKPrqzmDIsLI7sA25VEnHU1uCLNwBuUiCO11_-7dYbsr4iJmG0Q' + 'u2j8DsVyT1azpJC_NG84Ty5KKthuCaPod7iI7w0LK9orSMhBEwwZDCxTWq4a' + 'YWAchc8t-emd9qOvWtVMDC2BXksRngh6X5bUYLy6AyHKvj-nUy1wgzjYQDwH' + 'MTplCoLtU-o-8SNnZ1tmRoGE9uJkBLdh5gFENabWnU5m1ZqZPdwS-qo-meMv' + 'VfJb6jJVWRpl2SUtCnYG2C32qvbWbjZ_jBPD5eunqsIo1vQ', + 'e': 'AQAB', + 'x5c': [ + 'MIIDQjCCAiqgAwIBAgIGATz/FuLiMA0GCSqGSIb3DQEBBQUAMGIxCzAJB' + 'gNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYD' + 'VQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1' + 'wYmVsbDAeFw0xMzAyMjEyMzI5MTVaFw0xODA4MTQyMjI5MTVaMGIxCzAJBg' + 'NVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDV' + 'QQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1w' + 'YmVsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64zn8/QnH' + 'YMeZ0LncoXaEde1fiLm1jHjmQsF/449IYALM9if6amFtPDy2yvz3YlRij66' + 's5gyLCyO7ANuVRJx1NbgizcAblIgjtdf/u3WG7K+IiZhtELto/A7Fck9Ws6' + 'SQvzRvOE8uSirYbgmj6He4iO8NCyvaK0jIQRMMGQwsU1quGmFgHIXPLfnpn' + 'fajr1rVTAwtgV5LEZ4Iel+W1GC8ugMhyr4/p1MtcIM42EA8BzE6ZQqC7VPq' + 'PvEjZ2dbZkaBhPbiZAS3YeYBRDWm1p1OZtWamT3cEvqqPpnjL1XyW+oyVVk' + 'aZdklLQp2Btgt9qr21m42f4wTw+Xrp6rCKNb0CAwEAATANBgkqhkiG9w0BA' + 'QUFAAOCAQEAh8zGlfSlcI0o3rYDPBB07aXNswb4ECNIKG0CETTUxmXl9KUL' + '+9gGlqCz5iWLOgWsnrcKcY0vXPG9J1r9AqBNTqNgHq2G03X09266X5CpOe1' + 'zFo+Owb1zxtp3PehFdfQJ610CDLEaS9V9Rqp17hCyybEpOGVwe8fnk+fbEL' + '2Bo3UPGrpsHzUoaGpDftmWssZkhpBJKVMJyf/RuP2SmmaIzmnw9JiSlYhzo' + '4tpzd5rFXhjRbg4zW9C+2qok+2+qDM1iJ684gPHMIY8aLWrdgQTxkumGmTq' + 'gawR+N5MDtdPTEQ0XfIBc2cJEUyMTY5MPvACWpkA6SdS4xSvdXK3IVfOWA==' ] }; - var key = new JsonWebKey.fromJson(json); + var key = JsonWebKey.fromJson(json); - expect(key.keyType, "RSA"); + expect(key.keyType, 'RSA'); expect(key.toJson(), json); - }, skip: "X.509 not implemented"); + }, skip: 'X.509 not implemented'); }); } diff --git a/test/tests/jws_test.dart b/test/tests/jws_test.dart index 46b936a..0a27c40 100644 --- a/test/tests/jws_test.dart +++ b/test/tests/jws_test.dart @@ -3,233 +3,232 @@ import 'package:jose/src/jws.dart'; import 'package:jose/src/jose.dart'; import 'package:test/test.dart'; -main() { +void main() { group('JWS Examples from RFC7515', () { group('Example JWS Using HMAC SHA-256', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - new JsonWebKey.fromJson({ - "kty": "oct", - "k": - "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow" + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, + JsonWebKey.fromJson({ + 'kty': 'oct', + 'k': + 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow' }), - "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"); + 'eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk'); }); group('Example JWS Using RSASSA-PKCS1-v1_5 SHA-256', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - new JsonWebKey.fromJson({ - "kty": "RSA", - "n": "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx" - "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs" - "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH" - "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV" - "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8" - "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ", - "e": "AQAB", - "d": "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I" - "jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0" - "BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn" - "439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT" - "CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh" - "BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ", - "p": "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi" - "YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG" - "BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc", - "q": "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa" - "ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA" - "-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc", - "dp": "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q" - "CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb" - "34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0", - "dq": "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa" - "7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky" - "NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU", - "qi": "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o" - "y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU" - "W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U" + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, + JsonWebKey.fromJson({ + 'kty': 'RSA', + 'n': 'ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx' + 'HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs' + 'D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH' + 'SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV' + 'MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8' + 'NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ', + 'e': 'AQAB', + 'd': 'Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I' + 'jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0' + 'BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn' + '439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT' + 'CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh' + 'BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ', + 'p': '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi' + 'YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG' + 'BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc', + 'q': 'uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa' + 'ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA' + '-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc', + 'dp': 'BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q' + 'CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb' + '34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0', + 'dq': 'h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa' + '7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky' + 'NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU', + 'qi': 'IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o' + 'y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU' + 'W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U' }), - "eyJhbGciOiJSUzI1NiJ9." - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt" - "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ." - "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7" - "AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4" - "BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K" - "0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv" - "hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB" - "p0igcN_IoypGlUPQGe77Rw"); + 'eyJhbGciOiJSUzI1NiJ9.' + 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt' + 'cGxlLmNvbS9pc19yb290Ijp0cnVlfQ.' + 'cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7' + 'AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4' + 'BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K' + '0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqv' + 'hJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrB' + 'p0igcN_IoypGlUPQGe77Rw'); }); group('Example JWS Using ECDSA P-256 SHA-256', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - new JsonWebKey.fromJson({ - "kty": "EC", - "crv": "P-256", - "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", - "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0", - "d": "jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI" + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, + JsonWebKey.fromJson({ + 'kty': 'EC', + 'crv': 'P-256', + 'x': 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU', + 'y': 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0', + 'd': 'jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI' }), - "eyJhbGciOiJFUzI1NiJ9." - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt" - "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ." - "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSA" - "pmWQxfKTUJqPP3-Kg6NU1Q"); + 'eyJhbGciOiJFUzI1NiJ9.' + 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt' + 'cGxlLmNvbS9pc19yb290Ijp0cnVlfQ.' + 'DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSA' + 'pmWQxfKTUJqPP3-Kg6NU1Q'); }); group('Example JWS Using ECDSA P-521 SHA-512', () { _doTests( - "Payload", - new JsonWebKey.fromJson({ - "kty": "EC", - "crv": "P-521", - "x": "AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_" - "NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk", - "y": "ADSmRA43Z1DSNx_RvcLI87cdL07l6jQyyBXMoxVg_l2Th-x3S1WDhjDl" - "y79ajL4Kkd0AZMaZmh9ubmf63e3kyMj2", - "d": "AY5pb7A0UFiB3RELSD64fTLOSV_jazdF7fLYyuTw8lOfRhWg6Y6rUrPA" - "xerEzgdRhajnu0ferB0d53vM9mE15j2C" + 'Payload', + JsonWebKey.fromJson({ + 'kty': 'EC', + 'crv': 'P-521', + 'x': 'AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_' + 'NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk', + 'y': 'ADSmRA43Z1DSNx_RvcLI87cdL07l6jQyyBXMoxVg_l2Th-x3S1WDhjDl' + 'y79ajL4Kkd0AZMaZmh9ubmf63e3kyMj2', + 'd': 'AY5pb7A0UFiB3RELSD64fTLOSV_jazdF7fLYyuTw8lOfRhWg6Y6rUrPA' + 'xerEzgdRhajnu0ferB0d53vM9mE15j2C' }), - "eyJhbGciOiJFUzUxMiJ9." - "UGF5bG9hZA." - "AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZq" - "wqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8Kp" - "EHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn"); + 'eyJhbGciOiJFUzUxMiJ9.' + 'UGF5bG9hZA.' + 'AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZq' + 'wqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8Kp' + 'EHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn'); }); group('Example Unsecured JWS', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, null, - "eyJhbGciOiJub25lIn0." - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt" - "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ.", - allowedAlgorithms: ["none"]); + 'eyJhbGciOiJub25lIn0.' + 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt' + 'cGxlLmNvbS9pc19yb290Ijp0cnVlfQ.', + allowedAlgorithms: ['none']); }); group('Example JWS Using General JWS JSON Serialization', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - new JsonWebKeySet.fromKeys([ - new JsonWebKey.fromJson({ - "kty": "RSA", - "kid": "2010-12-29", - "n": "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx" - "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs" - "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH" - "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV" - "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8" - "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ", - "e": "AQAB", - "d": "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I" - "jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0" - "BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn" - "439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT" - "CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh" - "BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ", - "p": "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi" - "YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG" - "BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc", - "q": "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa" - "ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA" - "-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc", - "dp": "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q" - "CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb" - "34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0", - "dq": "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa" - "7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky" - "NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU", - "qi": "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o" - "y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU" - "W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U" + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, + JsonWebKeySet.fromKeys([ + JsonWebKey.fromJson({ + 'kty': 'RSA', + 'kid': '2010-12-29', + 'n': 'ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx' + 'HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs' + 'D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH' + 'SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV' + 'MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8' + 'NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ', + 'e': 'AQAB', + 'd': 'Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I' + 'jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0' + 'BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn' + '439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT' + 'CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh' + 'BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ', + 'p': '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi' + 'YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG' + 'BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc', + 'q': 'uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa' + 'ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA' + '-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc', + 'dp': 'BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q' + 'CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb' + '34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0', + 'dq': 'h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa' + '7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky' + 'NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU', + 'qi': 'IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o' + 'y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU' + 'W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U' }), - new JsonWebKey.fromJson({ - "kid": "e9bc097a-ce51-4036-9562-d2ade882db0d", - "kty": "EC", - "crv": "P-256", - "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", - "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0", - "d": "jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI" + JsonWebKey.fromJson({ + 'kid': 'e9bc097a-ce51-4036-9562-d2ade882db0d', + 'kty': 'EC', + 'crv': 'P-256', + 'x': 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU', + 'y': 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0', + 'd': 'jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI' }), ]), { - "payload": - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF" - "tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ", - "signatures": [ + 'payload': + 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF' + 'tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ', + 'signatures': [ { - "protected": "eyJhbGciOiJSUzI1NiJ9", - "header": {"kid": "2010-12-29"}, - "signature": - "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ" - "mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb" - "KBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHl" - "b1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZES" - "c6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AX" - "LIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw" + 'protected': 'eyJhbGciOiJSUzI1NiJ9', + 'header': {'kid': '2010-12-29'}, + 'signature': 'cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ' + 'mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb' + 'KBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHl' + 'b1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZES' + 'c6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AX' + 'LIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw' }, { - "protected": "eyJhbGciOiJFUzI1NiJ9", - "header": {"kid": "e9bc097a-ce51-4036-9562-d2ade882db0d"}, - "signature": - "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS" - "lSApmWQxfKTUJqPP3-Kg6NU1Q" + 'protected': 'eyJhbGciOiJFUzI1NiJ9', + 'header': {'kid': 'e9bc097a-ce51-4036-9562-d2ade882db0d'}, + 'signature': + 'DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS' + 'lSApmWQxfKTUJqPP3-Kg6NU1Q' } ] }); }); group('Example JWS Using Flattened JWS JSON Serialization', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - new JsonWebKey.fromJson({ - "kid": "e9bc097a-ce51-4036-9562-d2ade882db0d", - "kty": "EC", - "crv": "P-256", - "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", - "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0", - "d": "jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI" + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, + JsonWebKey.fromJson({ + 'kid': 'e9bc097a-ce51-4036-9562-d2ade882db0d', + 'kty': 'EC', + 'crv': 'P-256', + 'x': 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU', + 'y': 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0', + 'd': 'jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI' }), { - "payload": - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF" - "tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ", - "protected": "eyJhbGciOiJFUzI1NiJ9", - "header": {"kid": "e9bc097a-ce51-4036-9562-d2ade882db0d"}, - "signature": - "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS" - "lSApmWQxfKTUJqPP3-Kg6NU1Q" + 'payload': + 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF' + 'tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ', + 'protected': 'eyJhbGciOiJFUzI1NiJ9', + 'header': {'kid': 'e9bc097a-ce51-4036-9562-d2ade882db0d'}, + 'signature': + 'DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS' + 'lSApmWQxfKTUJqPP3-Kg6NU1Q' }); }); }); group('Special algorithms JWS', () { test('Signing with `none`', () async { - var payload = "I am disguised"; - var builder = new JsonWebSignatureBuilder()..content = payload; + var payload = 'I am disguised'; + var builder = JsonWebSignatureBuilder()..content = payload; - builder.addRecipient(null, algorithm: "none"); + builder.addRecipient(null, algorithm: 'none'); var jws = builder.build(); - var keyStore = new JsonWebKeyStore(); + var keyStore = JsonWebKeyStore(); jws = JsonWebSignature.fromCompactSerialization( jws.toCompactSerialization()); expect(jws.getPayload(keyStore), throwsException); expect( - (await jws.getPayload(keyStore, allowedAlgorithms: ["none"])) + (await jws.getPayload(keyStore, allowedAlgorithms: ['none'])) .stringContent, payload); }); }); } -_doTests(dynamic payload, dynamic key, dynamic encoded, +void _doTests(dynamic payload, dynamic key, dynamic encoded, {List allowedAlgorithms}) { var jws = encoded is String - ? new JsonWebSignature.fromCompactSerialization(encoded) - : new JsonWebSignature.fromJson(encoded); + ? JsonWebSignature.fromCompactSerialization(encoded) + : JsonWebSignature.fromJson(encoded); var keys = key is JsonWebKeySet ? key - : new JsonWebKeySet.fromKeys(key == null ? [] : [key]); - var context = new JsonWebKeyStore()..addKeySet(keys); + : JsonWebKeySet.fromKeys(key == null ? [] : [key]); + var context = JsonWebKeyStore()..addKeySet(keys); - _expectPayload(JoseObject jose, {List allowedAlgorithms}) async { + void _expectPayload(JoseObject jose, {List allowedAlgorithms}) async { var content = await jose.getPayload(context, allowedAlgorithms: allowedAlgorithms); if (payload is String) { @@ -243,19 +242,20 @@ _doTests(dynamic payload, dynamic key, dynamic encoded, test('decode', () { _expectPayload(jws, allowedAlgorithms: allowedAlgorithms); - if (encoded is String) + if (encoded is String) { expect(jws.toCompactSerialization(), encoded); - else + } else { expect(jws.toJson(), encoded); + } }); test('verify', () async { await _expectPayload(jws, allowedAlgorithms: allowedAlgorithms); }); test('create', () async { - var builder = new JsonWebSignatureBuilder()..content = payload; + var builder = JsonWebSignatureBuilder()..content = payload; if (keys.keys.isEmpty) { - builder.addRecipient(null, algorithm: "none"); + builder.addRecipient(null, algorithm: 'none'); } else { for (var key in keys.keys) { builder.addRecipient(key); diff --git a/test/tests/jwt_test.dart b/test/tests/jwt_test.dart index bddb6f4..2b3ecc6 100644 --- a/test/tests/jwt_test.dart +++ b/test/tests/jwt_test.dart @@ -2,90 +2,90 @@ import 'package:test/test.dart'; import 'package:jose/src/jwt.dart'; import 'package:jose/src/jwk.dart'; -main() { +void main() { group('JWT Examples from RFC7519', () { - var context = new JsonWebKeyStore() - ..addKey(new JsonWebKey.fromJson({ - "kty": "oct", - "k": - "AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow" + var context = JsonWebKeyStore() + ..addKey(JsonWebKey.fromJson({ + 'kty': 'oct', + 'k': + 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow' })) - ..addKey(new JsonWebKey.fromJson( + ..addKey(JsonWebKey.fromJson( { - "kty": "RSA", - "n": "sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl" - "UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre" - "cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_" - "7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI" - "Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU" - "7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw", - "e": "AQAB", - "d": "VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq" - "1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry" - "nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_" - "0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj" - "-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj" - "T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ", - "p": "9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68" - "ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP" - "krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM", - "q": "uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y" - "BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN" - "-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0", - "dp": "w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv" - "ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra" - "Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs", - "dq": "o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff" - "7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_" - "odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU", - "qi": "eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC" - "tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ" - "B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo" + 'kty': 'RSA', + 'n': 'sXchDaQebHnPiGvyDOAT4saGEUetSyo9MKLOoWFsueri23bOdgWp4Dy1Wl' + 'UzewbgBHod5pcM9H95GQRV3JDXboIRROSBigeC5yjU1hGzHHyXss8UDpre' + 'cbAYxknTcQkhslANGRUZmdTOQ5qTRsLAt6BTYuyvVRdhS8exSZEy_c4gs_' + '7svlJJQ4H9_NxsiIoLwAEk7-Q3UXERGYw_75IDrGA84-lA_-Ct4eTlXHBI' + 'Y2EaV7t7LjJaynVJCpkv4LKjTTAumiGUIuQhrNhZLuF_RJLqHpM2kgWFLU' + '7-VTdL1VbC2tejvcI2BlMkEpk1BzBZI0KQB0GaDWFLN-aEAw3vRw', + 'e': 'AQAB', + 'd': 'VFCWOqXr8nvZNyaaJLXdnNPXZKRaWCjkU5Q2egQQpTBMwhprMzWzpR8Sxq' + '1OPThh_J6MUD8Z35wky9b8eEO0pwNS8xlh1lOFRRBoNqDIKVOku0aZb-ry' + 'nq8cxjDTLZQ6Fz7jSjR1Klop-YKaUHc9GsEofQqYruPhzSA-QgajZGPbE_' + '0ZaVDJHfyd7UUBUKunFMScbflYAAOYJqVIVwaYR5zWEEceUjNnTNo_CVSj' + '-VvXLO5VZfCUAVLgW4dpf1SrtZjSt34YLsRarSb127reG_DUwg9Ch-Kyvj' + 'T1SkHgUWRVGcyly7uvVGRSDwsXypdrNinPA4jlhoNdizK2zF2CWQ', + 'p': '9gY2w6I6S6L0juEKsbeDAwpd9WMfgqFoeA9vEyEUuk4kLwBKcoe1x4HG68' + 'ik918hdDSE9vDQSccA3xXHOAFOPJ8R9EeIAbTi1VwBYnbTp87X-xcPWlEP' + 'krdoUKW60tgs1aNd_Nnc9LEVVPMS390zbFxt8TN_biaBgelNgbC95sM', + 'q': 'uKlCKvKv_ZJMVcdIs5vVSU_6cPtYI1ljWytExV_skstvRSNi9r66jdd9-y' + 'BhVfuG4shsp2j7rGnIio901RBeHo6TPKWVVykPu1iYhQXw1jIABfw-MVsN' + '-3bQ76WLdt2SDxsHs7q7zPyUyHXmps7ycZ5c72wGkUwNOjYelmkiNS0', + 'dp': 'w0kZbV63cVRvVX6yk3C8cMxo2qCM4Y8nsq1lmMSYhG4EcL6FWbX5h9yuv' + 'ngs4iLEFk6eALoUS4vIWEwcL4txw9LsWH_zKI-hwoReoP77cOdSL4AVcra' + 'Hawlkpyd2TWjE5evgbhWtOxnZee3cXJBkAi64Ik6jZxbvk-RR3pEhnCs', + 'dq': 'o_8V14SezckO6CNLKs_btPdFiO9_kC1DsuUTd2LAfIIVeMZ7jn1Gus_Ff' + '7B7IVx3p5KuBGOVF8L-qifLb6nQnLysgHDh132NDioZkhH7mI7hPG-PYE_' + 'odApKdnqECHWw0J-F0JWnUd6D2B_1TvF9mXA2Qx-iGYn8OVV1Bsmp6qU', + 'qi': 'eNho5yRBEBxhGBtQRww9QirZsB66TrfFReG_CcteI1aCneT0ELGhYlRlC' + 'tUkTRclIfuEPmNsNDPbLoLqqCVznFbvdB7x-Tl-m0l_eFTj2KiqwGqE9PZ' + 'B9nNTwMVvH3VRRSLWACvPnSiwP8N5Usy-WRXS-V7TbpxIhvepTfE0NNo' }, )) - ..addKey(new JsonWebKey.fromJson({ - "kty": "RSA", - "n": "ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx" - "HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs" - "D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH" - "SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV" - "MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8" - "NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ", - "e": "AQAB", - "d": "Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I" - "jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0" - "BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn" - "439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT" - "CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh" - "BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ", - "p": "4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi" - "YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG" - "BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc", - "q": "uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa" - "ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA" - "-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc", - "dp": "BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q" - "CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb" - "34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0", - "dq": "h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa" - "7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky" - "NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU", - "qi": "IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o" - "y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU" - "W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U" + ..addKey(JsonWebKey.fromJson({ + 'kty': 'RSA', + 'n': 'ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddx' + 'HmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMs' + 'D1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSH' + 'SXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdV' + 'MTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8' + 'NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ', + 'e': 'AQAB', + 'd': 'Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97I' + 'jlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0' + 'BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn' + '439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYT' + 'CBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLh' + 'BOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ', + 'p': '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdi' + 'YrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPG' + 'BY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc', + 'q': 'uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxa' + 'ewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA' + '-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc', + 'dp': 'BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3Q' + 'CLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb' + '34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0', + 'dq': 'h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa' + '7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-ky' + 'NlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU', + 'qi': 'IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2o' + 'y26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLU' + 'W0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U' })); - _doTests(dynamic payload, dynamic encoded, [bool verify = true]) { + void _doTests(dynamic payload, dynamic encoded, [bool verify = true]) { test('decode', () async { var jwt = await JsonWebToken.decodeAndVerify(encoded, context, - allowedArguments: verify ? null : ["none"]); + allowedArguments: verify ? null : ['none']); expect(jwt.toCompactSerialization(), encoded); expect(jwt.claims.toJson(), payload); }); test('create', () { /* - var jws = new JsonWebSignature.unsigned(payload); + var jws = JsonWebSignature.unsigned(payload); for (var key in keys.keys) { jws = jws.sign(key); @@ -99,58 +99,58 @@ main() { group('Example JWT', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9." - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt" - "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ." - "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"); + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, + 'eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.' + 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt' + 'cGxlLmNvbS9pc19yb290Ijp0cnVlfQ.' + 'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk'); }); group('Example Unsecured JWT', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - "eyJhbGciOiJub25lIn0." - "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt" - "cGxlLmNvbS9pc19yb290Ijp0cnVlfQ.", + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, + 'eyJhbGciOiJub25lIn0.' + 'eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt' + 'cGxlLmNvbS9pc19yb290Ijp0cnVlfQ.', false); }); group('Example Encrypted JWT', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0." - "QR1Owv2ug2WyPBnbQrRARTeEk9kDO2w8qDcjiHnSJflSdv1iNqhWXaKH4MqAkQtM" - "oNfABIPJaZm0HaA415sv3aeuBWnD8J-Ui7Ah6cWafs3ZwwFKDFUUsWHSK-IPKxLG" - "TkND09XyjORj_CHAgOPJ-Sd8ONQRnJvWn_hXV1BNMHzUjPyYwEsRhDhzjAD26ima" - "sOTsgruobpYGoQcXUwFDn7moXPRfDE8-NoQX7N7ZYMmpUDkR-Cx9obNGwJQ3nM52" - "YCitxoQVPzjbl7WBuB7AohdBoZOdZ24WlN1lVIeh8v1K4krB8xgKvRU8kgFrEn_a" - "1rZgN5TiysnmzTROF869lQ." - "AxY8DCtDaGlsbGljb3RoZQ." - "MKOle7UQrG6nSxTLX6Mqwt0orbHvAKeWnDYvpIAeZ72deHxz3roJDXQyhxx0wKaM" - "HDjUEOKIwrtkHthpqEanSBNYHZgmNOV7sln1Eu9g3J8." - "fiK51VwhsxJ-siBMR-YFiA"); + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, + 'eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.' + 'QR1Owv2ug2WyPBnbQrRARTeEk9kDO2w8qDcjiHnSJflSdv1iNqhWXaKH4MqAkQtM' + 'oNfABIPJaZm0HaA415sv3aeuBWnD8J-Ui7Ah6cWafs3ZwwFKDFUUsWHSK-IPKxLG' + 'TkND09XyjORj_CHAgOPJ-Sd8ONQRnJvWn_hXV1BNMHzUjPyYwEsRhDhzjAD26ima' + 'sOTsgruobpYGoQcXUwFDn7moXPRfDE8-NoQX7N7ZYMmpUDkR-Cx9obNGwJQ3nM52' + 'YCitxoQVPzjbl7WBuB7AohdBoZOdZ24WlN1lVIeh8v1K4krB8xgKvRU8kgFrEn_a' + '1rZgN5TiysnmzTROF869lQ.' + 'AxY8DCtDaGlsbGljb3RoZQ.' + 'MKOle7UQrG6nSxTLX6Mqwt0orbHvAKeWnDYvpIAeZ72deHxz3roJDXQyhxx0wKaM' + 'HDjUEOKIwrtkHthpqEanSBNYHZgmNOV7sln1Eu9g3J8.' + 'fiK51VwhsxJ-siBMR-YFiA'); }); group('Example Nested JWT', () { _doTests( - {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - "eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiY3R5IjoiSldU" - "In0." - "g_hEwksO1Ax8Qn7HoN-BVeBoa8FXe0kpyk_XdcSmxvcM5_P296JXXtoHISr_DD_M" - "qewaQSH4dZOQHoUgKLeFly-9RI11TG-_Ge1bZFazBPwKC5lJ6OLANLMd0QSL4fYE" - "b9ERe-epKYE3xb2jfY1AltHqBO-PM6j23Guj2yDKnFv6WO72tteVzm_2n17SBFvh" - "DuR9a2nHTE67pe0XGBUS_TK7ecA-iVq5COeVdJR4U4VZGGlxRGPLRHvolVLEHx6D" - "YyLpw30Ay9R6d68YCLi9FYTq3hIXPK_-dmPlOUlKvPr1GgJzRoeC9G5qCvdcHWsq" - "JGTO_z3Wfo5zsqwkxruxwA." - "UmVkbW9uZCBXQSA5ODA1Mg." - "VwHERHPvCNcHHpTjkoigx3_ExK0Qc71RMEParpatm0X_qpg-w8kozSjfNIPPXiTB" - "BLXR65CIPkFqz4l1Ae9w_uowKiwyi9acgVztAi-pSL8GQSXnaamh9kX1mdh3M_TT" - "-FZGQFQsFhu0Z72gJKGdfGE-OE7hS1zuBD5oEUfk0Dmb0VzWEzpxxiSSBbBAzP10" - "l56pPfAtrjEYw-7ygeMkwBl6Z_mLS6w6xUgKlvW6ULmkV-uLC4FUiyKECK4e3WZY" - "Kw1bpgIqGYsw2v_grHjszJZ-_I5uM-9RA8ycX9KqPRp9gc6pXmoU_-27ATs9XCvr" - "ZXUtK2902AUzqpeEUJYjWWxSNsS-r1TJ1I-FMJ4XyAiGrfmo9hQPcNBYxPz3GQb2" - "8Y5CLSQfNgKSGt0A4isp1hBUXBHAndgtcslt7ZoQJaKe_nNJgNliWtWpJ_ebuOpE" - "l8jdhehdccnRMIwAmU1n7SPkmhIl1HlSOpvcvDfhUN5wuqU955vOBvfkBOh5A11U" - "zBuo2WlgZ6hYi9-e3w29bR0C2-pp3jbqxEDw3iWaf2dc5b-LnR0FEYXvI_tYk5rd" - "_J9N0mg0tQ6RbpxNEMNoA9QWk5lgdPvbh9BaO195abQ." - "AVO9iT5AV4CzvDJCdhSFlQ"); + {'iss': 'joe', 'exp': 1300819380, 'http://example.com/is_root': true}, + 'eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiY3R5IjoiSldU' + 'In0.' + 'g_hEwksO1Ax8Qn7HoN-BVeBoa8FXe0kpyk_XdcSmxvcM5_P296JXXtoHISr_DD_M' + 'qewaQSH4dZOQHoUgKLeFly-9RI11TG-_Ge1bZFazBPwKC5lJ6OLANLMd0QSL4fYE' + 'b9ERe-epKYE3xb2jfY1AltHqBO-PM6j23Guj2yDKnFv6WO72tteVzm_2n17SBFvh' + 'DuR9a2nHTE67pe0XGBUS_TK7ecA-iVq5COeVdJR4U4VZGGlxRGPLRHvolVLEHx6D' + 'YyLpw30Ay9R6d68YCLi9FYTq3hIXPK_-dmPlOUlKvPr1GgJzRoeC9G5qCvdcHWsq' + 'JGTO_z3Wfo5zsqwkxruxwA.' + 'UmVkbW9uZCBXQSA5ODA1Mg.' + 'VwHERHPvCNcHHpTjkoigx3_ExK0Qc71RMEParpatm0X_qpg-w8kozSjfNIPPXiTB' + 'BLXR65CIPkFqz4l1Ae9w_uowKiwyi9acgVztAi-pSL8GQSXnaamh9kX1mdh3M_TT' + '-FZGQFQsFhu0Z72gJKGdfGE-OE7hS1zuBD5oEUfk0Dmb0VzWEzpxxiSSBbBAzP10' + 'l56pPfAtrjEYw-7ygeMkwBl6Z_mLS6w6xUgKlvW6ULmkV-uLC4FUiyKECK4e3WZY' + 'Kw1bpgIqGYsw2v_grHjszJZ-_I5uM-9RA8ycX9KqPRp9gc6pXmoU_-27ATs9XCvr' + 'ZXUtK2902AUzqpeEUJYjWWxSNsS-r1TJ1I-FMJ4XyAiGrfmo9hQPcNBYxPz3GQb2' + '8Y5CLSQfNgKSGt0A4isp1hBUXBHAndgtcslt7ZoQJaKe_nNJgNliWtWpJ_ebuOpE' + 'l8jdhehdccnRMIwAmU1n7SPkmhIl1HlSOpvcvDfhUN5wuqU955vOBvfkBOh5A11U' + 'zBuo2WlgZ6hYi9-e3w29bR0C2-pp3jbqxEDw3iWaf2dc5b-LnR0FEYXvI_tYk5rd' + '_J9N0mg0tQ6RbpxNEMNoA9QWk5lgdPvbh9BaO195abQ.' + 'AVO9iT5AV4CzvDJCdhSFlQ'); }); }); }