Skip to content

Commit

Permalink
Update: Support RSAES-PKCS1-v1_5 key encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
linuxwolf authored Jul 22, 2016
2 parents b751879 + 1ddbfb4 commit 76ae28a
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 6 deletions.
3 changes: 3 additions & 0 deletions include/cjose/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ extern const char *CJOSE_HDR_KID;
/** The JWE algorithm attribute value for RSA-OAEP. */
extern const char *CJOSE_HDR_ALG_RSA_OAEP;

/** The JWE algorithm attribute value for RSA1_5. */
extern const char *CJOSE_HDR_ALG_RSA1_5;

/** The JWE algorithm attribute value for A128KW, A192KW and A256KW. */
extern const char *CJOSE_HDR_ALG_A128KW;
extern const char *CJOSE_HDR_ALG_A192KW;
Expand Down
1 change: 1 addition & 0 deletions src/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

const char *CJOSE_HDR_ALG = "alg";
const char *CJOSE_HDR_ALG_RSA_OAEP = "RSA-OAEP";
const char *CJOSE_HDR_ALG_RSA1_5 = "RSA1_5";
const char *CJOSE_HDR_ALG_A128KW = "A128KW";
const char *CJOSE_HDR_ALG_A192KW = "A192KW";
const char *CJOSE_HDR_ALG_A256KW = "A256KW";
Expand Down
69 changes: 63 additions & 6 deletions src/jwe.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ static bool _cjose_jwe_decrypt_ek_rsa_oaep(
const cjose_jwk_t *jwk,
cjose_err *err);

static bool _cjose_jwe_encrypt_ek_rsa1_5(
cjose_jwe_t *jwe,
const cjose_jwk_t *jwk,
cjose_err *err);

static bool _cjose_jwe_decrypt_ek_rsa1_5(
cjose_jwe_t *jwe,
const cjose_jwk_t *jwk,
cjose_err *err);

