Skip to content

Commit 9e12dcc

Browse files
committed
Add l8w8jwt component
1 parent 9e9a935 commit 9e12dcc

18 files changed

+833
-1
lines changed

.build-test-rules.yml

+5
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,8 @@ catch2/examples/catch2-console:
4242
disable:
4343
- if: IDF_VERSION_MAJOR < 5
4444
reason: Example relies on WHOLE_ARCHIVE component property which was introduced in IDF v5.0
45+
46+
l8w8jwt/examples/es256:
47+
enable:
48+
- if: IDF_VERSION_MAJOR > 4
49+
reason: Supported only on IDF versions with Mbed TLS v3.x

.github/ISSUE_TEMPLATE/bug-report.yml

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ body:
3636
- jsmn
3737
- json_generator
3838
- json_parser
39+
- l8w8jwt
3940
- led_strip
4041
- libsodium
4142
- nghttp

.github/workflows/upload_component.yml

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ jobs:
5151
json_generator;
5252
json_parser;
5353
led_strip;
54+
l8w8jwt;
5455
libsodium;
5556
nghttp;
5657
onewire_bus;

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,6 @@
5757
[submodule "catch2/Catch2"]
5858
path = catch2/Catch2
5959
url = https://github.com/catchorg/Catch2.git
60+
[submodule "l8w8jwt/l8w8jwt"]
61+
path = l8w8jwt/l8w8jwt
62+
url = https://github.com/GlitchedPolygons/l8w8jwt.git

l8w8jwt/CMakeLists.txt

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
idf_component_register(SRCS "l8w8jwt/src/base64.c"
2+
"l8w8jwt/src/claim.c"
3+
"l8w8jwt/src/decode.c"
4+
"l8w8jwt/src/encode.c"
5+
"l8w8jwt/src/util.c"
6+
"l8w8jwt/src/version.c"
7+
INCLUDE_DIRS "l8w8jwt/include"
8+
PRIV_INCLUDE_DIRS "port/private_include"
9+
PRIV_REQUIRES "mbedtls"
10+
)
11+
12+
set_source_files_properties("l8w8jwt/src/encode.c" "l8w8jwt/src/decode.c"
13+
PROPERTIES COMPILE_FLAGS "-Wno-maybe-uninitialized")
14+
15+
target_compile_options(${COMPONENT_LIB} PRIVATE "-DL8W8JWT_SMALL_STACK=1" "-DL8W8JWT_ENABLE_EDDSA=0")

l8w8jwt/LICENSE

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
l8w8jwt/LICENSE

l8w8jwt/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
l8w8jwt/README.md

l8w8jwt/examples/es256/CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# The following lines of boilerplate have to be in your project's
2+
# CMakeLists in this exact order for cmake to work correctly
3+
cmake_minimum_required(VERSION 3.16)
4+
5+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
6+
project(es256)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
idf_component_register(SRCS "main.c"
2+
INCLUDE_DIRS "")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## IDF Component Manager Manifest File
2+
version: "1.0.0"
3+
description: l8w8jwt Example
4+
dependencies:
5+
idf: ">=5.0"
6+
espressif/l8w8jwt:
7+
version: '>=2.2.1'
8+
override_path: '../../../'

l8w8jwt/examples/es256/main/main.c

