END_TEST START_TEST(test_cjose_jws_import_export_compare) { cjose_err err; // import the common key cjose_jwk_t *jwk = cjose_jwk_import(JWK_COMMON, strlen(JWK_COMMON), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // import the jws created with the common key cjose_jws_t *jws = cjose_jws_import(JWS_COMMON, strlen(JWS_COMMON), &err); ck_assert_msg(NULL != jws, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // re-export the jws object const char *cser = NULL; ck_assert_msg(cjose_jws_export(jws, &cser, &err), "re-export of imported JWS faied: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // compare the re-export to the original serialization ck_assert_msg(strncmp(JWS_COMMON, cser, strlen(JWS_COMMON)) == 0, "export of imported JWS doesn't match original"); cjose_jwk_release(jwk); cjose_jws_release(jws); }
/* * create an "oct" symmetric JWK */ oidc_jwk_t *oidc_jwk_create_symmetric_key(apr_pool_t *pool, const char *skid, const unsigned char *key, unsigned int key_len, apr_byte_t set_kid, oidc_jose_error_t *err) { cjose_err cjose_err; cjose_jwk_t *cjose_jwk = cjose_jwk_create_oct_spec(key, key_len, &cjose_err); if (cjose_jwk == NULL) { oidc_jose_error(err, "cjose_jwk_create_oct_spec failed: %s", oidc_cjose_e2s(pool, cjose_err)); return FALSE; } if (set_kid == TRUE) { if (oidc_jwk_set_or_generate_kid(pool, cjose_jwk, skid, (const char *) key, key_len, err) == FALSE) { cjose_jwk_release(cjose_jwk); return FALSE; } } oidc_jwk_t *jwk = oidc_jwk_new(pool); jwk->cjose_jwk = cjose_jwk; jwk->kid = apr_pstrdup(pool, cjose_jwk_get_kid(jwk->cjose_jwk, &cjose_err)); jwk->kty = cjose_jwk_get_kty(jwk->cjose_jwk, &cjose_err); return jwk; }
END_TEST START_TEST(test_cjose_jws_verify_rs384) { cjose_err err; static const char *JWS = "eyJhbGciOiJSUzM4NCIsImtpZCI6InhrdjNhIn0." "eyJzdWIiOiJqb2UiLCJhdWQiOiJhY19vaWNfY2xpZW50IiwianRpIjoiZmp1cXJDMGlmand0MTVjdEE3dWJEOCIsImlzcyI6Imh0d" "HBzOlwvXC9sb2NhbGhvc3Q6OTAzMSIsImlhdCI6MTQ2ODgyODIwNiwiZXhwIjoxNDY4ODI4NTA2LCJub25jZSI6ImpVSmZDeHZ0cG" "NhcDIxWjJBZ3F5ejRJUFVVVWZ3NElrM2JlVks5blpjSjQifQ.Ir1TaYIybDQxubPA1nRKUVaz4X2D6kMjWJpUzC_" "kYiBt8BzdINh5uiCNFXeI9LOVP-eSnwa0vlIg2ZcO1MNyiOQtcK71CKFfwA-1LUMrZtOEYkEQjO8YTAK_Bp1LUQ6QSm_" "jyibUBOHG0mXjdJimwh7Hu8WPOco4RcCXx-LgT55L5ewYReXPC4rNKTm3e3uvwkBs0KcL7CjgMlf6K9AbITwpIHxVFX4s6mlb-" "nlhXZ6pVapkREzvpLxC1JWQIN4Bf4KHv5tMKvjGGvMx-l3FTMQ1ZP-TkuzhN2ZdOE6LynqeNS9uo9qEa4zRM8HLD6-WM6e23y2ph_" "dHgNasVXa2bQ"; cjose_jws_t *jws = cjose_jws_import(JWS, strlen(JWS), &err); ck_assert_msg(NULL != jws, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *JWK = "{ \"kty\":\"RSA\"," "\"n\":\"u-kRzaNkYQXZWtfADCiOC_uGl1Fti_dolgzJgaZdOVpAE4zXbOgfJzm9wQK3IY7K1kFMD7p1bjamWXPOKgKKzqQwdLUOnq-" "zgTGga06wR1xGO4luEvRojsYp-eGlgpLCOW2uhzknh6s9JLsfcJ2vzz6LD9omgMY3-JSGS71ECR78yTXAxUnyeoUr_tlFDhDi31uAmXnyP_" "O89uqzGn2ZeVFdMPEpdaJCndpuW_zj6jDBFcOlkn6IC_O9UxQH9aEtctkaVdhB5Zw2mP5DWf81f8v8XfScrqn2IVtNcbBWPnHDcRSZPXx1vuN9T083w8_" "3wyb3YbTYlcRyvFN703FxsQ\"," "\"e\":\"AQAB\" }"; // import the key cjose_jwk_t *jwk = cjose_jwk_import(JWK, strlen(JWK), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // verify the deserialized JWS ck_assert_msg(cjose_jws_verify(jws, jwk, &err), "cjose_jws_verify failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // get the verified plaintext uint8_t *plain = NULL; size_t plain_len = 0; ck_assert_msg(cjose_jws_get_plaintext(jws, &plain, &plain_len, &err), "cjose_jws_get_plaintext failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *PLAINTEXT = "{\"sub\":\"joe\",\"aud\":\"ac_oic_client\",\"jti\":\"fjuqrC0ifjwt15ctA7ubD8\",\"iss\":\"https:\\/\\/" "localhost:9031\",\"iat\":1468828206,\"exp\":1468828506,\"nonce\":\"jUJfCxvtpcap21Z2Agqyz4IPUUUfw4Ik3beVK9nZcJ4\"}"; // confirm plain == PLAINTEXT ck_assert_msg(plain_len == strlen(PLAINTEXT), "length of verified plaintext does not match length of original, " "expected: %lu, found: %lu", strlen(PLAINTEXT), plain_len); ck_assert_msg(strncmp(PLAINTEXT, plain, plain_len) == 0, "verified plaintext does not match signed plaintext: %s", plain); cjose_jwk_release(jwk); cjose_jws_release(jws); }
/* * destroy resources allocated for a JWK struct */ void oidc_jwk_destroy(oidc_jwk_t *jwk) { if (jwk) { if (jwk->cjose_jwk) { cjose_jwk_release(jwk->cjose_jwk); jwk->cjose_jwk = NULL; } } }
END_TEST START_TEST(test_cjose_jws_verify_hs256) { cjose_err err; // https://tools.ietf.org/html/rfc7515#appendix-A.1 static const char *JWS = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9." "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ." "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"; cjose_jws_t *jws = cjose_jws_import(JWS, strlen(JWS), &err); ck_assert_msg(NULL != jws, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *JWK = "{ \"kty\": \"oct\", " "\"k\": \"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow\" }"; // import the key cjose_jwk_t *jwk = cjose_jwk_import(JWK, strlen(JWK), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // verify the deserialized JWS ck_assert_msg(cjose_jws_verify(jws, jwk, &err), "cjose_jws_verify failed"); // get the verified plaintext uint8_t *plain = NULL; size_t plain_len = 0; ck_assert_msg(cjose_jws_get_plaintext(jws, &plain, &plain_len, &err), "cjose_jws_get_plaintext failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *PLAINTEXT = "{\"iss\":\"joe\",\r\n" " \"exp\":1300819380,\r\n" " \"http://example.com/is_root\":true}"; // confirm plain == PLAINTEXT ck_assert_msg(plain_len == strlen(PLAINTEXT), "length of verified plaintext does not match length of original, " "expected: %lu, found: %lu", strlen(PLAINTEXT), plain_len); ck_assert_msg(strncmp(PLAINTEXT, plain, plain_len) == 0, "verified plaintext does not match signed plaintext: %s", plain); cjose_jwk_release(jwk); cjose_jws_release(jws); }
END_TEST START_TEST(test_cjose_jws_sign_with_bad_content) { cjose_err err; cjose_header_t *hdr = NULL; cjose_jws_t *jws = NULL; static const char *JWK = "{ \"kty\": \"RSA\", " "\"e\": \"AQAB\", " "\"n\": " "\"0a5nKJLjaB1xdebYWfhvlhYhgfzkw49HAUIjyvb6fNPKhwlBQMoAS5jM3kI17_OMGrHxL7ZP00OE-24__" "VWDCAhOQsSvlgCvw2XOOCtSWWLpb03dTrCMFeemqS4S9jrKd3NbUk3UJ2dVb_EIbQEC_BVjZStr_" "HcCrKsj4AluaQUn09H7TuK0yZFBzZMhJ1J8Yi3nAPkxzdGah0XuWhLObMAvANSVmHzRXwnTDw9Dh_" "bJ4G1xd1DE7W94uoUlcSDx59aSdzTpQzJh1l3lXc6JRUrXTESYgHpMv0O1n0gbIxX8X1ityBlMiccDjfZIKLnwz6hQObvRtRIpxEdq4SYS-w\", " "\"kid\": \"9ebf9edb-3a24-48b4-b2cb-21f0cf747ea7\", " "\"d\": " "\"B1vTivz8th6yaKzdUusBH4dPTbyOWr6gg07K6siYKeFU7kBI5fkw4XZPWk2AjxdBB37PNBl127g25owL-" "twRaSrBdF5quxzzDix4fEgo77Ik9x8IcUaI5AvpMW7Ig5O0n1SRE-" "ZfV7KssO0Imqq6bBZkEpzfgVC760tmSuqJ0W2on8eWzi36zuKru9qA5uo7L8w9I5rzqY7XEaak0PYFi5zB1BkpI83tN2bBP2jPsym9lMP4fbf-" "duHgu0s9H4mDeQFyb7OuI_P7AyH3V3qhUAvk37w-HNL-17g7OBYsZK5jMwa7LobO8Tw0ZdPk5u6dWKdmiWOUUScQVAqtaDjRIQ\" }"; // import the key cjose_jwk_t *jwk = cjose_jwk_import(JWK, strlen(JWK), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // set header for JWS hdr = cjose_header_new(&err); ck_assert_msg(cjose_header_set(hdr, CJOSE_HDR_ALG, CJOSE_HDR_ALG_PS256, &err), "cjose_header_set failed"); jws = cjose_jws_sign(jwk, hdr, NULL, 1024, &err); ck_assert_msg(NULL == jws, "cjose_jws_sign created with NULL plaintext"); ck_assert_msg(err.code == CJOSE_ERR_INVALID_ARG, "cjose_jws_sign returned bad err.code (%zu:%s)", err.code, err.message); jws = cjose_jws_sign(jwk, hdr, NULL, 0, &err); ck_assert_msg(NULL == jws, "cjose_jws_sign created with NULL plaintext"); ck_assert_msg(err.code == CJOSE_ERR_INVALID_ARG, "cjose_jws_sign returned bad err.code (%zu:%s)", err.code, err.message); cjose_jwk_release(jwk); cjose_header_release(hdr); }
END_TEST START_TEST(test_cjose_jws_sign_with_bad_header) { cjose_err err; cjose_header_t *hdr = NULL; cjose_jws_t *jws = NULL; static const char *plain = "The mind is everything. What you think you become."; size_t plain_len = strlen(plain); static const char *JWK = "{ \"kty\": \"RSA\", " "\"kid\": \"9ebf9edb-3a24-48b4-b2cb-21f0cf747ea7\", " "\"e\": \"AQAB\", " "\"n\": " "\"0a5nKJLjaB1xdebYWfhvlhYhgfzkw49HAUIjyvb6fNPKhwlBQMoAS5jM3kI17_OMGrHxL7ZP00OE-24__" "VWDCAhOQsSvlgCvw2XOOCtSWWLpb03dTrCMFeemqS4S9jrKd3NbUk3UJ2dVb_EIbQEC_BVjZStr_" "HcCrKsj4AluaQUn09H7TuK0yZFBzZMhJ1J8Yi3nAPkxzdGah0XuWhLObMAvANSVmHzRXwnTDw9Dh_" "bJ4G1xd1DE7W94uoUlcSDx59aSdzTpQzJh1l3lXc6JRUrXTESYgHpMv0O1n0gbIxX8X1ityBlMiccDjfZIKLnwz6hQObvRtRIpxEdq4SYS-w\" }"; cjose_jwk_t *jwk = cjose_jwk_import(JWK, strlen(JWK), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // set header for JWS with bad alg hdr = cjose_header_new(&err); ck_assert_msg(cjose_header_set(hdr, CJOSE_HDR_ALG, "Cayley-Purser", &err), "cjose_header_set failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // create a JWS jws = cjose_jws_sign(jwk, hdr, plain, plain_len, &err); ck_assert_msg(NULL == jws, "cjose_jws_sign created with bad header"); ck_assert_msg(err.code == CJOSE_ERR_INVALID_ARG, "cjose_jws_sign returned bad err.code (%zu:%s)", err.code, err.message); cjose_header_release(hdr); cjose_jwk_release(jwk); }
END_TEST START_TEST(test_cjose_jws_import_get_plain_after_verify) { cjose_err err; // import the common key cjose_jwk_t *jwk = cjose_jwk_import(JWK_COMMON, strlen(JWK_COMMON), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // import the jws created with the common key cjose_jws_t *jws = cjose_jws_import(JWS_COMMON, strlen(JWS_COMMON), &err); ck_assert_msg(NULL != jws, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // verify the imported jws ck_assert_msg(cjose_jws_verify(jws, jwk, &err), "cjose_jws_verify failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // get plaintext from imported and verified jws uint8_t *plaintext = NULL; size_t plaintext_len = 0; ck_assert_msg(cjose_jws_get_plaintext(jws, &plaintext, &plaintext_len, &err), "cjose_jws_get_plaintext failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // compare the verified plaintext to the expected value ck_assert_msg(strncmp(PLAIN_COMMON, plaintext, strlen(PLAIN_COMMON)) == 0, "verified plaintext from JWS doesn't match the original"); cjose_jws_release(jws); cjose_jwk_release(jwk); }
cjose_jwk_t *cjose_jwk_derive_ecdh_ephemeral_key( cjose_jwk_t *jwk_self, cjose_jwk_t *jwk_peer, cjose_err *err) { EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *pkey_self = NULL; EVP_PKEY *pkey_peer = NULL; uint8_t *secret = NULL; size_t secret_len = 0; uint8_t *ephemeral_key = NULL; size_t ephemeral_key_len = 0; cjose_jwk_t *jwk_ephemeral_key = NULL; // get EVP_KEY from jwk_self if (!_cjose_jwk_evp_key_from_ec_key(jwk_self, &pkey_self, err)) { goto _cjose_jwk_derive_shared_secret_fail; } // get EVP_KEY from jwk_peer if (!_cjose_jwk_evp_key_from_ec_key(jwk_peer, &pkey_peer, err)) { goto _cjose_jwk_derive_shared_secret_fail; } // create derivation context based on local key pair ctx = EVP_PKEY_CTX_new(pkey_self, NULL); if (NULL == ctx) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwk_derive_shared_secret_fail; } // initialize derivation context if (1 != EVP_PKEY_derive_init(ctx)) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwk_derive_shared_secret_fail; } // provide the peer public key if (1 != EVP_PKEY_derive_set_peer(ctx, pkey_peer)) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwk_derive_shared_secret_fail; } // determine buffer length for shared secret if(1 != EVP_PKEY_derive(ctx, NULL, &secret_len)) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwk_derive_shared_secret_fail; } // allocate buffer for shared secret secret = (uint8_t *)cjose_get_alloc()(secret_len); if (NULL == secret) { CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY); goto _cjose_jwk_derive_shared_secret_fail; } memset(secret, 0, secret_len); // derive the shared secret if (1 != (EVP_PKEY_derive(ctx, secret, &secret_len))) { CJOSE_ERROR(err, CJOSE_ERR_NO_MEMORY); goto _cjose_jwk_derive_shared_secret_fail; } // HKDF of the DH shared secret (SHA256, no salt, no info, 256 bit expand) ephemeral_key_len = 32; ephemeral_key = (uint8_t *)cjose_get_alloc()(ephemeral_key_len); if (!cjose_jwk_hkdf(EVP_sha256(), (uint8_t *)"", 0, (uint8_t *)"", 0, secret, secret_len, ephemeral_key, ephemeral_key_len, err)) { goto _cjose_jwk_derive_shared_secret_fail; } // create a JWK of the shared secret jwk_ephemeral_key = cjose_jwk_create_oct_spec( ephemeral_key, ephemeral_key_len, err); if (NULL == jwk_ephemeral_key) { goto _cjose_jwk_derive_shared_secret_fail; } // happy path EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey_self); EVP_PKEY_free(pkey_peer); cjose_get_dealloc()(secret); cjose_get_dealloc()(ephemeral_key); return jwk_ephemeral_key; // fail path _cjose_jwk_derive_shared_secret_fail: if (NULL != ctx) { EVP_PKEY_CTX_free(ctx); } if (NULL != pkey_self) { EVP_PKEY_free(pkey_self); } if (NULL != pkey_peer) { EVP_PKEY_free(pkey_peer); } if (NULL != jwk_ephemeral_key) { cjose_jwk_release(jwk_ephemeral_key); } cjose_get_dealloc()(secret); cjose_get_dealloc()(ephemeral_key); return NULL; }
cjose_jwk_t *cjose_jwk_import(const char *jwk_str, size_t len, cjose_err *err) { cjose_jwk_t *jwk= NULL; // check params if ((NULL == jwk_str) || (0 == len)) { return NULL; } // parse json content from the given string json_t *jwk_json = json_loadb(jwk_str, len, 0, NULL); if (NULL == jwk_json) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_cleanup; } // get the string value of the kty attribute of the jwk const char *kty_str = _get_json_object_string_attribute(jwk_json, CJOSE_JWK_KTY_STR, err); if (NULL == kty_str) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_cleanup; } // get kty corresponding to kty_str (kty is required) cjose_jwk_kty_t kty; if (!_kty_from_name(kty_str, &kty, err)) { CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_cleanup; } // create a cjose_jwt_t based on the kty switch (kty) { case CJOSE_JWK_KTY_EC: jwk = _cjose_jwk_import_EC(jwk_json, err); break; case CJOSE_JWK_KTY_RSA: jwk = _cjose_jwk_import_RSA(jwk_json, err); break; case CJOSE_JWK_KTY_OCT: jwk = _cjose_jwk_import_oct(jwk_json, err); break; default: CJOSE_ERROR(err, CJOSE_ERR_INVALID_ARG); goto import_cleanup; } if (NULL == jwk) { // helper function will have already set err goto import_cleanup; } // get the value of the kid attribute (kid is optional) const char *kid_str = _get_json_object_string_attribute(jwk_json, CJOSE_JWK_KID_STR, err); if (kid_str != NULL) { jwk->kid = _cjose_strndup(kid_str, -1, err); if (!jwk->kid) { cjose_jwk_release(jwk); jwk = NULL; goto import_cleanup; } } // poor man's "finally" import_cleanup: if (NULL != jwk_json) { json_decref(jwk_json); } return jwk; }
END_TEST START_TEST(test_cjose_jws_none) { cjose_err err; // https://tools.ietf.org/html/rfc7519#section-6.1 // Unsecured JWT (alg=none) static const char *JWS = "eyJhbGciOiJub25lIn0" ".eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" "."; cjose_jws_t *jws = cjose_jws_import(JWS, strlen(JWS), &err); ck_assert_msg(NULL != jws, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *JWK = "{ \"kty\": \"EC\"," "\"kid\": \"h4h93\"," "\"use\": \"sig\"," "\"x\": \"qcZ8jiBDygzf1XMWNN3jS7qT3DDslHOYvaa6XHMxShw\"," "\"y\": \"vMcP1OkZsSNaFN6MHrdApLdtLPWo8RnNflgP3DAbcfY\"," "\"crv\": \"P-256\" }"; // import the key cjose_jwk_t *jwk = cjose_jwk_import(JWK, strlen(JWK), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // get the plaintext uint8_t *plain = NULL; size_t plain_len = 0; ck_assert_msg(cjose_jws_get_plaintext(jws, &plain, &plain_len, &err), "cjose_jws_get_plaintext failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *PLAINTEXT = "{\"iss\":\"joe\",\r\n" " \"exp\":1300819380,\r\n" " \"http://example.com/is_root\":true}"; // confirm plain == PLAINTEXT ck_assert_msg(plain_len == strlen(PLAINTEXT), "length of verified plaintext does not match length of original, " "expected: %lu, found: %lu", strlen(PLAINTEXT), plain_len); ck_assert_msg(strncmp(PLAINTEXT, plain, plain_len) == 0, "verified plaintext does not match signed plaintext: %s", plain); // try to verify the unsecured JWS ck_assert_msg(!cjose_jws_verify(jws, jwk, &err), "cjose_jws_verify succeeded for unsecured JWT"); cjose_jws_release(jws); jws = cjose_jws_import(JWS, strlen(JWS), &err); ck_assert_msg(NULL != jws, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // try to sign the unsecured JWS ck_assert_msg(!cjose_jws_sign(jwk, (cjose_header_t *)jws->hdr, PLAINTEXT, strlen(PLAINTEXT), &err), "cjose_jws_sign succeeded for unsecured JWT"); cjose_jws_release(jws); cjose_jwk_release(jwk); }
static void _self_sign_self_verify(const char *plain1, const char *alg, cjose_err *err) { const char *s_jwk = _self_get_jwk_by_alg(alg); cjose_jwk_t *jwk = cjose_jwk_import(s_jwk, strlen(s_jwk), err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err->message, err->file, err->function, err->line); // set header for JWS cjose_header_t *hdr = cjose_header_new(err); ck_assert_msg(cjose_header_set(hdr, CJOSE_HDR_ALG, alg, err), "cjose_header_set failed: " "%s, file: %s, function: %s, line: %ld", err->message, err->file, err->function, err->line); // create the JWS size_t plain1_len = strlen(plain1); cjose_jws_t *jws1 = cjose_jws_sign(jwk, hdr, plain1, plain1_len, err); ck_assert_msg(NULL != jws1, "cjose_jws_sign failed: " "%s, file: %s, function: %s, line: %ld", err->message, err->file, err->function, err->line); ck_assert(hdr == cjose_jws_get_protected(jws1)); // get the compact serialization of JWS const char *compact = NULL; ck_assert_msg(cjose_jws_export(jws1, &compact, err), "cjose_jws_export failed: " "%s, file: %s, function: %s, line: %ld", err->message, err->file, err->function, err->line); // deserialize the compact representation to a new JWS cjose_jws_t *jws2 = cjose_jws_import(compact, strlen(compact), err); ck_assert_msg(NULL != jws2, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err->message, err->file, err->function, err->line); // verify the deserialized JWS ck_assert_msg(cjose_jws_verify(jws2, jwk, err), "cjose_jws_verify failed: " "%s, file: %s, function: %s, line: %ld", err->message, err->file, err->function, err->line); // get the verified plaintext uint8_t *plain2 = NULL; size_t plain2_len = 0; ck_assert_msg(cjose_jws_get_plaintext(jws2, &plain2, &plain2_len, err), "cjose_jws_get_plaintext failed: " "%s, file: %s, function: %s, line: %ld", err->message, err->file, err->function, err->line); // confirm equal headers ck_assert(json_equal((json_t *)cjose_jws_get_protected(jws1), (json_t *)cjose_jws_get_protected(jws2))); // confirm plain2 == plain1 ck_assert_msg(plain2_len == strlen(plain1), "length of verified plaintext does not match length of original, " "expected: %lu, found: %lu", strlen(plain1), plain2_len); ck_assert_msg(strncmp(plain1, plain2, plain2_len) == 0, "verified plaintext does not match signed plaintext"); cjose_header_release(hdr); cjose_jws_release(jws1); cjose_jws_release(jws2); cjose_jwk_release(jwk); }
END_TEST START_TEST(test_cjose_jws_verify_ec256) { cjose_err err; static const char *JWS = "eyJhbGciOiJFUzI1NiIsImtpZCI6Img0aDkzIn0." "eyJzdWIiOiJqb2UiLCJhdWQiOiJhY19vaWNfY2xpZW50IiwianRpIjoiZGV0blVpU2FTS0lpSUFvdHZ0ZzV3VyIsImlzcyI6Imh0d" "HBzOlwvXC9sb2NhbGhvc3Q6OTAzMSIsImlhdCI6MTQ2OTAzMDk1MCwiZXhwIjoxNDY5MDMxMjUwLCJub25jZSI6Im8zNU8wMi1WM0" "poSXJ1SkdHSlZVOGpUUGg2LUhKUTgzWEpmQXBZTGtrZHcifQ.o9bb_yW6-h9lPser01eYoK-VMlJoUabKFQ9tT_" "KdgMHlqRqTa4isqFqXllViDdUIQoHGMMP7Qms565YKSCS3iA"; cjose_jws_t *jws_ok = cjose_jws_import(JWS, strlen(JWS), &err); ck_assert_msg(NULL != jws_ok, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *JWK = "{ \"kty\": \"EC\"," "\"kid\": \"h4h93\"," "\"use\": \"sig\"," "\"x\": \"qcZ8jiBDygzf1XMWNN3jS7qT3DDslHOYvaa6XHMxShw\"," "\"y\": \"vMcP1OkZsSNaFN6MHrdApLdtLPWo8RnNflgP3DAbcfY\"," "\"crv\": \"P-256\" }"; // import the key cjose_jwk_t *jwk = cjose_jwk_import(JWK, strlen(JWK), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // verify the deserialized JWS ck_assert_msg(cjose_jws_verify(jws_ok, jwk, &err), "cjose_jws_verify failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // get the verified plaintext uint8_t *plain = NULL; size_t plain_len = 0; ck_assert_msg(cjose_jws_get_plaintext(jws_ok, &plain, &plain_len, &err), "cjose_jws_get_plaintext failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *PLAINTEXT = "{\"sub\":\"joe\",\"aud\":\"ac_oic_client\",\"jti\":\"detnUiSaSKIiIAotvtg5wW\",\"iss\":\"https:\\/\\/" "localhost:9031\",\"iat\":1469030950,\"exp\":1469031250,\"nonce\":\"o35O02-V3JhIruJGGJVU8jTPh6-HJQ83XJfApYLkkdw\"}"; // confirm plain == PLAINTEXT ck_assert_msg(plain_len == strlen(PLAINTEXT), "length of verified plaintext does not match length of original, " "expected: %lu, found: %lu", strlen(PLAINTEXT), plain_len); ck_assert_msg(strncmp(PLAINTEXT, plain, plain_len) == 0, "verified plaintext does not match signed plaintext: %s", plain); cjose_jws_release(jws_ok); static const char *JWS_TAMPERED_SIG = "eyJhbGciOiJFUzI1NiIsImtpZCI6Img0aDkzIn0." "eyJzdWIiOiJqb2UiLCJhdWQiOiJhY19vaWNfY2xpZW50IiwianRpIjoiZGV0blVpU2FTS0lpSUFvdHZ0ZzV3VyIs" "ImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhvc3Q6OTAzMSIsImlhdCI6MTQ2OTAzMDk1MCwiZXhwIjoxNDY5MDMxMjUw" "LCJub25jZSI6Im8zNU8wMi1WM0poSXJ1SkdHSlZVOGpUUGg2LUhKUTgzWEpmQXBZTGtrZHcifQ.o9bb_yW6-" "h9lPser01eYoK-VMlJoUabKFQ9tT_KdgMHlqRqTa4isqFqXllViDdUIQoHGMMP7Qms565YKSCS3ia"; cjose_jws_t *jws_ts = cjose_jws_import(JWS_TAMPERED_SIG, strlen(JWS_TAMPERED_SIG), &err); ck_assert_msg(NULL != jws_ts, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); ck_assert_msg(!cjose_jws_verify(jws_ts, jwk, &err), "cjose_jws_verify succeeded with tampered signature"); ck_assert_msg(err.code == CJOSE_ERR_CRYPTO, "cjose_jws_verify returned wrong err.code (%zu:%s)", err.code, err.message); cjose_jws_release(jws_ts); static const char *JWS_TAMPERED_CONTENT = "eyJhbGciOiJFUzI1NiIsImtpZCI6Img0aDkzIn0." "eyJzdWIiOiJqb2UiLCJhdWQiOiJhY19vaWNfY2xpZW50IiwianRpIjoiZGV0blVpU2FTS0lpSUFvdHZ0ZzV3VyIsImlzcyI6Imh0dHBzOlwvXC9sb2NhbGhv" "c3Q6OTAzMSIsImlhdCI6MTQ2OTAzMDk1MCwiZXhwIjoxNDY5MDMxMjUwLCJub25jZSI6Im8zNU8wMi1WM0poSXJ1SkdHSlZVOGpUUGG2LUhKUTgzWEpmQXBZ" "TGtrZHcifQ.o9bb_yW6-h9lPser01eYoK-VMlJoUabKFQ9tT_KdgMHlqRqTa4isqFqXllViDdUIQoHGMMP7Qms565YKSCS3iA"; cjose_jws_t *jws_tc = cjose_jws_import(JWS_TAMPERED_CONTENT, strlen(JWS_TAMPERED_CONTENT), &err); ck_assert_msg(NULL != jws_tc, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); ck_assert_msg(!cjose_jws_verify(jws_tc, jwk, &err), "cjose_jws_verify succeeded with tampered content"); ck_assert_msg(err.code == CJOSE_ERR_CRYPTO, "cjose_jws_verify returned wrong err.code (%zu:%s)", err.code, err.message); cjose_jws_release(jws_tc); cjose_jwk_release(jwk); }
END_TEST START_TEST(test_cjose_jws_verify_rs256) { cjose_err err; // https://tools.ietf.org/html/rfc7515#appendix-A.2 static const char *JWS = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ." "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_" "O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_" "eSN9383LcOLn6_dO--xi12jzDwusC-" "eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw"; cjose_jws_t *jws_ok = cjose_jws_import(JWS, strlen(JWS), &err); ck_assert_msg(NULL != jws_ok, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *JWK = "{ \"kty\":\"RSA\"," "\"n\":\"ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-" "pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-" "UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_" "h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ\"," "\"e\":\"AQAB\"," "\"d\":\"Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-" "pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_" "0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_" "RQyGWSeWjnczT0QU91p1DhOVRuOopznQ\"," "\"p\":\"4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw_" "Py5PJdTJNPY8cQn7ouZ2KKDcmnPGBY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc\"," "\"q\":\"uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-" "TnBA-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc\"," "\"dp\":\"BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3QCLdhrqE2e9YkxvuxdBfpT_PI7Yz-" "FOKnu1R6HsJeDCjn12Sk3vmAktV2zb34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0\"," "\"dq\":\"h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-" "NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU\"," "\"qi\":\"IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_" "QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U\" }"; // import the key cjose_jwk_t *jwk = cjose_jwk_import(JWK, strlen(JWK), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // verify the deserialized JWS ck_assert_msg(cjose_jws_verify(jws_ok, jwk, &err), "cjose_jws_verify failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // get the verified plaintext uint8_t *plain = NULL; size_t plain_len = 0; ck_assert_msg(cjose_jws_get_plaintext(jws_ok, &plain, &plain_len, &err), "cjose_jws_get_plaintext failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); static const char *PLAINTEXT = "{\"iss\":\"joe\",\r\n" " \"exp\":1300819380,\r\n" " \"http://example.com/is_root\":true}"; // confirm plain == PLAINTEXT ck_assert_msg(plain_len == strlen(PLAINTEXT), "length of verified plaintext does not match length of original, " "expected: %lu, found: %lu", strlen(PLAINTEXT), plain_len); ck_assert_msg(strncmp(PLAINTEXT, plain, plain_len) == 0, "verified plaintext does not match signed plaintext: %s", plain); cjose_jws_release(jws_ok); static const char *JWS_TAMPERED_SIG = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ." "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_" "O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_" "eSN9383LcOLn6_dO--xi12jzDwusC-" "eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77RW"; cjose_jws_t *jws_ts = cjose_jws_import(JWS_TAMPERED_SIG, strlen(JWS_TAMPERED_SIG), &err); ck_assert_msg(NULL != jws_ts, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); ck_assert_msg(!cjose_jws_verify(jws_ts, jwk, &err), "cjose_jws_verify succeeded with tampered signature"); ck_assert_msg(err.code == CJOSE_ERR_CRYPTO, "cjose_jws_verify returned wrong err.code (%zu:%s)", err.code, err.message); cjose_jws_release(jws_ts); static const char *JWS_TAMPERED_CONTENT = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfq." "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_" "O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_" "eSN9383LcOLn6_dO--xi12jzDwusC-" "eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw"; cjose_jws_t *jws_tc = cjose_jws_import(JWS_TAMPERED_CONTENT, strlen(JWS_TAMPERED_CONTENT), &err); ck_assert_msg(NULL != jws_tc, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); ck_assert_msg(!cjose_jws_verify(jws_tc, jwk, &err), "cjose_jws_verify succeeded with tampered content"); ck_assert_msg(err.code == CJOSE_ERR_CRYPTO, "cjose_jws_verify returned wrong err.code (%zu:%s)", err.code, err.message); cjose_jws_release(jws_tc); cjose_jwk_release(jwk); }
END_TEST START_TEST(test_cjose_jws_verify_bad_params) { cjose_err err; // some bad keys to test with static const char *JWK_BAD[] = { // missing private part 'd' needed for signion "{ \"kty\": \"RSA\", " "\"e\": \"AQAB\", " "\"n\": " "\"0a5nKJLjaB1xdebYWfhvlhYhgfzkw49HAUIjyvb6fNPKhwlBQMoAS5jM3kI17_OMGrHxL7ZP00OE-24__" "VWDCAhOQsSvlgCvw2XOOCtSWWLpb03dTrCMFeemqS4S9jrKd3NbUk3UJ2dVb_EIbQEC_BVjZStr_" "HcCrKsj4AluaQUn09H7TuK0yZFBzZMhJ1J8Yi3nAPkxzdGah0XuWhLObMAvANSVmHzRXwnTDw9Dh_" "bJ4G1xd1DE7W94uoUlcSDx59aSdzTpQzJh1l3lXc6JRUrXTESYgHpMv0O1n0gbIxX8X1ityBlMiccDjfZIKLnwz6hQObvRtRIpxEdq4SYS-w\", " "\"kid\": \"9ebf9edb-3a24-48b4-b2cb-21f0cf747ea7\" }", // currently unsupported key type (EC) "{ \"kty\": \"EC\", \"crv\": \"P-256\", " "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", " "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", " "\"kid\": \"4E34BAFD-E5D9-479C-964D-009C419C38DB\" }", NULL }; // import the common key cjose_jwk_t *jwk = cjose_jwk_import(JWK_COMMON, strlen(JWK_COMMON), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // import the jws created with the common key cjose_jws_t *jws = cjose_jws_import(JWS_COMMON, strlen(JWS_COMMON), &err); ck_assert_msg(NULL != jws, "cjose_jws_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // try to verify a NULL jws ck_assert_msg(!cjose_jws_verify(NULL, jwk, &err), "cjose_jws_verify succeeded with NULL jws"); ck_assert_msg(err.code == CJOSE_ERR_INVALID_ARG, "cjose_jws_verify returned wrong err.code (%zu:%s)", err.code, err.message); // try to verify with a NULL jwk ck_assert_msg(!cjose_jws_verify(jws, NULL, &err), "cjose_jws_verify succeeded with NULL jwk"); ck_assert_msg(err.code == CJOSE_ERR_INVALID_ARG, "cjose_jws_verify returned wrong err.code (%zu:%s)", err.code, err.message); // try to verify with bad/wrong/unsupported keys for (int i = 0; NULL != JWK_BAD[i]; ++i) { cjose_jwk_t *jwk_bad = cjose_jwk_import(JWK_BAD[i], strlen(JWK_BAD[i]), &err); ck_assert_msg(NULL != jwk_bad, "cjose_jwk_import failed"); ck_assert_msg(!cjose_jws_verify(jws, NULL, &err), "cjose_jws_verify succeeded with bad jwk"); ck_assert_msg(err.code == CJOSE_ERR_INVALID_ARG, "cjose_jws_verify returned wrong err.code (%zu:%s)", err.code, err.message); cjose_jwk_release(jwk_bad); } cjose_jws_release(jws); cjose_jwk_release(jwk); }
END_TEST START_TEST(test_cjose_jws_sign_with_bad_key) { cjose_err err; cjose_header_t *hdr = NULL; cjose_jws_t *jws = NULL; static const char *plain = "The mind is everything. What you think you become."; size_t plain_len = strlen(plain); // some bad keys to test with static const char *JWK_BAD[] = { // missing private part 'd' needed for signing "{ \"kty\": \"RSA\", " "\"kid\": \"9ebf9edb-3a24-48b4-b2cb-21f0cf747ea7\", " "\"e\": \"AQAB\", " "\"n\": " "\"0a5nKJLjaB1xdebYWfhvlhYhgfzkw49HAUIjyvb6fNPKhwlBQMoAS5jM3kI17_OMGrHxL7ZP00OE-24__" "VWDCAhOQsSvlgCvw2XOOCtSWWLpb03dTrCMFeemqS4S9jrKd3NbUk3UJ2dVb_EIbQEC_BVjZStr_" "HcCrKsj4AluaQUn09H7TuK0yZFBzZMhJ1J8Yi3nAPkxzdGah0XuWhLObMAvANSVmHzRXwnTDw9Dh_" "bJ4G1xd1DE7W94uoUlcSDx59aSdzTpQzJh1l3lXc6JRUrXTESYgHpMv0O1n0gbIxX8X1ityBlMiccDjfZIKLnwz6hQObvRtRIpxEdq4SYS-w\" }", // currently unsupported key type (EC) "{ \"kty\": \"EC\", \"crv\": \"P-256\", " "\"x\": \"VoFkf6Wk5kDQ1ob6csBmiMPHU8jALwdtaap35Fsj20M\", " "\"y\": \"XymwN6u2PmsKbIPy5iij6qZ-mIyej5dvZWB_75lnRgQ\", " "\"kid\": \"4E34BAFD-E5D9-479C-964D-009C419C38DB\" }", NULL }; // set header for JWS hdr = cjose_header_new(&err); ck_assert_msg(cjose_header_set(hdr, CJOSE_HDR_ALG, CJOSE_HDR_ALG_PS256, &err), "cjose_header_set failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); // attempt signion with each bad key for (int i = 0; NULL != JWK_BAD[i]; ++i) { cjose_jwk_t *jwk = cjose_jwk_import(JWK_BAD[i], strlen(JWK_BAD[i]), &err); ck_assert_msg(NULL != jwk, "cjose_jwk_import failed: " "%s, file: %s, function: %s, line: %ld", err.message, err.file, err.function, err.line); jws = cjose_jws_sign(jwk, hdr, plain, plain_len, &err); ck_assert_msg(NULL == jws, "cjose_jws_sign created with bad key"); ck_assert_msg(err.code == CJOSE_ERR_INVALID_ARG, "%d cjose_jws_sign returned bad err.code (%zu:%s)", i, err.code, err.message); cjose_jwk_release(jwk); } jws = cjose_jws_sign(NULL, hdr, plain, plain_len, &err); ck_assert_msg(NULL == jws, "cjose_jws_sign created with bad key"); ck_assert_msg(err.code == CJOSE_ERR_INVALID_ARG, "cjose_jws_sign returned bad err.code (%zu:%s)", err.code, err.message); cjose_header_release(hdr); }