From 59e924e19d8fce8beb9fa35a43bde026046fe776 Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Fri, 9 Apr 2021 09:57:16 -0500 Subject: [PATCH] crypto.jwt: Add a library to encode/decode jwt web tokens. https://tools.ietf.org/html/rfc7519 online tester at https://jwt.io/#debugger - we don't have a way to minify json (remove spaces from the final payload) - had to add a word in base64 that urlencodes and removes trailing = signs - only sha-256 is supported --- extra/crypto/jwt/authors.txt | 1 + extra/crypto/jwt/jwt-tests.factor | 24 +++++++++++++++++++ extra/crypto/jwt/jwt.factor | 38 +++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 extra/crypto/jwt/authors.txt create mode 100644 extra/crypto/jwt/jwt-tests.factor create mode 100644 extra/crypto/jwt/jwt.factor diff --git a/extra/crypto/jwt/authors.txt b/extra/crypto/jwt/authors.txt new file mode 100644 index 0000000000..7c1b2f2279 --- /dev/null +++ b/extra/crypto/jwt/authors.txt @@ -0,0 +1 @@ +Doug Coleman diff --git a/extra/crypto/jwt/jwt-tests.factor b/extra/crypto/jwt/jwt-tests.factor new file mode 100644 index 0000000000..dd8fd5a0aa --- /dev/null +++ b/extra/crypto/jwt/jwt-tests.factor @@ -0,0 +1,24 @@ +! Copyright (C) 2021 Doug Coleman. +! See http://factorcode.org/license.txt for BSD license. +USING: checksums.sha crypto.jwt tools.test ; +IN: crypto.jwt.tests + +{ t } [ + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.he0ErCNloe4J7Id0Ry2SEDg09lKkZkfsRiGsdX_vgEg" + "" check-signature +] unit-test + +{ t } [ + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.QjxgSJl1C760VSNK4e5EZaYo6qemRqYL_Ol8ZgeQreg" + "covid" check-signature +] unit-test + +{ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.he0ErCNloe4J7Id0Ry2SEDg09lKkZkfsRiGsdX_vgEg" } [ + H{ { "alg" "HS256" } { "typ" "JWT" } } + H{ + { "sub" "1234567890" } + { "name" "John Doe" } + { "iat" 1516239022 } + } + "" sha-256 sign-jwt +] unit-test \ No newline at end of file diff --git a/extra/crypto/jwt/jwt.factor b/extra/crypto/jwt/jwt.factor new file mode 100644 index 0000000000..0b51235387 --- /dev/null +++ b/extra/crypto/jwt/jwt.factor @@ -0,0 +1,38 @@ +! Copyright (C) 2021 Doug Coleman. +! See http://factorcode.org/license.txt for BSD license. +USING: assocs base64 checksums.hmac checksums.sha json.reader +json.writer kernel sequences splitting strings ; +IN: crypto.jwt + +: jwt> ( jwt -- header payload signature ) + "." split first3 + [ urlsafe-base64> >string json> ] + [ urlsafe-base64> >string json> ] + [ ] tri* ; + +: hmac-signature ( encoded secret/f method/f -- signature ) + [ "" or ] [ sha-256 or ] bi* + hmac-bytes >urlsafe-base64-jwt >string ; + +: jwt-encode-header-payload ( header payload -- encoded ) + [ >json >urlsafe-base64-jwt ] bi@ "." glue ; + +: sign-jwt ( header payload secret/f method/f -- jwt ) + [ jwt-encode-header-payload dup ] 2dip + hmac-signature "." "" glue-as ; + +ERROR: unsupported-jwt header ; + +: ensure-sha256 ( header -- header ) + dup "typ" of "JWT" = [ unsupported-jwt ] unless + dup "alg" of "HS256" = [ unsupported-jwt ] unless ; + +: check-signature ( jwt secret/f -- ? ) + [ + "." split first3 [ + dup + urlsafe-base64> >string json> ensure-sha256 drop + ] [ "." glue ] + [ ] tri* + ] dip + '[ _ f hmac-signature ] dip = ; -- 2.34.1