Wednesday, March 02, 2011

RSA Encrypting JSON



After I implemented the current draft to sign JSON: "JSON Web Token (JWT) - Claims and Signing" I implemented some simple JSON encryption.

This works by generating a ephemeral symmetric key with a specified keylength (128, 192, 256 bits) that is encrypted using the recipient's public RSA key. The ephemeral symmetric key is used to encrypt the payload using AES in CBC-mode with PKCS7 padding.
Depending on the key length the algorithms are called RE128, RE192 and RE256.

The following is an example of a JSON object that can be encoded to produce a JWT Claims Object:

{"iss":"joe",
"exp":1300819380,
"http://example.com/is_root":true}


The following example JSON header object declares that the encoded object is a JSON Web Token (JWT) and that the JWT Payload Segment is encrypted using the RE256 algorithm and that the RSA public key has the thumbprint of b9E8JDWjYefFiM0X9V9a098Bd6ZsFyemogCEX016uIw:

{"typ":"JWT",
"alg":"RE256",
"x5t":"b9E8JDWjYefFiM0X9V9a098Bd6ZsFyemogCEX016uIw"}


Base64url encoding the JSON header yields the following JWT header segment:
eyJhbGciOiJSRTI1NiIsDQogIng1dCI6ImI5RThKRFdqWWVmRmlNMFg5VjlhMDk4QmQ2WnNGeWVtb2dDRVgwMTZ1SXcifQ

The following byte array contains the UTF-8 characters for an example ephemeral key:
[27, 24, 24, 78, 51, -38, -111, -13, -53, -4, -13, -84, 34, -59, 96, 20, -23, 87, -26, -56, -116, -35, 127, -21, -97, -26, -71, 74, -36, -67, -124, -45]

The RSA key consists of a public part (n, e), and a private exponent d. The values of the RSA key used in this example, presented as the byte arrays representing big endian integers are:
Parameter NameValue
n[161, 248, 22, 10, 226, 227, 201, 180, 101, 206, 141, 45, 101, 98, 99, 54, 43, 146, 125, 190, 41, 225, 240, 36, 119, 252, 22, 37, 204, 144, 161, 54, 227, 139, 217, 52, 151, 197, 182, 234, 99, 221, 119, 17, 230, 124, 116, 41, 249, 86, 176, 251, 138, 143, 8, 154, 220, 75, 105, 137, 60, 193, 51, 63, 83, 237, 208, 25, 184, 119, 132, 37, 47, 236, 145, 79, 228, 133, 119, 105, 89, 75, 234, 66, 128, 211, 44, 15, 85, 191, 98, 148, 79, 19, 3, 150, 188, 110, 155, 223, 110, 189, 210, 189, 163, 103, 142, 236, 160, 198, 104, 247, 1, 179, 141, 191, 251, 56, 200, 52, 44, 226, 254, 109, 39, 250, 222, 74, 90, 72, 116, 151, 157, 212, 185, 207, 154, 222, 196, 199, 91, 5, 133, 44, 44, 15, 94, 248, 165, 193, 117, 3, 146, 249, 68, 232, 237, 100, 193, 16, 198, 182, 71, 96, 154, 164, 120, 58, 235, 156, 108, 154, 215, 85, 49, 48, 80, 99, 139, 131, 102, 92, 111, 111, 122, 130, 163, 150, 112, 42, 31, 100, 27, 130, 211, 235, 242, 57, 34, 25, 73, 31, 182, 134, 135, 44, 87, 22, 245, 10, 248, 53, 141, 154, 139, 157, 23, 195, 64, 114, 143, 127, 135, 216, 154, 24, 216, 252, 171, 103, 173, 132, 89, 12, 46, 207, 117, 147, 57, 54, 60, 7, 3, 77, 111, 96, 111, 158, 33, 224, 84, 86, 202, 229, 233, 161]
e[1, 0, 1]
d[18, 174, 113, 164, 105, 205, 10, 43, 195, 126, 82, 108, 69, 0, 87, 31, 29, 97, 117, 29, 100, 233, 73, 112, 123, 98, 89, 15, 157, 11, 165, 124, 150, 60, 64, 30, 63, 207, 47, 44, 211, 189, 236, 136, 229, 3, 191, 198, 67, 155, 11, 40, 200, 47, 125, 55, 151, 103, 31, 82, 19, 238, 216, 193, 90, 37, 216, 213, 206, 160, 2, 94, 227, 171, 46, 139, 127, 121, 33, 111, 198, 59, 234, 86, 39, 83, 180, 6, 68, 198, 161, 81, 39, 217, 178, 149, 69, 64, 160, 187, 225, 163, 5, 86, 152, 45, 78, 159, 222, 95, 100, 37, 241, 77, 75, 113, 52, 65, 181, 93, 199, 59, 155, 74, 237, 204, 146, 172, 227, 146, 126, 55, 245, 125, 12, 253, 94, 117, 129, 250, 81, 44, 143, 73, 97, 169, 235, 11, 128, 248, 168, 7, 70, 114, 138, 85, 255, 70, 71, 31, 52, 37, 6, 59, 157, 83, 100, 47, 94, 222, 30, 132, 214, 19, 8, 26, 250, 92, 34, 208, 81, 40, 91, 214, 59, 148, 59, 86, 93, 137, 138, 5, 104, 84, 19, 229, 60, 60, 108, 101, 37, 255, 31, 227, 78, 61, 220, 112, 240, 213, 100, 80, 253, 164, 139, 161, 46, 16, 78, 157, 235, 159, 184, 24, 129, 225, 196, 189, 242, 93, 146, 71, 244, 80, 200, 101, 146, 121, 104, 231, 115, 52, 244, 65, 79, 117, 167, 80, 225, 57, 84, 110, 58, 138, 115, 157]


