Initial commit with JWK parsing implementation.
This commit is contained in:
2
src/test/unit/config.nims
Normal file
2
src/test/unit/config.nims
Normal file
@ -0,0 +1,2 @@
|
||||
switch("path", "../../main")
|
||||
switch("verbosity", "0")
|
3
src/test/unit/runner.nim
Normal file
3
src/test/unit/runner.nim
Normal file
@ -0,0 +1,3 @@
|
||||
import std/unittest
|
||||
|
||||
import ./tjwk
|
217
src/test/unit/tjwk.nim
Normal file
217
src/test/unit/tjwk.nim
Normal file
@ -0,0 +1,217 @@
|
||||
import std/json, std/options, std/unittest
|
||||
|
||||
import jwt/jwk
|
||||
|
||||
suite "jwt/jwk":
|
||||
|
||||
const rfc7517A1ExamplePubKeysStr = """
|
||||
{"keys":
|
||||
[
|
||||
{"kty":"EC",
|
||||
"crv":"P-256",
|
||||
"x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
|
||||
"y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
|
||||
"use":"enc",
|
||||
"kid":"1"},
|
||||
{"kty":"RSA",
|
||||
"n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
|
||||
"e":"AQAB",
|
||||
"alg":"RS256",
|
||||
"kid":"2011-04-29"}
|
||||
]
|
||||
}"""
|
||||
|
||||
let rfc7517A1ExamplePubKeysJson = parseJson(rfc7517A1ExamplePubKeysStr)
|
||||
|
||||
const rfc7517A2ExamplePrvKeysStr = """
|
||||
{"keys":
|
||||
[
|
||||
{"kty":"EC",
|
||||
"crv":"P-256",
|
||||
"x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
|
||||
"y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
|
||||
"d":"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
|
||||
"use":"enc",
|
||||
"kid":"1"},
|
||||
|
||||
{"kty":"RSA",
|
||||
"n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
|
||||
"e":"AQAB",
|
||||
"d":"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q",
|
||||
"p":"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs",
|
||||
"q":"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk",
|
||||
"dp":"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0",
|
||||
"dq":"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk",
|
||||
"qi":"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU",
|
||||
"alg":"RS256",
|
||||
"kid":"2011-04-29"}
|
||||
]
|
||||
}"""
|
||||
|
||||
let rfc7517A2ExamplePrvKeysJson = parseJson(rfc7517A2ExamplePrvKeysStr)
|
||||
|
||||
test "parseEcPubKey parses valid keys":
|
||||
let keyNode = rfc7517A1ExamplePubKeysJson["keys"][0]
|
||||
let jwk = parseJwk(keyNode)
|
||||
|
||||
check:
|
||||
jwk.kty == $ktyEC
|
||||
jwk.keyKind == EcPublic
|
||||
jwk.use.isSome
|
||||
jwk.use.get == $jwkuEncrypt
|
||||
jwk.kid.isSome
|
||||
jwk.kid.get == "1"
|
||||
jwk.key_ops.isNone
|
||||
jwk.ecPub.crv == $P256
|
||||
jwk.ecPub.x == "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4"
|
||||
jwk.ecPub.y.isSome
|
||||
jwk.ecPub.y.get == "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM"
|
||||
|
||||
test "parseEcPubKey rejects keys missing required values":
|
||||
let keyNode = rfc7517A1ExamplePubKeysJson["keys"][0]
|
||||
|
||||
let withoutCrv = parseJson($keyNode)
|
||||
withoutCrv.delete("crv")
|
||||
expect ValueError: discard parseJwk(withoutCrv)
|
||||
|
||||
let withoutX = parseJson($keyNode)
|
||||
withoutX.delete("x")
|
||||
expect ValueError: discard parseJwk(withoutX)
|
||||
|
||||
let withoutY = parseJson($keyNode)
|
||||
withoutY.delete("y")
|
||||
let jwkWithoutY = parseJwk(withoutY)
|
||||
|
||||
check:
|
||||
jwkWithoutY.kty == $ktyEc
|
||||
jwkWithoutY.keyKind == EcPublic
|
||||
jwkWithoutY.ecPub.y.isNone
|
||||
|
||||
test "parseRsaPubKey parses valid keys":
|
||||
let keyNode = rfc7517A1ExamplePubKeysJson["keys"][1]
|
||||
let jwk = parseJwk(keyNode)
|
||||
|
||||
check:
|
||||
jwk.kty == $ktyRSA
|
||||
jwk.keyKind == RsaPublic
|
||||
jwk.alg.isSome
|
||||
jwk.alg.get == $RS256
|
||||
jwk.use.isNone
|
||||
jwk.kid.isSome
|
||||
jwk.kid.get == "2011-04-29"
|
||||
jwk.key_ops.isNone
|
||||
jwk.rsaPub.e == "AQAB"
|
||||
jwk.rsaPub.n == "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw"
|
||||
|
||||
test "parseRsaPubKey rejects keys missing required values":
|
||||
let keyNode = rfc7517A1ExamplePubKeysJson["keys"][1]
|
||||
|
||||
let withoutN = parseJson($keyNode)
|
||||
withoutN.delete("n")
|
||||
expect ValueError: discard parseJwk(withoutN)
|
||||
|
||||
let withoutE = parseJson($keyNode)
|
||||
withoutE.delete("e")
|
||||
expect ValueError: discard parseJwk(withoutE)
|
||||
|
||||
test "parseEcPrvKey parses valid keys":
|
||||
let keyNode = rfc7517A2ExamplePrvKeysJson["keys"][0]
|
||||
let jwk = parseJwk(keyNode)
|
||||
|
||||
check:
|
||||
jwk.kty == $ktyEC
|
||||
jwk.keyKind == EcPrivate
|
||||
jwk.use.isSome
|
||||
jwk.use.get == $jwkuEncrypt
|
||||
jwk.kid.isSome
|
||||
jwk.kid.get == "1"
|
||||
jwk.key_ops.isNone
|
||||
jwk.ecPrv.crv == $P256
|
||||
jwk.ecPrv.x == "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4"
|
||||
jwk.ecPrv.y.isSome
|
||||
jwk.ecPrv.y.get == "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM"
|
||||
jwk.ecPrv.d == "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE"
|
||||
|
||||
test "parseEcPrvKey rejects keys missing required values":
|
||||
let keyNode = rfc7517A2ExamplePrvKeysJson["keys"][0]
|
||||
|
||||
let withoutCrv = parseJson($keyNode)
|
||||
withoutCrv.delete("crv")
|
||||
expect ValueError: discard parseJwk(withoutCrv)
|
||||
|
||||
let withoutX = parseJson($keyNode)
|
||||
withoutX.delete("x")
|
||||
expect ValueError: discard parseJwk(withoutX)
|
||||
|
||||
let withoutY = parseJson($keyNode)
|
||||
withoutY.delete("y")
|
||||
let jwkWithoutY = parseJwk(withoutY)
|
||||
|
||||
check:
|
||||
jwkWithoutY.kty == $ktyEc
|
||||
jwkWithoutY.keyKind == EcPrivate
|
||||
jwkWithoutY.ecPrv.y.isNone
|
||||
|
||||
test "parseRsaPrvKey parses valid keys":
|
||||
let keyNode = rfc7517A2ExamplePrvKeysJson["keys"][1]
|
||||
let jwk = parseJwk(keyNode)
|
||||
|
||||
check:
|
||||
jwk.kty == $ktyRSA
|
||||
jwk.keyKind == RsaPrivate
|
||||
jwk.alg.isSome
|
||||
jwk.alg.get == $RS256
|
||||
jwk.use.isNone
|
||||
jwk.kid.isSome
|
||||
jwk.kid.get == "2011-04-29"
|
||||
jwk.key_ops.isNone
|
||||
jwk.rsaPrv.e == "AQAB"
|
||||
jwk.rsaPrv.n == "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw"
|
||||
jwk.rsaPrv.d == "X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q"
|
||||
jwk.rsaPrv.p.isSome
|
||||
jwk.rsaPrv.p.get == "83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs"
|
||||
jwk.rsaPrv.q.isSome
|
||||
jwk.rsaPrv.q.get == "3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk"
|
||||
jwk.rsaPrv.dp.isSome
|
||||
jwk.rsaPrv.dp.get == "G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0"
|
||||
jwk.rsaPrv.dq.isSome
|
||||
jwk.rsaPrv.dq.get == "s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk"
|
||||
jwk.rsaPrv.qi.isSome
|
||||
jwk.rsaPrv.qi.get == "GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU"
|
||||
jwk.rsaPrv.oth.isNone
|
||||
|
||||
test "parseRsaPrvKey rejects keys missing required values":
|
||||
let keyNode = rfc7517A2ExamplePrvKeysJson["keys"][1]
|
||||
|
||||
let withoutN = parseJson($keyNode)
|
||||
withoutN.delete("n")
|
||||
expect ValueError: discard parseJwk(withoutN)
|
||||
|
||||
let withoutE = parseJson($keyNode)
|
||||
withoutE.delete("e")
|
||||
expect ValueError: discard parseJwk(withoutE)
|
||||
|
||||
let withoutP = parseJson($keyNode)
|
||||
withoutP.delete("p")
|
||||
let jwkWithoutP = parseJwk(withoutP)
|
||||
check jwkWithoutP.rsaPrv.p.isNone
|
||||
|
||||
test "parseJwkSet (public key examples)":
|
||||
let jwkSet = parseJwkSet(rfc7517A1ExamplePubKeysJson)
|
||||
|
||||
check:
|
||||
jwkSet.len == 2
|
||||
jwkSet[0].kty == $ktyEC
|
||||
jwkSet[0].keyKind == EcPublic
|
||||
jwkSet[1].kty == $ktyRSA
|
||||
jwkSet[1].keyKind == RsaPublic
|
||||
|
||||
test "parseJwkSet (private key examples)":
|
||||
let jwkSet = parseJwkSet(rfc7517A2ExamplePrvKeysJson)
|
||||
|
||||
check:
|
||||
jwkSet.len == 2
|
||||
jwkSet[0].kty == $ktyEC
|
||||
jwkSet[0].keyKind == EcPrivate
|
||||
jwkSet[1].kty == $ktyRSA
|
||||
jwkSet[1].keyKind == RsaPrivate
|
Reference in New Issue
Block a user