static bool _cjose_jwe_set_iv_a256gcm(
cjose_jwe_t *jwe,
cjose_err *err);
Expand Down Expand Up @@ -185,6 +195,11 @@ static bool _cjose_jwe_validate_hdr(
jwe->fns.encrypt_ek = _cjose_jwe_encrypt_ek_rsa_oaep;
jwe->fns.decrypt_ek = _cjose_jwe_decrypt_ek_rsa_oaep;
}
if (strcmp(alg, CJOSE_HDR_ALG_RSA1_5) == 0)
{
jwe->fns.encrypt_ek = _cjose_jwe_encrypt_ek_rsa1_5;
jwe->fns.decrypt_ek = _cjose_jwe_decrypt_ek_rsa1_5;
}
if (strcmp(alg, CJOSE_HDR_ALG_DIR) == 0)
{
jwe->fns.encrypt_ek = _cjose_jwe_encrypt_ek_dir;
Expand Down Expand Up @@ -434,9 +449,10 @@ static bool _cjose_jwe_decrypt_ek_aes_kw(


////////////////////////////////////////////////////////////////////////////////
static bool _cjose_jwe_encrypt_ek_rsa_oaep(
static bool _cjose_jwe_encrypt_ek_rsa_padding(
cjose_jwe_t *jwe,
const cjose_jwk_t *jwk,
int padding,
cjose_err *err)
{
// jwk must be RSA and have the necessary public parts set
Expand Down Expand Up @@ -472,9 +488,9 @@ static bool _cjose_jwe_encrypt_ek_rsa_oaep(
return false;
}

// encrypt the CEK using RSAES-OAEP
// encrypt the CEK using RSA v1.5 or OAEP padding
if (RSA_public_encrypt(jwe->cek_len, jwe->cek, jwe->part[1].raw,
(RSA *)jwk->keydata, RSA_PKCS1_OAEP_PADDING) !=
(RSA *)jwk->keydata, padding) !=
jwe->part[1].raw_len)
{
CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
Expand All @@ -486,9 +502,10 @@ static bool _cjose_jwe_encrypt_ek_rsa_oaep(


////////////////////////////////////////////////////////////////////////////////
static bool _cjose_jwe_decrypt_ek_rsa_oaep(
static bool _cjose_jwe_decrypt_ek_rsa_padding(
cjose_jwe_t *jwe,
const cjose_jwk_t *jwk,
int padding,
cjose_err *err)
{
if (NULL == jwe || NULL == jwk)
Expand All @@ -512,10 +529,10 @@ static bool _cjose_jwe_decrypt_ek_rsa_oaep(
return false;
}

// decrypt the CEK using RSAES-OAEP
// decrypt the CEK using RSA v1.5 or OAEP padding
jwe->cek_len = RSA_private_decrypt(
jwe->part[1].raw_len, jwe->part[1].raw, jwe->cek,
(RSA *)jwk->keydata, RSA_PKCS1_OAEP_PADDING);
(RSA *)jwk->keydata, padding);
if (-1 == jwe->cek_len)
{
CJOSE_ERROR(err, CJOSE_ERR_CRYPTO);
Expand All @@ -526,6 +543,46 @@ static bool _cjose_jwe_decrypt_ek_rsa_oaep(
}


////////////////////////////////////////////////////////////////////////////////
static bool _cjose_jwe_encrypt_ek_rsa_oaep(
cjose_jwe_t *jwe,
const cjose_jwk_t *jwk,
cjose_err *err)
{
return _cjose_jwe_encrypt_ek_rsa_padding(jwe, jwk, RSA_PKCS1_OAEP_PADDING ,err);
}


////////////////////////////////////////////////////////////////////////////////
static bool _cjose_jwe_decrypt_ek_rsa_oaep(
cjose_jwe_t *jwe,
const cjose_jwk_t *jwk,
cjose_err *err)
{
return _cjose_jwe_decrypt_ek_rsa_padding(jwe, jwk, RSA_PKCS1_OAEP_PADDING ,err);
}


////////////////////////////////////////////////////////////////////////////////
static bool _cjose_jwe_encrypt_ek_rsa1_5(
cjose_jwe_t *jwe,
const cjose_jwk_t *jwk,
cjose_err *err)
{
return _cjose_jwe_encrypt_ek_rsa_padding(jwe, jwk, RSA_PKCS1_PADDING ,err);
}


////////////////////////////////////////////////////////////////////////////////
static bool _cjose_jwe_decrypt_ek_rsa1_5(
cjose_jwe_t *jwe,
const cjose_jwk_t *jwk,
cjose_err *err)
{
return _cjose_jwe_decrypt_ek_rsa_padding(jwe, jwk, RSA_PKCS1_PADDING ,err);
}


////////////////////////////////////////////////////////////////////////////////
static bool _cjose_jwe_set_iv_a256gcm(
cjose_jwe_t *jwe,
Expand Down
146 changes: 146 additions & 0 deletions test/check_jwe.c
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,151 @@ START_TEST(test_cjose_jwe_decrypt_aes)
}
END_TEST

START_TEST(test_cjose_jwe_decrypt_rsa)
{
struct cjose_jwe_decrypt_rsa {
const char *jwe;
const char *plaintext;
const char *jwk;
};

static const struct cjose_jwe_decrypt_rsa JWE_RSA[] = {

// https://tools.ietf.org/html/rfc7516#appendix-A.1
// JWE using RSAES-OAEP and AES GCM
{ "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ."
"OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe"
"ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb"
"Sv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaV"
"mqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8"
"1860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi"
"6UklfCpIMfIjf7iGdXKHzg."
"48V1_ALb6US04U3b."
"5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6ji"
"SdiwkIr3ajwQzaBtQD_A."
"XFBoMYUZodetZdvTiFvSkQ",

"The true sign of intelligence is not knowledge but imagination.",

"{\"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\" }" },

// https://tools.ietf.org/html/rfc7516#appendix-A.2
// JWE using RSAES-PKCS1-v1_5 and AES_128_CBC_HMAC_SHA_256
{ "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",

"Live long and prosper.",

"{\"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\" }" },

{ NULL, NULL, NULL }
};

for (int i = 0; NULL != JWE_RSA[i].jwe; ++i)
{
cjose_err err;

// import the JWK
cjose_jwk_t *jwk = cjose_jwk_import(JWE_RSA[i].jwk, strlen(JWE_RSA[i].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);

// import the JWE
cjose_jwe_t *jwe = cjose_jwe_import(JWE_RSA[i].jwe, strlen(JWE_RSA[i].jwe), &err);
ck_assert_msg(NULL != jwe, "cjose_jwe_import failed: "
"%s, file: %s, function: %s, line: %ld",
err.message, err.file, err.function, err.line);

// decrypt the imported JWE
size_t plain1_len = 0;
uint8_t *plain1 = cjose_jwe_decrypt(jwe, jwk, &plain1_len, &err);
ck_assert_msg(
NULL != plain1,
"cjose_jwe_get_plaintext failed: "
"%s, file: %s, function: %s, line: %ld",
err.message, err.file, err.function, err.line);

// confirm plain == PLAINTEXT_S
ck_assert_msg(
plain1_len == strlen(JWE_RSA[i].plaintext),
"length of decrypted plaintext does not match length of original, "
"expected: %lu, found: %lu", strlen(JWE_RSA[i].plaintext), plain1_len);
ck_assert_msg(
strncmp(JWE_RSA[i].plaintext, plain1, plain1_len) == 0,
"decrypted plaintext does not match encrypted plaintext");

cjose_get_dealloc()(plain1);
cjose_jwe_release(jwe);
cjose_jwk_release(jwk);
}
}
END_TEST


Suite *cjose_jwe_suite()
{
Expand All @@ -748,6 +893,7 @@ Suite *cjose_jwe_suite()
tcase_add_test(tc_jwe, test_cjose_jwe_self_encrypt_self_decrypt_large);
tcase_add_test(tc_jwe, test_cjose_jwe_self_encrypt_self_decrypt_many);
tcase_add_test(tc_jwe, test_cjose_jwe_decrypt_aes);
tcase_add_test(tc_jwe, test_cjose_jwe_decrypt_rsa);
tcase_add_test(tc_jwe, test_cjose_jwe_encrypt_with_bad_header);
tcase_add_test(tc_jwe, test_cjose_jwe_encrypt_with_bad_key);
tcase_add_test(tc_jwe, test_cjose_jwe_encrypt_with_bad_content);
Expand Down

0 comments on commit 76ae28a

Please sign in to comment.