From 6df1ffa5476aba57e90ec26bcb70bdb63ddba104 Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Sat, 25 Dec 2021 17:50:04 -0600 Subject: [PATCH] WIP: restructure, debug PEM support. --- comment-on-issue-8.md | 10 + jwt.nimble | 1 - src/main/jwt/claims.nim | 6 +- src/main/jwt/joseheader.nim | 4 +- src/main/jwt/jwk.nim | 2 +- src/main/jwt/jws.nim | 21 +- src/main/jwt/jwssig.nim | 2 +- src/main/jwt/jwt.nim | 29 ++- src/main/{ => jwt}/private/crypto.nim | 10 +- src/main/{ => jwt}/private/crypto/ecdsa.nim | 18 +- src/main/{ => jwt}/private/crypto/hash.nim | 0 src/main/{ => jwt}/private/crypto/hmac.nim | 4 +- src/main/{ => jwt}/private/crypto/pem.nim | 10 +- src/main/{ => jwt}/private/crypto/rsa.nim | 6 +- src/main/{ => jwt}/private/encoding.nim | 0 src/main/{ => jwt}/private/jsonutils.nim | 0 src/main/{ => jwt}/private/timeutils.nim | 0 src/test/testdata.nim | 215 +++++++++++++++----- src/test/unit/tencoding.nim | 2 +- src/test/unit/tjws.nim | 34 +++- src/test/unit/tjwt.nim | 8 +- 21 files changed, 291 insertions(+), 91 deletions(-) create mode 100644 comment-on-issue-8.md rename src/main/{ => jwt}/private/crypto.nim (87%) rename src/main/{ => jwt}/private/crypto/ecdsa.nim (90%) rename src/main/{ => jwt}/private/crypto/hash.nim (100%) rename src/main/{ => jwt}/private/crypto/hmac.nim (97%) rename src/main/{ => jwt}/private/crypto/pem.nim (92%) rename src/main/{ => jwt}/private/crypto/rsa.nim (98%) rename src/main/{ => jwt}/private/encoding.nim (100%) rename src/main/{ => jwt}/private/jsonutils.nim (100%) rename src/main/{ => jwt}/private/timeutils.nim (100%) diff --git a/comment-on-issue-8.md b/comment-on-issue-8.md new file mode 100644 index 0000000..457900a --- /dev/null +++ b/comment-on-issue-8.md @@ -0,0 +1,10 @@ +@yglukhov After thinking, I decided to take the time to implement the entire +JWT standard (RFCs 7515-7520). This ended up being a pretty big architectural +change. + +The result of my effort currently lives here: +https://git.jdb-software.com/jdb/nim-jwt + +I'd love to get feedback on the implementation and thoughts on how this fits +into the Nim ecosystem: does it make sense to have parallel implementations, +naming, etc. For broader discussion I opened a thread on the Nim forums: diff --git a/jwt.nimble b/jwt.nimble index 26b4b56..70d96d3 100644 --- a/jwt.nimble +++ b/jwt.nimble @@ -5,7 +5,6 @@ author = "Jonathan Bernard" description = "Full JWT, JWS, JWE, and JWK implementation for Nim, compliant with RFCs 7515-7519." license = "GPL-3.0-or-later" srcDir = "src/main" -skipDirs = @["private"] # Dependencies diff --git a/src/main/jwt/claims.nim b/src/main/jwt/claims.nim index 058b3f4..c8a4f91 100644 --- a/src/main/jwt/claims.nim +++ b/src/main/jwt/claims.nim @@ -16,9 +16,9 @@ import std/json, std/options, std/times -import ../private/encoding -import ../private/jsonutils -import ../private/timeutils +import ./private/encoding +import ./private/jsonutils +import ./private/timeutils type JwtClaims* = object diff --git a/src/main/jwt/joseheader.nim b/src/main/jwt/joseheader.nim index f3546df..ff01a79 100644 --- a/src/main/jwt/joseheader.nim +++ b/src/main/jwt/joseheader.nim @@ -17,8 +17,8 @@ import std/json, std/options, std/sequtils, std/strutils import ./jwa, ./jwk -import ../private/encoding -import ../private/jsonutils +import ./private/encoding +import ./private/jsonutils type JoseHeader* = object diff --git a/src/main/jwt/jwk.nim b/src/main/jwt/jwk.nim index 674760b..199673b 100644 --- a/src/main/jwt/jwk.nim +++ b/src/main/jwt/jwk.nim @@ -13,8 +13,8 @@ import std/json, std/options, std/sequtils, std/strutils -import ../private/jsonutils import ./jwa +import ./private/jsonutils type JwkKeyType* = enum EcPublic, EcPrivate, RsaPublic, RsaPrivate, Octet diff --git a/src/main/jwt/jws.nim b/src/main/jwt/jws.nim index 905eb23..55dc6c4 100644 --- a/src/main/jwt/jws.nim +++ b/src/main/jwt/jws.nim @@ -12,9 +12,9 @@ import std/json, std/logging, std/options, std/sequtils, std/strutils -import ../private/crypto -import ../private/encoding -import ../private/jsonutils +import ./private/crypto +import ./private/encoding +import ./private/jsonutils import ./claims import ./joseheader @@ -108,7 +108,12 @@ proc initJWS*(n: JsonNode): JWS = payloadB64: n.reqStrVal("payload"), signatures: @[initJwsSignature(n)]) -proc sign*(payload: string, header: JoseHeader, key: JWK, payloadIsB64Encoded = false): JWS = +proc sign*( + payload: string, + header: JoseHeader, + key: JWK | string, + payloadIsB64Encoded = false + ): JWS = ## Create a JWS signing the given payload, which can be any arbitrary data. ## The returned JWS can be serialized with the compact serialization. All ## header data will be protected. @@ -144,7 +149,7 @@ proc sign*( payload: string, unprotected: JoseHeader, protected: JoseHeader, - key: JWK, + key: JWK | string, payloadIsB64Encoded = false): JWS = ## Create a JWS signing the given payload, which can be arbitrary data. The ## returned JWS can be serialized with the compact serialization. @@ -177,7 +182,7 @@ proc sign*( jws: JWS, unprotected: JoseHeader, protected: JoseHeader, - key: JWK): JWS = + key: JWK | string): JWS = ## Create a new JWS signing the payload again with the newly supplied header ## and key. The resulting JWS token will have multiple signatures and cannot ## be serialized with the compact serialization. @@ -202,7 +207,7 @@ proc sign*( result.compactSerialization = none[string]() -proc validate*(jws: JWS, alg: JwtAlgorithm, key: JWK, sigIdx = 0) = +proc validate*(jws: JWS, alg: JwtAlgorithm, key: JWK | string, sigIdx = 0) = if jws.len == 0: raise newException(InvalidSignature, "JWS has no signature.") @@ -241,7 +246,7 @@ proc validate*(jws: JWS, alg: JwtAlgorithm, key: JWK, sigIdx = 0) = raise newException(InvalidSignature, "failed to verify signature value.") -proc tryValidate*(jws: JWS, alg: JwtAlgorithm, key: JWK): bool = +proc tryValidate*(jws: JWS, alg: JwtAlgorithm, key: JWK | string): bool = try: jws.validate(alg, key) return true diff --git a/src/main/jwt/jwssig.nim b/src/main/jwt/jwssig.nim index 75e1ec2..dbdc574 100644 --- a/src/main/jwt/jwssig.nim +++ b/src/main/jwt/jwssig.nim @@ -13,7 +13,7 @@ import std/json, std/options import ./jwa import ./joseheader -import ../private/jsonutils +import ./private/jsonutils type JwsSignature* = object diff --git a/src/main/jwt/jwt.nim b/src/main/jwt/jwt.nim index c78a4d2..6a16c4c 100644 --- a/src/main/jwt/jwt.nim +++ b/src/main/jwt/jwt.nim @@ -74,7 +74,21 @@ proc createSignedJwt*( claims: claims, jws: sign(claims, header, key)) -proc validate*(jwt: JWT, sigAlg: JwtAlgorithm, key: JWK) = +proc validateTimeClaims*(jwt: JWT) = + let now = now() + if jwt.claims.exp.isSome and now > jwt.claims.exp.get: + raise newException(InvalidToken, "Token is expired.") + + if jwt.claims.nbf.isSome and now < jwt.claims.nbf.get: + raise newException(InvalidToken, "Token cannot be used yet.") + +proc validate*( + jwt: JWT, + sigAlg: JwtAlgorithm, + key: JWK, + validateTimeClaims = true + ) = + case jwt.kind: of jkJWS: jwt.jws.validate(sigAlg, key) @@ -82,12 +96,21 @@ proc validate*(jwt: JWT, sigAlg: JwtAlgorithm, key: JWK) = of jkJWE: raise newException(Exception, "JWE validation is not yet implemented") -proc tryValidate*(jwt: JWT, sigAlg: JwtAlgorithm, key: JWK): bool = + if validateTimeClaims: jwt.validateTimeClaims + +proc tryValidate*( + jwt: JWT, + sigAlg: JwtAlgorithm, + key: JWK, + validateTimeClaims = true + ): bool = + try: jwt.validate(sigAlg, key) return true except: return false -# proc verify*(jwt: JWT): bool = +## proc verify*(jwt: JWT, secret: string, alg: SignatureAlgorithm): bool = +## tryValidate(jwt, sigAlg, secret) # proc sign*(jwt: JWT, key: JWK): JWT = diff --git a/src/main/private/crypto.nim b/src/main/jwt/private/crypto.nim similarity index 87% rename from src/main/private/crypto.nim rename to src/main/jwt/private/crypto.nim index 35c9a23..9b39ccb 100644 --- a/src/main/private/crypto.nim +++ b/src/main/jwt/private/crypto.nim @@ -1,8 +1,8 @@ import std/options import bearssl -import ../jwt/jwa -import ../jwt/jwk +import ../jwa +import ../jwk import ./crypto/ecdsa import ./crypto/hmac @@ -20,7 +20,7 @@ proc computeSignature*( key: JWK | string ): string = - validateAlgMatchesKey(alg, key) + if typeof(key) is JWK: validateAlgMatchesKey(alg, cast[JWK](key)) case alg: of HS256, HS384, HS512: return hmac(payload, alg, key) @@ -34,10 +34,10 @@ proc verifySignature*( payload: string, signature: string, alg: JwtAlgorithm, - key: JWK + key: JWK | string ): bool = - validateAlgMatchesKey(alg, key) + if typeof(key) is JWK: validateAlgMatchesKey(alg, cast[JWK](key)) case alg: of HS256, HS384, HS512: diff --git a/src/main/private/crypto/ecdsa.nim b/src/main/jwt/private/crypto/ecdsa.nim similarity index 90% rename from src/main/private/crypto/ecdsa.nim rename to src/main/jwt/private/crypto/ecdsa.nim index dacf720..cdbe8de 100644 --- a/src/main/private/crypto/ecdsa.nim +++ b/src/main/jwt/private/crypto/ecdsa.nim @@ -1,8 +1,8 @@ import std/tables import bearssl, bearssl_pkey_decoder -import ../../jwt/jwa -import ../../jwt/jwk +import ../../jwa +import ../../jwk import ../encoding @@ -63,7 +63,7 @@ proc toEcPublicKey(jwk: JWK): EcPublicKeyObj = proc toEcPublicKey(pem: string): EcPublicKeyObj = var pkCtx: PkeyDecoderContext pkeyDecoderInit(addr pkCtx) - decodePem(pem, "EC PUBLIC KEY", addr pkCtx, + decodePem(pem, "PUBLIC KEY", addr pkCtx, cast[BearPemDecoderCallback](pkeyDecoderPush)) let k = pkCtx.key.ec @@ -158,6 +158,12 @@ proc ecSign*(message: string, alg: JwtAlgorithm, key: JWK): string = return bearEcSign(message, alg, toEcPrivateKey(key)) +proc ecSign*(message: string, alg: JwtAlgorithm, pemKey: string): string = + ## Sign a message using the ECDSA algorithm. + ## + ## *pemKey* is expected to be a PEM + return bearEcSign(message, alg, toEcPrivateKey(pemKey)) + proc ecVerify*(message, signature: string, alg: JwtAlgorithm, key: JWK): bool = ## Verify the signature for a message using ECDSA. ## @@ -170,3 +176,9 @@ proc ecVerify*(message, signature: string, alg: JwtAlgorithm, key: JWK): bool = "\"typ\"=\"" & $(key.keyKind) & "\" key.") return bearEcVerify(message, signature, alg, toEcPublicKey(key)) + +proc ecVerify*(message, signature: string, alg: JwtAlgorithm, pemKey: string): bool = + ## Verify the signature for a message using ECDSA. + ## + ## *pemKey* is expected to be a PEM. + return bearEcVerify(message, signature, alg, toEcPublicKey(pemKey)) diff --git a/src/main/private/crypto/hash.nim b/src/main/jwt/private/crypto/hash.nim similarity index 100% rename from src/main/private/crypto/hash.nim rename to src/main/jwt/private/crypto/hash.nim diff --git a/src/main/private/crypto/hmac.nim b/src/main/jwt/private/crypto/hmac.nim similarity index 97% rename from src/main/private/crypto/hmac.nim rename to src/main/jwt/private/crypto/hmac.nim index c526837..aca267d 100644 --- a/src/main/private/crypto/hmac.nim +++ b/src/main/jwt/private/crypto/hmac.nim @@ -2,8 +2,8 @@ import std/logging import bearssl -import ../../jwt/jwa -import ../../jwt/jwk +import ../../jwa +import ../../jwk import ../encoding diff --git a/src/main/private/crypto/pem.nim b/src/main/jwt/private/crypto/pem.nim similarity index 92% rename from src/main/private/crypto/pem.nim rename to src/main/jwt/private/crypto/pem.nim index a6555af..a22df62 100644 --- a/src/main/private/crypto/pem.nim +++ b/src/main/jwt/private/crypto/pem.nim @@ -15,14 +15,16 @@ proc decodePem*( var pemCtx: PemDecoderContext pemDecoderInit(addr pemCtx) - var bytesRead = 0 + var offset = 0 + var bytesRemaining = len(pem) var readingObj = false - while bytesRead < len(pem): - bytesRead += pemDecoderPush(addr pemCtx, unsafeAddr pem[bytesRead], len(pem)) + while bytesRemaining > 0: + let bytesRead = pemDecoderPush(addr pemCtx, unsafeAddr pem[offset], bytesRemaining) + offset += bytesRead + bytesRemaining -= bytesRead case pemDecoderEvent(addr pemCtx): - of PEM_BEGIN_OBJ: if readingObj: raise newException(ValueError, diff --git a/src/main/private/crypto/rsa.nim b/src/main/jwt/private/crypto/rsa.nim similarity index 98% rename from src/main/private/crypto/rsa.nim rename to src/main/jwt/private/crypto/rsa.nim index 58ab7ef..3bf9b8a 100644 --- a/src/main/private/crypto/rsa.nim +++ b/src/main/jwt/private/crypto/rsa.nim @@ -1,8 +1,8 @@ import std/options, std/tables import bearssl, bearssl_pkey_decoder -import ../../jwt/jwa -import ../../jwt/jwk +import ../../jwa +import ../../jwk import ../encoding @@ -57,7 +57,7 @@ proc toRsaPublicKey(jwk: JWK): RsaPublicKeyObj = proc toRsaPublicKey(pem: string): RsaPublicKeyObj = var pkCtx: PkeyDecoderContext pkeyDecoderInit(addr pkCtx) - decodePem(pem, "RSA PUBLIC KEY", addr pkCtx, + decodePem(pem, "PUBLIC KEY", addr pkCtx, cast[BearPemDecoderCallback](pkeyDecoderPush)) let k = pkCtx.key.rsa diff --git a/src/main/private/encoding.nim b/src/main/jwt/private/encoding.nim similarity index 100% rename from src/main/private/encoding.nim rename to src/main/jwt/private/encoding.nim diff --git a/src/main/private/jsonutils.nim b/src/main/jwt/private/jsonutils.nim similarity index 100% rename from src/main/private/jsonutils.nim rename to src/main/jwt/private/jsonutils.nim diff --git a/src/main/private/timeutils.nim b/src/main/jwt/private/timeutils.nim similarity index 100% rename from src/main/private/timeutils.nim rename to src/main/jwt/private/timeutils.nim diff --git a/src/test/testdata.nim b/src/test/testdata.nim index d5eb4db..4761f19 100644 --- a/src/test/testdata.nim +++ b/src/test/testdata.nim @@ -1,29 +1,32 @@ ## Example JWT from RFC 7519 (JWT) section 3.1 -const rfc7519_S31_HeaderB64* = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9" -const rfc7519_S31_HeaderBytes* = [123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125] -const rfc7519_S31_ClaimsB64* = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" -const rfc7519_S31_ClaimsBytes* = [123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125] +const + rfc7519_S31_HeaderB64* = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9" + rfc7519_S31_HeaderBytes* = [123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125] + rfc7519_S31_ClaimsB64* = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + rfc7519_S31_ClaimsBytes* = [123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125] ## Examples from RFC 7515 (JWS -const rfc7515_A1_HeaderB64* = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9" -const rfc7515_A1_HeaderBytes* = [123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125] -const rfc7515_A1_ClaimsB64* = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" -const rfc7515_A1_ClaimsBytes* = [123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125] -const rfc7515_A1_SigB64* = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" -const rfc7515_A1_SigBytes* = [116, 24, 223, 180, 151, 153, 224, 37, 79, 250, 96, 125, 216, 173, 187, 186, 22, 212, 37, 77, 105, 214, 191, 240, 91, 88, 5, 88, 83, 132, 141, 121] -const rfc7515_A1_Jwt* = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" -const rfc7515_A1_JwkStr* = """{ +const + rfc7515_A1_HeaderB64* = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9" + rfc7515_A1_HeaderBytes* = [123, 34, 116, 121, 112, 34, 58, 34, 74, 87, 84, 34, 44, 13, 10, 32, 34, 97, 108, 103, 34, 58, 34, 72, 83, 50, 53, 54, 34, 125] + rfc7515_A1_ClaimsB64* = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + rfc7515_A1_ClaimsBytes* = [123, 34, 105, 115, 115, 34, 58, 34, 106, 111, 101, 34, 44, 13, 10, 32, 34, 101, 120, 112, 34, 58, 49, 51, 48, 48, 56, 49, 57, 51, 56, 48, 44, 13, 10, 32, 34, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 47, 105, 115, 95, 114, 111, 111, 116, 34, 58, 116, 114, 117, 101, 125] + rfc7515_A1_SigB64* = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" + rfc7515_A1_SigBytes* = [116, 24, 223, 180, 151, 153, 224, 37, 79, 250, 96, 125, 216, 173, 187, 186, 22, 212, 37, 77, 105, 214, 191, 240, 91, 88, 5, 88, 83, 132, 141, 121] + rfc7515_A1_Jwt* = "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" + rfc7515_A1_JwkStr* = """{ "kty":"oct", "k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow" }""" -const rfc7515_A2_HeaderB64* = "eyJhbGciOiJSUzI1NiJ9" -const rfc7515_A2_HeaderBytes* = [123, 34, 97, 108, 103, 34, 58, 34, 82, 83, 50, 53, 54, 34, 125] -const rfc7515_A2_HeaderStr* = """{"alg":"RS256"}""" -const rfc7515_A2_ClaimsB64* = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" -const rfc7515_A2_SigB64* = "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw" -const rfc7515_A2_Jwt* = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw" -const rfc7515_A2_JwkPrvStr* = """{ +const + rfc7515_A2_HeaderB64* = "eyJhbGciOiJSUzI1NiJ9" + rfc7515_A2_HeaderBytes* = [123, 34, 97, 108, 103, 34, 58, 34, 82, 83, 50, 53, 54, 34, 125] + rfc7515_A2_HeaderStr* = """{"alg":"RS256"}""" + rfc7515_A2_ClaimsB64* = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + rfc7515_A2_SigB64* = "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw" + rfc7515_A2_Jwt* = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw" + rfc7515_A2_JwkPrvStr* = """{ "kty":"RSA", "n":"ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ", "e":"AQAB", @@ -34,20 +37,20 @@ const rfc7515_A2_JwkPrvStr* = """{ "dq":"h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU", "qi":"IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U" }""" -const rfc7515_A2_JwkPubStr* = """{ + rfc7515_A2_JwkPubStr* = """{ "kty":"RSA", "n":"ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ", "e":"AQAB" }""" - -const rfc7515_A3_HeaderB64* = "eyJhbGciOiJFUzI1NiJ9" -const rfc7515_A3_HeaderBytes* = [123, 34, 97, 108, 103, 34, 58, 34, 69, 83, 50, 53, 54, 34, 125] -const rfc7515_A3_HeaderStr* = """{"alg":"ES256"}""" -const rfc7515_A3_ClaimsB64* = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" -const rfc7515_A3_SignB64* = "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" -const rfc7515_A3_Jwt* = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" -const rfc7515_A3_JwkStr* = """{ +const + rfc7515_A3_HeaderB64* = "eyJhbGciOiJFUzI1NiJ9" + rfc7515_A3_HeaderBytes* = [123, 34, 97, 108, 103, 34, 58, 34, 69, 83, 50, 53, 54, 34, 125] + rfc7515_A3_HeaderStr* = """{"alg":"ES256"}""" + rfc7515_A3_ClaimsB64* = "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ" + rfc7515_A3_SignB64* = "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" + rfc7515_A3_Jwt* = "eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" + rfc7515_A3_JwkStr* = """{ "kty":"EC", "crv":"P-256", "x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU", @@ -55,15 +58,15 @@ const rfc7515_A3_JwkStr* = """{ "d":"jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI" }""" - -const rfc7515_A4_HeaderB64* = "eyJhbGciOiJFUzUxMiJ9" -const rfc7515_A4_HeaderBytes* = [123, 34, 97, 108, 103, 34, 58, 34, 69, 83, 53, 49, 50, 34, 125] -const rfc7515_A4_HeaderStr* = """{"alg":"ES512"}""" -const rfc7515_A4_PayloadB64* = "UGF5bG9hZA" -const rfc7515_A4_PayloadBytes* = [80, 97, 121, 108, 111, 97, 100] -const rfc7515_A4_SignB64* = "AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn" -const rfc7515_A4_Jwt* = "eyJhbGciOiJFUzUxMiJ9.UGF5bG9hZA.AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn" -const rfc7515_A4_JwkStr* = """{ +const + rfc7515_A4_HeaderB64* = "eyJhbGciOiJFUzUxMiJ9" + rfc7515_A4_HeaderBytes* = [123, 34, 97, 108, 103, 34, 58, 34, 69, 83, 53, 49, 50, 34, 125] + rfc7515_A4_HeaderStr* = """{"alg":"ES512"}""" + rfc7515_A4_PayloadB64* = "UGF5bG9hZA" + rfc7515_A4_PayloadBytes* = [80, 97, 121, 108, 111, 97, 100] + rfc7515_A4_SignB64* = "AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn" + rfc7515_A4_Jwt* = "eyJhbGciOiJFUzUxMiJ9.UGF5bG9hZA.AdwMgeerwtHoh-l192l60hp9wAHZFVJbLfD_UxMi70cwnZOYaRI1bKPWROc-mZZqwqT2SI-KGDKB34XO0aw_7XdtAG8GaSwFKdCAPZgoXD2YBJZCPEX3xKpRwcdOO8KpEHwJjyqOgzDO7iKvU8vcnwNrmxYbSW9ERBXukOXolLzeO_Jn" + rfc7515_A4_JwkStr* = """{ "kty":"EC", "crv":"P-521", "x":"AekpBQ8ST8a8VcfVOTNl353vSrDCLLJXmPk06wTjxrrjcBpXp5EOnYG_NjFZ6OvLFV1jSfS9tsz4qUxcWceqwQGk", @@ -75,13 +78,133 @@ const rfc7515_A4_JwkStr* = """{ # match the data from the RFC. For cases where we want exact matches (to # validate B64 conversion, signature, etc.) use either the Base64 version or # the byte arrays above. -const rfc7519_S31_HeaderStr* = """{"typ":"JWT", "alg":"HS256"}""" -const rfc7519_S31_ClaimsStr* = """{"iss":"joe", "exp":1300819380, "http://example.com/is_root":true}""" -const rfc7515_A1_HeaderStr* = """{"typ":"JWT", "alg":"HS256"}""" -const rfc7515_A1_ClaimsStr* = """{"iss":"joe", "exp":1300819380, "http://example.com/is_root":true}""" -const rfc7515_A2_ClaimsStr* = """{"iss":"joe", "exp":1300819380, "http://example.com/is_root":true}""" +const + rfc7519_S31_HeaderStr* = """{"typ":"JWT", "alg":"HS256"}""" + rfc7519_S31_ClaimsStr* = """{"iss":"joe", "exp":1300819380, "http://example.com/is_root":true}""" + rfc7515_A1_HeaderStr* = """{"typ":"JWT", "alg":"HS256"}""" + rfc7515_A1_ClaimsStr* = """{"iss":"joe", "exp":1300819380, "http://example.com/is_root":true}""" + rfc7515_A2_ClaimsStr* = """{"iss":"joe", "exp":1300819380, "http://example.com/is_root":true}""" -const sampleJwt* = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhYmMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.fKGoqlw-Nporec-dVTrNbC0ZC7kAhUsEs50s12Iwy14" -const sampleJwtHeaderDecoded* = """{"alg":"HS256","typ":"JWT"}""" -const sampleJwtClaimsDecoded* = """{"sub":"abc","name":"John Doe","iat":1516239022}""" -const sampleJwtKey* = """{ "kty": "oct", "k": "eW91ci0yNTYtYml0LXNlY3JldAo" }""" +const + sampleJwt* = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhYmMiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE1MTYyMzkwMjJ9.fKGoqlw-Nporec-dVTrNbC0ZC7kAhUsEs50s12Iwy14" + sampleJwtHeaderDecoded* = """{"alg":"HS256","typ":"JWT"}""" + sampleJwtClaimsDecoded* = """{"sub":"abc","name":"John Doe","iat":1516239022}""" + sampleJwtKey* = """{ "kty": "oct", "k": "eW91ci0yNTYtYml0LXNlY3JldAo" }""" + +const + sampleJwtRsa* = "" + sampleJwtRsaHeaderDecoded* = """{"alg":"RS256","type":"JWT"}""" + sampleJwtRsaClaimsDecoded* = """{"sub":"abc","name":"John Doe","iat":1516239022}""" + +const + sampleRsaPrvPem* = """-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA6quR5amHVIaRWhPfZCe4sF2tBo+1NhhHjcFpzxD6YJ/HQBHP +Mr3aLuQCRKL3y4E5loQ/McGfLF9h/llwY0+6I8eHNPw9fIcVd7n0CYooyxBTIn+l +hsucV2+2tXCnriIQfPZ7VUs2k0ycu1SB/DVHw7Q8K+H98Ta6oQEByZDthWhnPmnF +JInlcg4o6ckE9BKxk2uiKmprhU4MsSgsdBMUVUMStP7nxI/iiTaIlEe78P8VteBB +B6gSy16+d9+VCONQ+MlRSrh3aBWdas0ppYKDUpPrcm8uXWpNxfPqbNpSlNzPUJqg +7FPeTyvRVKm/tbGSSGVYCxNvh8DXazySvVa1XwIDAQABAoIBAQChbD2i5lex/BMW +DF95TJ2NrBJuVgJH4LGvwCDhkAM63g24c8e8Vr4zzSIGRrf/Y7fSYsv5lP/CDSai +SLG3jssy+3h1KSG+fEl3HxHQUho3fNZC/91D+OFlf/IFoyWk8ce3vfEevesfre6O +KdZ0P85Kv7s4UG9XMtd0EvZAyhGo1tQQJqknvAaRpVHKpHUglbTpYroeWxKy03Ud +qCmOP3UTb1oLn4AAGwgFOHVmaSRlOCCs/MPliHBodGrYcw2FkBtNjF8hCH0+2XWL +angHt015o/BgZnKMk2uLWRYzGm4GzALFz7Xk8RaWs1/2RUL0izQ/pVbeE7gMZU+G +rRfkt5gRAoGBAPoiYvTha1udyIkOtZUuZTpC3taO7RlvhSR6mbQGuYj8VTp8v7lB +MA3pgINDcl1DqL0pCNeL3ahy4cFSYVU7ZEheVbTiYbsZ4N3F/Vk4uZDuEEXfC8WA +pf2yvBG6nEhdIE65Sjk1rxU6uSsVZIL0GKcPGMSlZ9cMsOBiXM1AoSt3AoGBAPAs +WUKmqN0DHa2e/oSIfDfFFAqSbN/6gOtAI/onartYFhHOph2H0JuxnPaElIDmfuuq +r59N5M9o1RpgFJ7ZSBT3vhsFw9aVnfGVLDKnSlWNyNGLMeuaKXRxTHlVVIEFE6TW +yZhhsODFwMovC5SeIKJuCgwZvM0ggh+o8Nxpum9ZAoGAMaHZGNYRw2APhoKQrUVD +eMgEB3bcvQtP0+kvznT3I6NOFgji0hOJQXlvspwTeUYPmVknE/4AwYfqG74I6iya +vXFaeEXjNojwAZFjr+x9hbB3MiYL4+ifBzQL9Uid8g3odzZ0790jHIdGbrIT+5gL +vDpWo85eSGGQRzW9TEzirgkCgYEAwIdMppljFIjC6cNi1Gt06GAbyL3IeWQepHcu +YAHpFXVve6bkkxekqqqe4R82zH35kIGrd1DB82JeMl6DKTOVDPnsc00TyJj3nAmw +/IoOlLasHQ4wXmWehbGtVDaLH0IqlSF5SaZGXGkqOumrpt972bnMZBbdurIsnaSY +MJiw00ECgYEAgkkhhWiYUNBpMXWYPeKXIthZ08X9M2l/6XTZsPy4P38Og7kmV2h8 +mlElb2jLRGRobR/I5Z4adupXAe3pgCvq8/LrVz6zEvEkTVQ4Ln4E14CmiqpqL1jD +aG3Ed4xKRgUd/5CpdiU3fB15BEeUDn6XdeEbKiZVZF7AA6mykSWFIgg= + -----END RSA PRIVATE KEY-----""" + + sampleRsaPubPem* = """-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6quR5amHVIaRWhPfZCe4 +sF2tBo+1NhhHjcFpzxD6YJ/HQBHPMr3aLuQCRKL3y4E5loQ/McGfLF9h/llwY0+6 +I8eHNPw9fIcVd7n0CYooyxBTIn+lhsucV2+2tXCnriIQfPZ7VUs2k0ycu1SB/DVH +w7Q8K+H98Ta6oQEByZDthWhnPmnFJInlcg4o6ckE9BKxk2uiKmprhU4MsSgsdBMU +VUMStP7nxI/iiTaIlEe78P8VteBBB6gSy16+d9+VCONQ+MlRSrh3aBWdas0ppYKD +UpPrcm8uXWpNxfPqbNpSlNzPUJqg7FPeTyvRVKm/tbGSSGVYCxNvh8DXazySvVa1 +XwIDAQAB +-----END PUBLIC KEY-----""" + +# --------------------------------------------------------------- + +const + rsPrivateKey* = """-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWw +kWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mr +m/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEi +NQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV +3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2 +QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQABAoIBACiARq2wkltjtcjs +kFvZ7w1JAORHbEufEO1Eu27zOIlqbgyAcAl7q+/1bip4Z/x1IVES84/yTaM8p0go +amMhvgry/mS8vNi1BN2SAZEnb/7xSxbflb70bX9RHLJqKnp5GZe2jexw+wyXlwaM ++bclUCrh9e1ltH7IvUrRrQnFJfh+is1fRon9Co9Li0GwoN0x0byrrngU8Ak3Y6D9 +D8GjQA4Elm94ST3izJv8iCOLSDBmzsPsXfcCUZfmTfZ5DbUDMbMxRnSo3nQeoKGC +0Lj9FkWcfmLcpGlSXTO+Ww1L7EGq+PT3NtRae1FZPwjddQ1/4V905kyQFLamAA5Y +lSpE2wkCgYEAy1OPLQcZt4NQnQzPz2SBJqQN2P5u3vXl+zNVKP8w4eBv0vWuJJF+ +hkGNnSxXQrTkvDOIUddSKOzHHgSg4nY6K02ecyT0PPm/UZvtRpWrnBjcEVtHEJNp +bU9pLD5iZ0J9sbzPU/LxPmuAP2Bs8JmTn6aFRspFrP7W0s1Nmk2jsm0CgYEAyH0X ++jpoqxj4efZfkUrg5GbSEhf+dZglf0tTOA5bVg8IYwtmNk/pniLG/zI7c+GlTc9B +BwfMr59EzBq/eFMI7+LgXaVUsM/sS4Ry+yeK6SJx/otIMWtDfqxsLD8CPMCRvecC +2Pip4uSgrl0MOebl9XKp57GoaUWRWRHqwV4Y6h8CgYAZhI4mh4qZtnhKjY4TKDjx +QYufXSdLAi9v3FxmvchDwOgn4L+PRVdMwDNms2bsL0m5uPn104EzM6w1vzz1zwKz +5pTpPI0OjgWN13Tq8+PKvm/4Ga2MjgOgPWQkslulO/oMcXbPwWC3hcRdr9tcQtn9 +Imf9n2spL/6EDFId+Hp/7QKBgAqlWdiXsWckdE1Fn91/NGHsc8syKvjjk1onDcw0 +NvVi5vcba9oGdElJX3e9mxqUKMrw7msJJv1MX8LWyMQC5L6YNYHDfbPF1q5L4i8j +8mRex97UVokJQRRA452V2vCO6S5ETgpnad36de3MUxHgCOX3qL382Qx9/THVmbma +3YfRAoGAUxL/Eu5yvMK8SAt/dJK6FedngcM3JEFNplmtLYVLWhkIlNRGDwkg3I5K +y18Ae9n7dHVueyslrb6weq7dTkYDi3iOYRW8HRkIQh06wEdbxt0shTzAJvvCQfrB +jg/3747WSsf/zBTcHihTRBdAv6OmdhV4/dD5YBfLAkLrd+mX7iE= +-----END RSA PRIVATE KEY-----""" + rsPublicKey* = """-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv +vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc +aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy +tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0 +e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb +V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9 +MwIDAQAB +-----END PUBLIC KEY-----""" + ec256PrivKey = """-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2 +OF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r +1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G +-----END PRIVATE KEY-----""" + ec256PubKey = """-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEVs/o5+uQbTjL3chynL4wXgUg2R9 +q9UU8I5mEovUf86QZ7kOBIjJwqnzD1omageEHWwHdBO6B+dFabmdT9POxg== +-----END PUBLIC KEY-----""" + + ec384PrivKey = """-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDCAHpFQ62QnGCEvYh/pE9QmR1C9aLcDItRbslbmhen/h1tt8AyMhske +enT+rAyyPhGgBwYFK4EEACKhZANiAAQLW5ZJePZzMIPAxMtZXkEWbDF0zo9f2n4+ +T1h/2sh/fviblc/VTyrv10GEtIi5qiOy85Pf1RRw8lE5IPUWpgu553SteKigiKLU +PeNpbqmYZUkWGh3MLfVzLmx85ii2vMU= +-----END EC PRIVATE KEY-----""" + ec384PubKey = """-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEC1uWSXj2czCDwMTLWV5BFmwxdM6PX9p+ +Pk9Yf9rIf374m5XP1U8q79dBhLSIuaojsvOT39UUcPJROSD1FqYLued0rXiooIii +1D3jaW6pmGVJFhodzC31cy5sfOYotrzF +-----END PUBLIC KEY-----""" + ec512PrivKey = """-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIBiyAa7aRHFDCh2qga9sTUGINE5jHAFnmM8xWeT/uni5I4tNqhV5Xx +0pDrmCV9mbroFtfEa0XVfKuMAxxfZ6LM/yKgBwYFK4EEACOhgYkDgYYABAGBzgdn +P798FsLuWYTDDQA7c0r3BVk8NnRUSexpQUsRilPNv3SchO0lRw9Ru86x1khnVDx+ +duq4BiDFcvlSAcyjLACJvjvoyTLJiA+TQFdmrearjMiZNE25pT2yWP1NUndJxPcv +VtfBW48kPOmvkY4WlqP5bAwCXwbsKrCgk6xbsp12ew== +-----END EC PRIVATE KEY-----""" + ec512PubKey = """-----BEGIN PUBLIC KEY----- +MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBgc4HZz+/fBbC7lmEww0AO3NK9wVZ +PDZ0VEnsaUFLEYpTzb90nITtJUcPUbvOsdZIZ1Q8fnbquAYgxXL5UgHMoywAib47 +6MkyyYgPk0BXZq3mq4zImTRNuaU9slj9TVJ3ScT3L1bXwVuPJDzpr5GOFpaj+WwM +Al8G7CqwoJOsW7Kddns= +-----END PUBLIC KEY-----""" diff --git a/src/test/unit/tencoding.nim b/src/test/unit/tencoding.nim index a63a111..52cce4f 100644 --- a/src/test/unit/tencoding.nim +++ b/src/test/unit/tencoding.nim @@ -1,6 +1,6 @@ import std/json, std/options, std/strutils, std/unittest -import private/encoding +import jwt/private/encoding import ../testdata suite "private/encoding": diff --git a/src/test/unit/tjws.nim b/src/test/unit/tjws.nim index afad221..5ad8248 100644 --- a/src/test/unit/tjws.nim +++ b/src/test/unit/tjws.nim @@ -2,7 +2,7 @@ import std/json, std/unittest import jwt/claims, jwt/joseheader, jwt/jwa, jwt/jwk, jwt/jws -import private/encoding +import jwt/private/encoding import ../testdata @@ -50,21 +50,21 @@ suite "jwt/jws": jws.validate(HS256, sampleKey) - test "RS256 - sign": + test "RS256 - sign using JWK": check rfc7515_A2_Jwt == $sign( header = initJoseHeader(rfc7515_A2_HeaderB64), payload = b64UrlDecode(rfc7515_A2_ClaimsB64), key = rfc7515_A2_JwkPrvKey) - test "RS256 - verify": + test "RS256 - verify using JWK": validate( jws = initJWS(rfc7515_A2_Jwt), alg = RS256, key = rfc7515_A2_JwkPubKey) - test "RS256 - round trip": + test "RS256 - round trip using JWK": let jws = sign( header = initJoseHeader(%*{"alg":"RS256"}), @@ -73,6 +73,31 @@ suite "jwt/jws": jws.validate(RS256, rfc7515_A2_JwkPubKey) +#[ TODO + test "RS256 - sign using PEM": + + #check rfc7515_A2_Jwt == $sign( + echo $sign( + header = initJoseHeader(parseJson(sampleJwtRsaHeaderDecoded)), + payload = $initJwtClaims(parseJson(sampleJwtRsaClaimsDecoded)), + key = rsPrivateKey) + + test "RS256 - verify using PEM": + + validate( + jws = initJWS(rfc7515_A2_Jwt), + alg = RS256, + key = rsPublicKey) + + test "RS256 - round trip using PEM": + + let jws = sign( + header = initJoseHeader(%*{"alg":"RS256"}), + payload = "This is a message I want to protect from tampering.", + key = rsPrivateKey) + + jws.validate(RS256, rsPublicKey) + test "ES256 - sign": check rfc7515_A3_Jwt == $sign( @@ -118,3 +143,4 @@ suite "jwt/jws": key = rfc7515_A4_Jwk) jws.validate(ES512, rfc7515_A4_Jwk) +]# diff --git a/src/test/unit/tjwt.nim b/src/test/unit/tjwt.nim index 9b4a5d7..fdabcc5 100644 --- a/src/test/unit/tjwt.nim +++ b/src/test/unit/tjwt.nim @@ -1,7 +1,7 @@ import std/json, std/unittest import jwt/claims, jwt/joseheader, jwt/jwa, jwt/jwk, jwt/jwt -import private/encoding +import jwt/private/encoding import ../testdata @@ -33,9 +33,9 @@ suite "jwt/jwt": test "validate - HS256": - initJwt(rfc7515_A1_Jwt).validate(HS256, rfc7515_A1_Jwk) - initJwt(sampleJwt).validate(HS256, sampleKey) + initJwt(rfc7515_A1_Jwt).validate(HS256, rfc7515_A1_Jwk, validateTimeClaims = false) + initJwt(sampleJwt).validate(HS256, sampleKey, validateTimeClaims = false) test "validate - RS256": - initJwt(rfc7515_A2_Jwt).validate(RS256, rfc7515_A2_JwkPubKey) + initJwt(rfc7515_A2_Jwt).validate(RS256, rfc7515_A2_JwkPubKey, validateTimeClaims = false)