+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
/*
2+
Copyright 2020 Raphael Beck
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
#include <stdio.h>
18+
#include <string.h>
19+
#include "l8w8jwt/encode.h"
20+
#include "l8w8jwt/decode.h"
21+
22+
/*
23+
* This keypair was generated using the following command:
24+
* openssl ecparam -name prime256v1 -genkey -noout -out private.pem && openssl ec -in private.pem -pubout -out public.pem
25+
*/
26+
27+
static const char ECDSA_PRIVATE_KEY[] = "-----BEGIN EC PRIVATE KEY-----\n"
28+
"MHcCAQEEILvM6E7mLOdndALDyFc3sOgUTb6iVjgwRBtBwYZngSuwoAoGCCqGSM49\n"
29+
"AwEHoUQDQgAEMlFGAIxe+/zLanxz4bOxTI6daFBkNGyQ+P4bc/RmNEq1NpsogiMB\n"
30+
"5eXC7jUcD/XqxP9HCIhdRBcQHx7aOo3ayQ==\n"
31+
"-----END EC PRIVATE KEY-----";
32+
33+
static const char ECDSA_PUBLIC_KEY[] = "-----BEGIN PUBLIC KEY-----\n"
34+
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMlFGAIxe+/zLanxz4bOxTI6daFBk\n"
35+
"NGyQ+P4bc/RmNEq1NpsogiMB5eXC7jUcD/XqxP9HCIhdRBcQHx7aOo3ayQ==\n"
36+
"-----END PUBLIC KEY-----";
37+
38+
int example_jwt_decode(char *jwt)
39+
{
40+
struct l8w8jwt_decoding_params params;
41+
l8w8jwt_decoding_params_init(&params);
42+
43+
params.alg = L8W8JWT_ALG_ES256;
44+
45+
params.jwt = jwt;
46+
params.jwt_length = strlen(jwt);
47+
48+
params.verification_key = (unsigned char *)ECDSA_PUBLIC_KEY;
49+
params.verification_key_length = strlen(ECDSA_PUBLIC_KEY);
50+
51+
params.validate_iss = "Black Mesa";
52+
params.validate_iss_length = strlen(params.validate_iss);
53+
54+
params.validate_sub = "Gordon Freeman";
55+
params.validate_sub_length = strlen(params.validate_sub);
56+
57+
params.validate_exp = 1;
58+
params.exp_tolerance_seconds = 60;
59+
60+
params.validate_iat = 1;
61+
params.iat_tolerance_seconds = 60;
62+
63+
enum l8w8jwt_validation_result validation_result;
64+
int r = l8w8jwt_decode(&params, &validation_result, NULL, NULL);
65+
66+
printf("\nl8w8jwt_decode_es256 function returned %s (code %d).\n\nValidation result: \n%d\n", r == L8W8JWT_SUCCESS ? "successfully" : "", r, validation_result);
67+
return r;
68+
}
69+
70+
char *example_jwt_encode(void)
71+
{
72+
char *jwt;
73+
size_t jwt_length;
74+
75+
struct l8w8jwt_claim header_claims[] = {
76+
{
77+
.key = "kid",
78+
.key_length = 3,
79+
.value = "some-key-id-here-012345",
80+
.value_length = strlen("some-key-id-here-012345"),
81+
.type = L8W8JWT_CLAIM_TYPE_STRING
82+
}
83+
};
84+
85+
struct l8w8jwt_claim payload_claims[] = {
86+
{
87+
.key = "ctx",
88+
.key_length = 3,
89+
.value = "Unforseen Consequences",
90+
.value_length = strlen("Unforseen Consequences"),
91+
.type = L8W8JWT_CLAIM_TYPE_STRING
92+
},
93+
{
94+
.key = "age",
95+
.key_length = 3,
96+
.value = "27",
97+
.value_length = strlen("27"),
98+
.type = L8W8JWT_CLAIM_TYPE_INTEGER
99+
},
100+
{
101+
.key = "size",
102+
.key_length = strlen("size"),
103+
.value = "1.85",
104+
.value_length = strlen("1.85"),
105+
.type = L8W8JWT_CLAIM_TYPE_NUMBER
106+
},
107+
{
108+
.key = "alive",
109+
.key_length = strlen("alive"),
110+
.value = "true",
111+
.value_length = strlen("true"),
112+
.type = L8W8JWT_CLAIM_TYPE_BOOLEAN
113+
},
114+
{
115+
.key = "nulltest",
116+
.key_length = strlen("nulltest"),
117+
.value = "null",
118+
.value_length = strlen("null"),
119+
.type = L8W8JWT_CLAIM_TYPE_NULL
120+
}
121+
};
122+
123+
struct l8w8jwt_encoding_params params;
124+
l8w8jwt_encoding_params_init(&params);
125+
126+
params.alg = L8W8JWT_ALG_ES256;
127+
128+
params.sub = "Gordon Freeman";
129+
params.sub_length = strlen("Gordon Freeman");
130+
131+
params.iss = "Black Mesa";
132+
params.iss_length = strlen("Black Mesa");
133+
134+
params.aud = "Administrator";
135+
params.aud_length = strlen("Administrator");
136+
137+
params.iat = time(NULL);
138+
params.exp = time(NULL) + 600; // Set to expire after 10 minutes (600 seconds).
139+
140+
params.additional_header_claims = header_claims;
141+
params.additional_header_claims_count = sizeof(header_claims) / sizeof(struct l8w8jwt_claim);
142+
143+
params.additional_payload_claims = payload_claims;
144+
params.additional_payload_claims_count = sizeof(payload_claims) / sizeof(struct l8w8jwt_claim);
145+
146+
params.secret_key = (unsigned char *)ECDSA_PRIVATE_KEY;
147+
params.secret_key_length = strlen(ECDSA_PRIVATE_KEY);
148+
149+
params.out = &jwt;
150+
params.out_length = &jwt_length;
151+
152+
int r = l8w8jwt_encode(&params);
153+
printf("\nl8w8jwt_encode_es256 function returned %s (code %d).\n\nCreated token: \n%s\n", r == L8W8JWT_SUCCESS ? "successfully" : "", r, jwt);
154+
155+
return jwt;
156+
}
157+
158+
void app_main(void)
159+
{
160+
printf("=== JWT Example on ESP32 ===\n");
161+
char *jwt = example_jwt_encode();
162+
int ret = example_jwt_decode(jwt);
163+
l8w8jwt_free(jwt); /* Never forget to free the jwt string! */
164+
printf("JWT generation and decoding: %s\n", ret == L8W8JWT_SUCCESS ? "success" : "failed");
165+
return;
166+
}

l8w8jwt/idf_component.yml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
version: "2.2.1"
2+
description: "Minimal, OpenSSL-less and super lightweight JWT library written in C"
3+
url: https://github.com/espressif/idf-extra-components/tree/master/l8w8jwt
4+
dependencies:
5+
idf: ">=5.0"
6+
espressif/jsmn:
7+
version: "^1.1.0"

l8w8jwt/l8w8jwt

Submodule l8w8jwt added at 824bb52

0 commit comments

Comments
 (0)