The RSA public (n,e) key and the ephemeral symmetric key are then passed to the RSA OAEP encryption function.
The following byte array contains the UTF-8 characters for the encrypted ephemeral key:
[-106, 115, -121, -62, -123, 54, -119, 65, -90, 8, 65, 115, 53, 22, 74, -88, 27, 29, -120, -76, 122, -113, 69, -63, 90, -22, -29, 78, 1, 66, -59, 62]

Base64url encoding this byte array produces this value for the JWT Key Segment:
lnOHwoU2iUGmCEFzNRZKqBsdiLR6j0XBWurjTgFCxT7eSfGNpni01a3TzuaeZjVc_f3jEiuvJFYFanizkpyk9BGqCNs5LhX2m1h2Qc_llKt3TgGRi67e9p36vX81G8-QccnNQ321vutKYe2jlEvcg0hhWhejhbtK2XjsKkMaJDzEDuULbJmnAFgchSdbcYgz0JK6onX_1tO2FWed0r-EK0v9v7Y65pwz_nrYf2u8f5-j5aX2RUEYVx0sq2oaJZbbp26QmUGVPdnnEgOVI6vpL5-M6Gl1q9j645Ag94Sx9HpQcg8KEUVLfK3BfbLYGnIf-kFP8fROHuIHAMdiPD4ong

Using the symmetric key to AES256 encrypt the payload bytes and base64url-encoding the resulting bytes yields the JWT Crypto Segment:
L2ZFNFVQcCtjdWw1QTVZSGw0bUhGRDZ6NDlkNFFtRWQ1a0VBSGUzNzN3V0txY29MZmRHWkhrRUtYMUJNRWl4dzQ0RHlZcmN6TWg4WWEvN04wdUYrc01UeWlYUXBYdmV6a2JvWWd2aFQzeS9OZkpoZ2doSTN6bmViTnVwZHNZZFI

Combining these segments in the order Header.Key.Crypt with period characters between the segments yields this complete JWT using the JWT Compact Serialization (with line breaks for display purposes only):

eyJhbGciOiJSRTI1NiIsDQogIng1dCI6ImI5RThKRFdqWWVmRmlNMFg5VjlhMDk4QmQ2WnNGeWVtb2dDRVgwMTZ1SXcifQ
.
lnOHwoU2iUGmCEFzNRZKqBsdiLR6j0XBWurjTgFCxT7eSfGNpni01a3TzuaeZjVc_f3jEiuvJFYFanizkpyk9BGqCNs5LhX2m1h2Qc_llKt3TgGRi67e9p36vX81G8-QccnNQ321vutKYe2jlEvcg0hhWhejhbtK2XjsKkMaJDzEDuULbJmnAFgchSdbcYgz0JK6onX_1tO2FWed0r-EK0v9v7Y65pwz_nrYf2u8f5-j5aX2RUEYVx0sq2oaJZbbp26QmUGVPdnnEgOVI6vpL5-M6Gl1q9j645Ag94Sx9HpQcg8KEUVLfK3BfbLYGnIf-kFP8fROHuIHAMdiPD4ong
.
L2ZFNFVQcCtjdWw1QTVZSGw0bUhGRDZ6NDlkNFFtRWQ1a0VBSGUzNzN3V0txY29MZmRHWkhrRUtYMUJNRWl4dzQ0RHlZcmN6TWg4WWEvN04wdUYrc01UeWlYUXBYdmV6a2JvWWd2aFQzeS9OZkpoZ2doSTN6bmViTnVwZHNZZFI

Decoding the JWT from this example requires processing the JWT Header Segment, finding the private key to decrypt the symmetric key and using that symmetric key to decrypt the encrypted payload.

No comments: