1 #!/usr/bin/env dub 2 /+ dub.sdl: 3 name "bench_l8w8jwt" 4 libs "l8w8jwt" "mbedcrypto" "mbedx509" 5 +/ 6 7 module benchmarks.l8w8jwt; 8 9 import core.stdc.string; 10 import std.algorithm; 11 import std.array; 12 import std.conv; 13 import std.datetime.stopwatch; 14 import std.stdio; 15 import std.string; 16 17 int main(string[] args) 18 { 19 // args: enc/dec/val, cycle count, alg, token/payload, signature 20 // output: 21 // payload/token/true 22 // msecs taken 23 // GC used bytes 24 25 if (args.length != 6) { writeln("Invalid args"); return 1; } 26 size_t cycles = args[2].to!size_t; 27 28 int alg = args[3].predSwitch( 29 "HS256", L8W8JWT_ALG_HS256, 30 "HS384", L8W8JWT_ALG_HS384, 31 "HS512", L8W8JWT_ALG_HS512, 32 "RS256", L8W8JWT_ALG_RS256, 33 "RS384", L8W8JWT_ALG_RS384, 34 "RS512", L8W8JWT_ALG_RS512, 35 "ES256", L8W8JWT_ALG_ES256, 36 "ES384", L8W8JWT_ALG_ES384, 37 "ES512", L8W8JWT_ALG_ES512, 38 -1 39 ); 40 if (alg < 0) 41 { 42 writeln("Unsupported algorithm"); 43 return 1; 44 } 45 46 { 47 StopWatch sw; 48 sw.start(); 49 scope (exit) 50 { 51 sw.stop(); 52 writeln(sw.peek.total!"msecs"); 53 writeln(0); // C library, no GC used 54 } 55 56 if (args[1] == "val") return validate(cycles, alg, args[4], args[5]); 57 else if (args[1] == "dec") return decode(cycles, alg, args[4], args[5]); 58 else if (args[1] == "enc") return encode(cycles, alg, args[4], args[5]); 59 } 60 61 writeln("Invalid command: ", args[1]); 62 return 1; 63 } 64 65 int validate(size_t cycles, int alg, string token, string secret) 66 { 67 l8w8jwt_decoding_params params; 68 l8w8jwt_decoding_params_init(¶ms); 69 params.alg = alg; 70 bool ret; 71 foreach (_; 0..cycles) 72 { 73 params.jwt = cast(char*)token.ptr; 74 params.jwt_length = token.length; 75 76 params.verification_key = cast(ubyte*)secret.ptr; 77 params.verification_key_length = secret.length; 78 79 l8w8jwt_validation_result validation_result; 80 immutable r = l8w8jwt_decode(¶ms, &validation_result, null, null); 81 ret = !r && validation_result == l8w8jwt_validation_result.L8W8JWT_VALID; 82 } 83 84 writeln(ret); 85 return 0; 86 } 87 88 int decode(size_t cycles, int alg, string token, string secret) 89 { 90 l8w8jwt_decoding_params params; 91 l8w8jwt_decoding_params_init(¶ms); 92 params.alg = alg; 93 size_t claims_length; 94 l8w8jwt_claim* claims; 95 96 bool ret; 97 foreach (_; 0..cycles) 98 { 99 params.jwt = cast(char*)token.ptr; 100 params.jwt_length = token.length; 101 102 params.verification_key = cast(ubyte*)secret.ptr; 103 params.verification_key_length = secret.length; 104 105 l8w8jwt_validation_result validation_result; 106 if (claims) l8w8jwt_free_claims(claims, claims_length); 107 immutable r = l8w8jwt_decode(¶ms, &validation_result, &claims, &claims_length); 108 if (r || validation_result != l8w8jwt_validation_result.L8W8JWT_VALID) 109 { 110 writeln("Failed to decode token. r=", r, ", res=", validation_result); 111 return 1; 112 } 113 } 114 115 chillbuff cb; 116 chillbuff_init(&cb, 32, 1, chillbuff_growth_method.CHILLBUFF_GROW_DUPLICATIVE); 117 assert(claims && claims_length > 1); 118 l8w8jwt_write_claims(&cb, claims+1, claims_length-1); // workaround - skip first as it has alg from header 119 l8w8jwt_free_claims(claims, claims_length); 120 scope (exit) chillbuff_free(&cb); 121 writeln('{', (cast(char*)cb.array)[0..cb.length], '}'); 122 123 return 0; 124 } 125 126 int encode(size_t cycles, int alg, string payload, string secret) 127 { 128 // prep claims - not all data types handled properly, but enough for the test 129 import std.json, std.typecons; 130 auto jpay = parseJSON(payload); 131 auto cl = jpay.object.byKeyValue.map!(a => tuple(a.key, a.value.type.predSwitch( 132 JSONType..string, a.value.str, 133 JSONType.integer, a.value.integer.to!string 134 ), a.value.type == JSONType..string ? L8W8JWT_CLAIM_TYPE_STRING : L8W8JWT_CLAIM_TYPE_INTEGER)).array; 135 136 l8w8jwt_claim[] payload_claims = 137 cl.map!(a => l8w8jwt_claim( 138 cast(char*)a[0].ptr, 139 a[0].length, 140 cast(char*)a[1].ptr, 141 a[1].length, 142 a[2] 143 )).array; 144 145 char* jwt; 146 size_t jwt_length; 147 l8w8jwt_encoding_params params; 148 l8w8jwt_encoding_params_init(¶ms); 149 params.alg = alg; 150 params.secret_key = cast(ubyte*)secret.ptr; 151 params.secret_key_length = secret.length; 152 params.out_ = &jwt; 153 params.out_length = &jwt_length; 154 155 foreach (_; 0..cycles) 156 { 157 if (jwt) l8w8jwt_free(jwt); 158 immutable r = l8w8jwt_encode(¶ms); 159 if (r) 160 { 161 writeln("Error encoding token: ", r); 162 return 1; 163 } 164 } 165 166 scope (exit) l8w8jwt_free(jwt); 167 writeln(jwt[0..jwt_length]); 168 return 0; 169 } 170 171 // bindings 172 extern(C) nothrow @nogc: 173 174 import core.sys.posix.sys.select; 175 176 enum L8W8JWT_ALG_HS256 = 0; 177 enum L8W8JWT_ALG_HS384 = 1; 178 enum L8W8JWT_ALG_HS512 = 2; 179 enum L8W8JWT_ALG_RS256 = 3; 180 enum L8W8JWT_ALG_RS384 = 4; 181 enum L8W8JWT_ALG_RS512 = 5; 182 enum L8W8JWT_ALG_PS256 = 6; 183 enum L8W8JWT_ALG_PS384 = 7; 184 enum L8W8JWT_ALG_PS512 = 8; 185 enum L8W8JWT_ALG_ES256 = 9; 186 enum L8W8JWT_ALG_ES384 = 10; 187 enum L8W8JWT_ALG_ES512 = 11; 188 enum L8W8JWT_ALG_ES256K = 12; 189 enum L8W8JWT_ALG_ED25519 = 13; 190 191 enum l8w8jwt_validation_result 192 { 193 /** 194 * The JWT is valid (according to the passed validation parameters). 195 */ 196 L8W8JWT_VALID = cast(uint) 0, 197 198 /** 199 * The issuer claim is invalid. 200 */ 201 L8W8JWT_ISS_FAILURE = cast(uint) 1 << cast(uint) 0, 202 203 /** 204 * The subject claim is invalid. 205 */ 206 L8W8JWT_SUB_FAILURE = cast(uint) 1 << cast(uint) 1, 207 208 /** 209 * The audience claim is invalid. 210 */ 211 L8W8JWT_AUD_FAILURE = cast(uint) 1 << cast(uint) 2, 212 213 /** 214 * The JWT ID claim is invalid. 215 */ 216 L8W8JWT_JTI_FAILURE = cast(uint) 1 << cast(uint) 3, 217 218 /** 219 * The token is expired. 220 */ 221 L8W8JWT_EXP_FAILURE = cast(uint) 1 << cast(uint) 4, 222 223 /** 224 * The token is not yet valid. 225 */ 226 L8W8JWT_NBF_FAILURE = cast(uint) 1 << cast(uint) 5, 227 228 /** 229 * The token was not issued yet, are you from the future? 230 */ 231 L8W8JWT_IAT_FAILURE = cast(uint) 1 << cast(uint) 6, 232 233 /** 234 * The token was potentially tampered with: its signature couldn't be verified. 235 */ 236 L8W8JWT_SIGNATURE_VERIFICATION_FAILURE = cast(uint) 1 << cast(uint) 7, 237 238 /** 239 * The token's "typ" claim validation failed. 240 */ 241 L8W8JWT_TYP_FAILURE = cast(uint) 1 << cast(uint) 8 242 } 243 244 /** 245 * Struct containing the parameters to use for decoding and validating a JWT. 246 */ 247 struct l8w8jwt_decoding_params 248 { 249 /** 250 * The token to decode and validate. 251 */ 252 char* jwt; 253 254 /** 255 * The jwt string length. 256 */ 257 size_t jwt_length; 258 259 /** 260 * The signature algorithm ID. <p> 261 * [0;2] = HS256/384/512 | [3;5] = RS256/384/512 | [6;8] = PS256/384/512 | [9;11] = ES256/384/512 <p> 262 * This affects what should be the value of {@link #verification_key} 263 */ 264 int alg; 265 266 /** 267 * [OPTIONAL] The issuer claim (who issued the JWT?). <p> 268 * Set to <code>NULL</code> if you don't want to validate the issuer. <p> 269 * The JWT will only pass verification if its <code>iss</code> claim matches this string. 270 * @see https://tools.ietf.org/html/rfc7519#section-4.1.1 271 */ 272 char* validate_iss; 273 274 /** 275 * validate_iss string length. 276 */ 277 size_t validate_iss_length; 278 279 /** 280 * [OPTIONAL] The subject claim (who is the JWT about?). <p> 281 * Set to <code>NULL</code> if you don't want to validate the subject claim. <p> 282 * The JWT will only pass verification if its <code>sub</code> matches this string. 283 * @see https://tools.ietf.org/html/rfc7519#section-4.1.2 284 */ 285 char* validate_sub; 286 287 /** 288 * validate_sub string length. 289 */ 290 size_t validate_sub_length; 291 292 /** 293 * [OPTIONAL] The audience claim (who is the JWT intended for? Who is the intended JWT's recipient?). <p> 294 * Set to <code>NULL</code> if you don't want to validate the audience. <p> 295 * The JWT will only pass verification if its <code>aud</code> matches this string. 296 * @see https://tools.ietf.org/html/rfc7519#section-4.1.3 297 */ 298 char* validate_aud; 299 300 /** 301 * validate_aud string length. 302 */ 303 size_t validate_aud_length; 304 305 /** 306 * [OPTIONAL] The JWT ID. Provides a unique identifier for the token. <p> 307 * Set to <code>NULL</code> if you don't want to validate the jti claim. <p> 308 * The JWT will only pass verification if its <code>jti</code> matches this string. 309 * @see https://tools.ietf.org/html/rfc7519#section-4.1.7 310 */ 311 char* validate_jti; 312 313 /** 314 * validate_jti claim length. 315 */ 316 size_t validate_jti_length; 317 318 /** 319 * Should the expiration claim be verified? 320 * If this is set to <code>1</code>, the <code>exp</code> claim will be compared to the current date and time + {@link #exp_tolerance_seconds} 321 */ 322 int validate_exp; 323 324 /** 325 * Should the "not before" claim be verified? 326 * If this is set to <code>1</code>, the <code>nbf</code> claim will be compared to the current date and time + {@link #nbf_tolerance_seconds} 327 */ 328 int validate_nbf; 329 330 /** 331 * Should the "issued at" claim be verified? 332 * If this is set to <code>1</code>, the <code>iat</code> claim will be compared to the current date and time + {@link #iat_tolerance_seconds} 333 */ 334 int validate_iat; 335 336 /** 337 * Small inconsistencies in time can happen, or also latency between clients and servers. 338 * That's just life. You can forgive a few seconds of expiration, but don't exaggerate this! <p> 339 * Only taken into consideration if {@link #validate_exp} is set to <code>1</code>. 340 */ 341 ubyte exp_tolerance_seconds; 342 343 /** 344 * The amount of seconds to subtract from the current time when comparing the "not before" claim, to allow for a small tolerance time frame. 345 * Only taken into consideration if {@link #validate_nbf} is set to <code>1</code>. 346 */ 347 ubyte nbf_tolerance_seconds; 348 349 /** 350 * The amount of seconds to subtract from the current time when comparing the "issued at" claim, to allow for a small tolerance time frame. 351 * Only taken into consideration if {@link #validate_iat} is set to <code>1</code>. 352 */ 353 ubyte iat_tolerance_seconds; 354 355 /** 356 * The key to use for verifying the token's signature 357 * (e.g. if you chose HS256 as algorithm, this will be the HMAC secret; for RS512 this will be the PEM-formatted public RSA key string, etc...). 358 */ 359 ubyte* verification_key; 360 361 /** 362 * Length of the {@link #verification_key} 363 */ 364 size_t verification_key_length; 365 366 /** 367 * [OPTIONAL] The typ claim (what type is the token?). <p> 368 * Set to <code>NULL</code> if you don't want to validate the "typ" claim. <p> 369 */ 370 char* validate_typ; 371 372 /** 373 * validate_typ string length. 374 */ 375 size_t validate_typ_length; 376 } 377 378 /** 379 * Initializes a {@link #l8w8jwt_decoding_params} instance by setting its fields to default values. 380 * @param params The l8w8jwt_decoding_params to initialize (set to default values). 381 */ 382 void l8w8jwt_decoding_params_init (l8w8jwt_decoding_params* params); 383 384 /** 385 * Validates a set of l8w8jwt_decoding_params. 386 * @param params The l8w8jwt_decoding_params to validate. 387 * @return Return code as defined in retcodes.h 388 */ 389 int l8w8jwt_validate_decoding_params (l8w8jwt_decoding_params* params); 390 391 /** 392 * Decode (and validate) a JWT using specific parameters. <p> 393 * The resulting {@link #l8w8jwt_validation_result} written into the passed "out_validation_result" pointer 394 * contains validation failure flags (see the {@link #l8w8jwt_validation_result} enum docs for more details). <p> 395 * This only happens if decoding also succeeded: if the token is malformed, nothing will be written into "out_validation_result". <p> 396 * If validation succeeds, the {@link #l8w8jwt_validation_result} receives the value 0 (enum value <code>L8W8JWT_VALID</code>). <p> 397 * The same applies to the "out_claims" argument: it is only allocated and written to if it (obviously) isn't <code>NULL</code> and if the decoding was also successful! 398 * 399 * @param params The parameters to use for decoding and validating the token. 400 * 401 * @param out_validation_result Where to write the validation result flags into (0 means success). In case of a decoding failure this is set to -1 (or <code>~L8W8JWT_VALID</code>)! 402 * 403 * @param out_claims 404 * [OPTIONAL] Where the decoded claims (header + payload claims together) should be written into. 405 * This pointer will be dereferenced + allocated, so make sure to pass a fresh pointer! 406 * If you don't need the claims, set this to <code>NULL</code> (they will only be validated, e.g. signature, exp, etc...). 407 * Check the note down below for more infos! 408 * 409 * @param out_claims_length Where to write the decoded claims count into. This will receive the value of how many claims were written into "out_claims" (0 if you decided to set "out_claims" to <code>NULL</code>). 410 * 411 * @note If you decide to keep the claims stored in the <code>out_claims</code> parameter, REMEMBER to call {@link #l8w8jwt_free_claims()} on it once you're done using them! 412 * 413 * @return Return code as defined in retcodes.h (this is NOT the validation result that's written into the out_validation_result argument; the returned int describes whether the actual parsing/decoding part failed). 414 */ 415 int l8w8jwt_decode (l8w8jwt_decoding_params* params, l8w8jwt_validation_result* out_validation_result, l8w8jwt_claim** out_claims, size_t* out_claims_length); 416 enum L8W8JWT_MAX_KEY_SIZE = 8192; 417 418 /** 419 * JWT claim value is a string (e.g. <code>"iss": "glitchedpolygons.com"</code>). 420 */ 421 enum L8W8JWT_CLAIM_TYPE_STRING = 0; 422 423 /** 424 * JWT claim value is an integer (e.g. <code>"exp": 1579610629</code>) 425 */ 426 enum L8W8JWT_CLAIM_TYPE_INTEGER = 1; 427 428 /** 429 * JWT claim value type number (e.g. <code>"size": 1.85</code>). 430 */ 431 enum L8W8JWT_CLAIM_TYPE_NUMBER = 2; 432 433 /** 434 * JWT claim value is a boolean (e.g. <code>"done": true</code>). 435 */ 436 enum L8W8JWT_CLAIM_TYPE_BOOLEAN = 3; 437 438 /** 439 * JWT claim value is null (e.g. <code>"ref": null</code>). 440 */ 441 enum L8W8JWT_CLAIM_TYPE_NULL = 4; 442 443 /** 444 * JWT claim value type JSON array (e.g. <code>"ids": [2, 4, 8, 16]</code>). 445 */ 446 enum L8W8JWT_CLAIM_TYPE_ARRAY = 5; 447 448 /** 449 * JWT claim value type is a JSON object (e.g. <code>"objs": { "name": "GMan", "id": 420 }</code>). 450 */ 451 enum L8W8JWT_CLAIM_TYPE_OBJECT = 6; 452 453 /** 454 * JWT claim value is some other type. 455 */ 456 enum L8W8JWT_CLAIM_TYPE_OTHER = 7; 457 458 /** 459 * Struct containing a jwt claim key-value pair.<p> 460 * If allocated on the heap by the decode function, 461 * remember to call <code>l8w8jwt_claims_free()</code> on it once you're done using it. 462 */ 463 struct l8w8jwt_claim 464 { 465 /** 466 * The token claim key (e.g. "iss", "iat", "sub", etc...). <p> 467 * NUL-terminated C-string! 468 */ 469 char* key; 470 471 /** 472 * key string length. <p> 473 * Set this to <code>0</code> if you want to make the encoder use <code>strlen(key)</code> instead. 474 */ 475 size_t key_length; 476 477 /** 478 * The claim's value as a NUL-terminated C-string. 479 */ 480 char* value; 481 482 /** 483 * value string length. <p> 484 * Set this to <code>0</code> if you want to make the encoder use <code>strlen(value)</code> instead. 485 */ 486 size_t value_length; 487 488 /** 489 * The type of the claim's value. <p> 490 * 0 = string, 1 = integer, 2 = number, 3 = boolean, 4 = null, 5 = array, 6 = object, 7 = other. 491 * @see https://www.w3schools.com/js/js_json_datatypes.asp 492 */ 493 int type; 494 } 495 496 /** 497 * Frees a heap-allocated <code>l8w8jwt_claim</code> array. 498 * @param claims The claims to free. 499 * @param claims_count The size of the passed claims array. 500 */ 501 void l8w8jwt_free_claims (l8w8jwt_claim* claims, size_t claims_count); 502 503 /** 504 * Writes a bunch of JWT claims into a chillbuff stringbuilder. <p> 505 * Curly braces and trailing commas won't be written; only the "key":"value" pairs! 506 * @param stringbuilder The buffer into which to write the claims. 507 * @param claims The l8w8jwt_claim array of claims to write. 508 * @param claims_count The claims array size. 509 * @return Return code as specified inside retcodes.h 510 */ 511 int l8w8jwt_write_claims (chillbuff* stringbuilder, l8w8jwt_claim* claims, size_t claims_count); 512 513 /** 514 * Gets a claim by key from a l8w8jwt_claim array. 515 * @param claims The array to look in. 516 * @param claims_count The claims array size. 517 * @param key The claim key (e.g. "sub") to look for. 518 * @param key_length The claim key's string length. 519 * @return The found claim; <code>NULL</code> if no such claim was found in the array. 520 */ 521 l8w8jwt_claim* l8w8jwt_get_claim (l8w8jwt_claim* claims, size_t claims_count, const(char)* key, size_t key_length); 522 523 /** 524 * Struct containing the parameters to use for creating a JWT with l8w8jwt. 525 */ 526 struct l8w8jwt_encoding_params 527 { 528 /** 529 * The signature algorithm ID. <p> 530 * [0;2] = HS256/384/512 | [3;5] = RS256/384/512 | [6;8] = PS256/384/512 | [9;11] = ES256/384/512 531 */ 532 int alg; 533 534 /** 535 * [OPTIONAL] The issuer claim (who issued the JWT?). Can be omitted by setting this to <code>NULL</code>. 536 * @see https://tools.ietf.org/html/rfc7519#section-4.1.1 537 */ 538 char* iss; 539 540 /** 541 * iss claim string length. 542 */ 543 size_t iss_length; 544 545 /** 546 * [OPTIONAL] The subject claim (who is the JWT about?). Set to <code>NULL</code> if you don't want it in your token. 547 * @see https://tools.ietf.org/html/rfc7519#section-4.1.2 548 */ 549 char* sub; 550 551 /** 552 * sub claim string length. 553 */ 554 size_t sub_length; 555 556 /** 557 * [OPTIONAL] The audience claim (who is the JWT intended for? Who is the intended JWT's recipient?). 558 * Set this to <code>NULL</code> if you don't wish to add this claim to the token. 559 * @see https://tools.ietf.org/html/rfc7519#section-4.1.3 560 */ 561 char* aud; 562 563 /** 564 * aud claim string length. 565 */ 566 size_t aud_length; 567 568 /** 569 * [OPTIONAL] The JWT ID. Provides a unique identifier for the token. Can be omitted by setting this to <code>NULL</code>. 570 * @see https://tools.ietf.org/html/rfc7519#section-4.1.7 571 */ 572 char* jti; 573 574 /** 575 * jti claim string length. 576 */ 577 size_t jti_length; 578 579 /** 580 * Expiration time claim; specifies when this token should stop being valid (in seconds since Unix epoch). <p> 581 * If you want to omit this, set this to <code>0</code>, but do NOT FORGET to set it to something, 582 * otherwise it will be set to whatever random value was in the memory where this variable resides. 583 * @see https://tools.ietf.org/html/rfc7519#section-4.1.4 584 */ 585 time_t exp; 586 587 /** 588 * "Not before" time claim; specifies when this token should start being valid (in seconds since Unix epoch). <p> 589 * If you want to omit this, set this to <code>0</code>, but do NOT FORGET to set it to something, 590 * otherwise it will be set to whatever random value was in the memory where this variable resides. 591 * @see https://tools.ietf.org/html/rfc7519#section-4.1.5 592 */ 593 time_t nbf; 594 595 /** 596 * "Issued at" timestamp claim; specifies when this token was emitted (in seconds since Unix epoch). <p> 597 * If you want to omit this, set this to <code>0</code>, but do NOT FORGET to set it to something, 598 * otherwise it will be set to whatever random value was in the memory where this variable resides. 599 * @see https://tools.ietf.org/html/rfc7519#section-4.1.6 600 */ 601 time_t iat; 602 603 /** 604 * [OPTIONAL] Array of additional claims to include in the JWT's header like for example "kid" or "cty"; pass <code>NULL</code> if you don't wish to add any! <p> 605 * Avoid header claims such as <code>typ</code> and <code>alg</code>, since those are written by the encoding function itself. 606 * @see https://tools.ietf.org/html/rfc7519#section-4.1.7 607 */ 608 l8w8jwt_claim* additional_header_claims; 609 610 /** 611 * [OPTIONAL] The additional_header_claims array size; pass <code>0</code> if you don't wish to include any custom claims! 612 */ 613 size_t additional_header_claims_count; 614 615 /** 616 * [OPTIONAL] Array of additional claims to include in the JWT's payload; pass <code>NULL</code> if you don't wish to add any! <p> 617 * Registered claim names such as "iss", "exp", etc... have their own dedicated field within this struct: do not include those in this array to prevent uncomfortable duplicates! 618 * @see https://tools.ietf.org/html/rfc7519#section-4 619 */ 620 l8w8jwt_claim* additional_payload_claims; 621 622 /** 623 * [OPTIONAL] The additional_payload_claims array size; pass <code>0</code> if you don't wish to include any custom claims! 624 */ 625 size_t additional_payload_claims_count; 626 627 /** 628 * The secret key to use for signing the token 629 * (e.g. if you chose HS256 as algorithm, this will be the HMAC secret; for RS512 this will be the private PEM-formatted RSA key string, and so on...). 630 */ 631 ubyte* secret_key; 632 633 /** 634 * Length of the secret_key 635 */ 636 size_t secret_key_length; 637 638 /** 639 * If the secret key requires a password for usage, please assign it to this field. <p> 640 * You can only omit this when using JWT algorithms "HS256", "HS384" or "HS512" (it's ignored in that case actually). <p> 641 * Every other algorithm requires you to at least set this to <code>NULL</code> if the {@link #secret_key} isn't password-protected. 642 */ 643 ubyte* secret_key_pw; 644 645 /** 646 * The secret key's password length (if there is any). If there's none, set this to zero! 647 */ 648 size_t secret_key_pw_length; 649 650 /** 651 * Where the encoded token should be written into 652 * (will be malloc'ed, so make sure to <code>l8w8jwt_free()</code> this as soon as you're done using it!). 653 */ 654 char** out_; 655 656 /** 657 * Where the output token string length should be written into. 658 */ 659 size_t* out_length; 660 } 661 662 /** 663 * Initializes a {@link #l8w8jwt_encoding_params} instance by setting its fields to default values. 664 * @param params The l8w8jwt_encoding_params to initialize (set to default values). 665 */ 666 void l8w8jwt_encoding_params_init (l8w8jwt_encoding_params* params); 667 668 /** 669 * Validates a set of l8w8jwt_encoding_params. 670 * @param params The l8w8jwt_encoding_params to validate. 671 * @return Return code as defined in retcodes.h 672 */ 673 int l8w8jwt_validate_encoding_params (l8w8jwt_encoding_params* params); 674 675 /** 676 * Creates, signs and encodes a Json-Web-Token. <p> 677 * An example output could be: <code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InNvbWUta2V5LWlkLWhlcmUtMDEyMzQ1NiJ9.eyJpYXQiOjE1Nzk2NDUzNTUsImV4cCI6MTU3OTY0NTk1NSwic3ViIjoiR29yZG9uIEZyZWVtYW4iLCJpc3MiOiJCbGFjayBNZXNhIiwiYXVkIjoiQWRtaW5pc3RyYXRvciJ9.uk4EEoq0ql_SguLto5EWzklakpzO-6GE2U26crB8vUY</code> <p> 678 * @param params The token encoding parameters (e.g. "alg", "iss", "exp", etc...). 679 * @return Return code as defined in retcodes.h 680 * @see l8w8jwt_encoding_params 681 */ 682 int l8w8jwt_encode (l8w8jwt_encoding_params* params); 683 684 void l8w8jwt_free(void* mem); 685 686 // chillbuff bindings 687 688 /** 689 * How should the chillbuff's underlying array grow in size 690 * once its maximum capacity is reached during a push_back? 691 */ 692 enum chillbuff_growth_method 693 { 694 /** 695 * Double the capacity. 696 */ 697 CHILLBUFF_GROW_DUPLICATIVE = 0, 698 699 /** 700 * Triple the capacity. 701 */ 702 CHILLBUFF_GROW_TRIPLICATIVE = 1, 703 704 /** 705 * Grow by the same capacity every time the buffer is full. 706 */ 707 CHILLBUFF_GROW_LINEAR = 2, 708 709 /** 710 * Multiplies the capacity by itself. Not the greatest idea... Use carefully! 711 */ 712 CHILLBUFF_GROW_EXPONENTIAL = 3 713 } 714 715 /** 716 * Self-reallocating dynamic size array of no strictly defined type. 717 * Easy 'n' "chill" (hope you like segmentation fault errors). 718 */ 719 struct chillbuff 720 { 721 /** 722 * The buffer's underlying array that stores the data. 723 */ 724 void* array; 725 726 /** 727 * The current amount of elements stored in the chillbuff. DO NOT touch this yourself, only read! 728 */ 729 size_t length; 730 731 /** 732 * The current buffer capacity. This grows dynamically according to the specified {@link #chillbuff_growth_method}. 733 */ 734 size_t capacity; 735 736 /** 737 * The size of each stored element. DO NOT CHANGE THIS! Only read (if necessary)... 738 */ 739 size_t element_size; 740 741 /** 742 * The way the buffer's capacity is increased when it's full. 743 */ 744 chillbuff_growth_method growth_method; 745 } 746 747 /** 748 * Initializes a chillbuff instance and makes it ready to accept data. 749 * @param buff The chillbuff instance to init (or rather, a pointer to it). 750 * @param initial_capacity The initial capacity of the underlying array. If you pass <code>0</code> here, <code>16</code> is used by default. 751 * @param element_size How big should every array element be? E.g. if you're storing <code>int</code> you should pass <code>sizeof(int)</code>. 752 * @param growth_method How should the buffer grow once its maximum capacity is reached? @see chillbuff_growth_method 753 * @return Chillbuff exit code as defined at the top of the chillbuff.h header file. <code>0</code> means success. 754 */ 755 int chillbuff_init ( 756 chillbuff* buff, 757 const size_t initial_capacity, 758 const size_t element_size, 759 const chillbuff_growth_method growth_method) 760 { 761 import core.stdc.stdlib; 762 buff.array = malloc(min(16, initial_capacity)*element_size); 763 buff.capacity = min(16, initial_capacity); 764 buff.element_size = element_size; 765 buff.growth_method = growth_method; 766 return 0; 767 } 768 769 /** 770 * Frees a chillbuff instance. 771 * @param buff The chillbuff to deallocate. If this is <code>NULL</code>, nothing happens at all. 772 */ 773 void chillbuff_free (chillbuff* buff) 774 { 775 import core.stdc.stdlib; 776 free(buff.array); 777 } 778 779 // /** 780 // * Clears a chillbuff's data. <p> 781 // * Deletes all of the underlying array's elements and resets the length to <code>0</code>. <p> 782 // * Leaves the array allocated at the current capacity. 783 // * @param buff The chillbuff to clear. If this is <code>NULL</code>, nothing happens at all. 784 // */ 785 // void chillbuff_clear (chillbuff* buff);