import std/options import bearssl import ../jwa import ../jwk import ./crypto/ecdsa import ./crypto/hmac import ./crypto/rsa proc validateAlgMatchesKey(alg: JwtAlgorithm, key: JWK) = if key.alg.isSome and key.alg.get != $alg: raise newException(ValueError, "requested signature algorithm (" & $alg & ") does not match the " & "algorithm intended for use with this key (" & key.alg.get & ")") proc computeSignature*( payload: string, alg: JwtAlgorithm, key: JWK | string ): string = if typeof(key) is JWK: validateAlgMatchesKey(alg, cast[JWK](key)) case alg: of HS256, HS384, HS512: return hmac(payload, alg, key) of RS256, RS384, RS512: return rsaSign(payload, alg, key) of ES256, ES384, ES512: return ecSign(payload, alg, key) else: raise newException(Exception, "unsupported signature algorithm: " & $alg) proc verifySignature*( payload: string, signature: string, alg: JwtAlgorithm, key: JWK | string ): bool = if typeof(key) is JWK: validateAlgMatchesKey(alg, cast[JWK](key)) case alg: of HS256, HS384, HS512: let hash = hmac(payload, alg, key) return hash == signature of RS256, RS384, RS512: return rsaVerify(payload, signature, alg, key) of ES256, ES384, ES512: return ecVerify(payload, signature, alg, key) else: raise newException(Exception, "unsupported signature algorithm: " & $alg)