Update dependencies (#5518)
This commit is contained in:
139
vendor/github.com/open-policy-agent/opa/topdown/tokens.go
generated
vendored
139
vendor/github.com/open-policy-agent/opa/topdown/tokens.go
generated
vendored
@@ -42,7 +42,8 @@ const (
|
||||
)
|
||||
|
||||
// JSONWebToken represent the 3 parts (header, payload & signature) of
|
||||
// a JWT in Base64.
|
||||
//
|
||||
// a JWT in Base64.
|
||||
type JSONWebToken struct {
|
||||
header string
|
||||
payload string
|
||||
@@ -52,11 +53,11 @@ type JSONWebToken struct {
|
||||
|
||||
// decodeHeader populates the decodedHeader field.
|
||||
func (token *JSONWebToken) decodeHeader() error {
|
||||
h, err := builtinBase64UrlDecode(ast.String(token.header))
|
||||
result, err := getResult(builtinBase64UrlDecode, ast.StringTerm(token.header))
|
||||
if err != nil {
|
||||
return fmt.Errorf("JWT header had invalid encoding: %w", err)
|
||||
}
|
||||
decodedHeader, err := validateJWTHeader(string(h.(ast.String)))
|
||||
decodedHeader, err := validateJWTHeader(string(result.Value.(ast.String)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -69,19 +70,19 @@ func (token *JSONWebToken) decodeHeader() error {
|
||||
// It does no data validation, it merely checks that the given string
|
||||
// represents a structurally valid JWT. It supports JWTs using JWS compact
|
||||
// serialization.
|
||||
func builtinJWTDecode(a ast.Value) (ast.Value, error) {
|
||||
token, err := decodeJWT(a)
|
||||
func builtinJWTDecode(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
token, err := decodeJWT(operands[0].Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if err = token.decodeHeader(); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
p, err := builtinBase64UrlDecode(ast.String(token.payload))
|
||||
p, err := getResult(builtinBase64UrlDecode, ast.StringTerm(token.payload))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JWT payload had invalid encoding: %v", err)
|
||||
return fmt.Errorf("JWT payload had invalid encoding: %v", err)
|
||||
}
|
||||
|
||||
if cty := token.decodedHeader.Get(jwtCtyKey); cty != nil {
|
||||
@@ -95,24 +96,28 @@ func builtinJWTDecode(a ast.Value) (ast.Value, error) {
|
||||
// contents are quoted (behavior of https://jwt.io/). To fix
|
||||
// this, remove leading and trailing quotes.
|
||||
if ctyVal == headerJwt {
|
||||
p, err = builtinTrim(p, ast.String(`"'`))
|
||||
p, err = getResult(builtinTrim, p, ast.StringTerm(`"'`))
|
||||
if err != nil {
|
||||
panic("not reached")
|
||||
}
|
||||
return builtinJWTDecode(p)
|
||||
result, err := getResult(builtinJWTDecode, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return iter(result)
|
||||
}
|
||||
}
|
||||
|
||||
payload, err := extractJSONObject(string(p.(ast.String)))
|
||||
payload, err := extractJSONObject(string(p.Value.(ast.String)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
s, err := builtinBase64UrlDecode(ast.String(token.signature))
|
||||
s, err := getResult(builtinBase64UrlDecode, ast.StringTerm(token.signature))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JWT signature had invalid encoding: %v", err)
|
||||
return fmt.Errorf("JWT signature had invalid encoding: %v", err)
|
||||
}
|
||||
sign := hex.EncodeToString([]byte(s.(ast.String)))
|
||||
sign := hex.EncodeToString([]byte(s.Value.(ast.String)))
|
||||
|
||||
arr := []*ast.Term{
|
||||
ast.NewTerm(token.decodedHeader),
|
||||
@@ -120,12 +125,12 @@ func builtinJWTDecode(a ast.Value) (ast.Value, error) {
|
||||
ast.StringTerm(sign),
|
||||
}
|
||||
|
||||
return ast.NewArray(arr...), nil
|
||||
return iter(ast.ArrayTerm(arr...))
|
||||
}
|
||||
|
||||
// Implements RS256 JWT signature verification
|
||||
func builtinJWTVerifyRS256(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(args[0].Value, args[1].Value, sha256.New, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
func builtinJWTVerifyRS256(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(operands[0].Value, operands[1].Value, sha256.New, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
return rsa.VerifyPKCS1v15(
|
||||
publicKey,
|
||||
crypto.SHA256,
|
||||
@@ -139,8 +144,8 @@ func builtinJWTVerifyRS256(bctx BuiltinContext, args []*ast.Term, iter func(*ast
|
||||
}
|
||||
|
||||
// Implements RS384 JWT signature verification
|
||||
func builtinJWTVerifyRS384(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(args[0].Value, args[1].Value, sha512.New384, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
func builtinJWTVerifyRS384(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(operands[0].Value, operands[1].Value, sha512.New384, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
return rsa.VerifyPKCS1v15(
|
||||
publicKey,
|
||||
crypto.SHA384,
|
||||
@@ -154,8 +159,8 @@ func builtinJWTVerifyRS384(bctx BuiltinContext, args []*ast.Term, iter func(*ast
|
||||
}
|
||||
|
||||
// Implements RS512 JWT signature verification
|
||||
func builtinJWTVerifyRS512(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(args[0].Value, args[1].Value, sha512.New, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
func builtinJWTVerifyRS512(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(operands[0].Value, operands[1].Value, sha512.New, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
return rsa.VerifyPKCS1v15(
|
||||
publicKey,
|
||||
crypto.SHA512,
|
||||
@@ -169,8 +174,8 @@ func builtinJWTVerifyRS512(bctx BuiltinContext, args []*ast.Term, iter func(*ast
|
||||
}
|
||||
|
||||
// Implements PS256 JWT signature verification
|
||||
func builtinJWTVerifyPS256(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(args[0].Value, args[1].Value, sha256.New, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
func builtinJWTVerifyPS256(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(operands[0].Value, operands[1].Value, sha256.New, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
return rsa.VerifyPSS(
|
||||
publicKey,
|
||||
crypto.SHA256,
|
||||
@@ -185,8 +190,8 @@ func builtinJWTVerifyPS256(bctx BuiltinContext, args []*ast.Term, iter func(*ast
|
||||
}
|
||||
|
||||
// Implements PS384 JWT signature verification
|
||||
func builtinJWTVerifyPS384(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(args[0].Value, args[1].Value, sha512.New384, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
func builtinJWTVerifyPS384(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(operands[0].Value, operands[1].Value, sha512.New384, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
return rsa.VerifyPSS(
|
||||
publicKey,
|
||||
crypto.SHA384,
|
||||
@@ -201,8 +206,8 @@ func builtinJWTVerifyPS384(bctx BuiltinContext, args []*ast.Term, iter func(*ast
|
||||
}
|
||||
|
||||
// Implements PS512 JWT signature verification
|
||||
func builtinJWTVerifyPS512(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(args[0].Value, args[1].Value, sha512.New, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
func builtinJWTVerifyPS512(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerifyRSA(operands[0].Value, operands[1].Value, sha512.New, func(publicKey *rsa.PublicKey, digest []byte, signature []byte) error {
|
||||
return rsa.VerifyPSS(
|
||||
publicKey,
|
||||
crypto.SHA512,
|
||||
@@ -228,8 +233,8 @@ func builtinJWTVerifyRSA(a ast.Value, b ast.Value, hasher func() hash.Hash, veri
|
||||
}
|
||||
|
||||
// Implements ES256 JWT signature verification.
|
||||
func builtinJWTVerifyES256(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerify(args[0].Value, args[1].Value, sha256.New, verifyES)
|
||||
func builtinJWTVerifyES256(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerify(operands[0].Value, operands[1].Value, sha256.New, verifyES)
|
||||
if err == nil {
|
||||
return iter(ast.NewTerm(result))
|
||||
}
|
||||
@@ -237,8 +242,8 @@ func builtinJWTVerifyES256(bctx BuiltinContext, args []*ast.Term, iter func(*ast
|
||||
}
|
||||
|
||||
// Implements ES384 JWT signature verification
|
||||
func builtinJWTVerifyES384(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerify(args[0].Value, args[1].Value, sha512.New384, verifyES)
|
||||
func builtinJWTVerifyES384(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerify(operands[0].Value, operands[1].Value, sha512.New384, verifyES)
|
||||
if err == nil {
|
||||
return iter(ast.NewTerm(result))
|
||||
}
|
||||
@@ -246,8 +251,8 @@ func builtinJWTVerifyES384(bctx BuiltinContext, args []*ast.Term, iter func(*ast
|
||||
}
|
||||
|
||||
// Implements ES512 JWT signature verification
|
||||
func builtinJWTVerifyES512(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerify(args[0].Value, args[1].Value, sha512.New, verifyES)
|
||||
func builtinJWTVerifyES512(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
result, err := builtinJWTVerify(operands[0].Value, operands[1].Value, sha512.New, verifyES)
|
||||
if err == nil {
|
||||
return iter(ast.NewTerm(result))
|
||||
}
|
||||
@@ -408,15 +413,15 @@ func builtinJWTVerify(a ast.Value, b ast.Value, hasher func() hash.Hash, verify
|
||||
}
|
||||
|
||||
// Implements HS256 (secret) JWT signature verification
|
||||
func builtinJWTVerifyHS256(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
func builtinJWTVerifyHS256(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
// Decode the JSON Web Token
|
||||
token, err := decodeJWT(args[0].Value)
|
||||
token, err := decodeJWT(operands[0].Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Process Secret input
|
||||
astSecret, err := builtins.StringOperand(args[1].Value, 2)
|
||||
astSecret, err := builtins.StringOperand(operands[1].Value, 2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -437,15 +442,15 @@ func builtinJWTVerifyHS256(bctx BuiltinContext, args []*ast.Term, iter func(*ast
|
||||
}
|
||||
|
||||
// Implements HS384 JWT signature verification
|
||||
func builtinJWTVerifyHS384(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
func builtinJWTVerifyHS384(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
// Decode the JSON Web Token
|
||||
token, err := decodeJWT(args[0].Value)
|
||||
token, err := decodeJWT(operands[0].Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Process Secret input
|
||||
astSecret, err := builtins.StringOperand(args[1].Value, 2)
|
||||
astSecret, err := builtins.StringOperand(operands[1].Value, 2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -466,15 +471,15 @@ func builtinJWTVerifyHS384(bctx BuiltinContext, args []*ast.Term, iter func(*ast
|
||||
}
|
||||
|
||||
// Implements HS512 JWT signature verification
|
||||
func builtinJWTVerifyHS512(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
func builtinJWTVerifyHS512(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
// Decode the JSON Web Token
|
||||
token, err := decodeJWT(args[0].Value)
|
||||
token, err := decodeJWT(operands[0].Value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Process Secret input
|
||||
astSecret, err := builtins.StringOperand(args[1].Value, 2)
|
||||
astSecret, err := builtins.StringOperand(operands[1].Value, 2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -749,7 +754,7 @@ func verifyHMAC(key interface{}, hash crypto.Hash, payload []byte, signature []b
|
||||
return fmt.Errorf("incorrect symmetric key type")
|
||||
}
|
||||
mac := hmac.New(hash.New, macKey)
|
||||
if _, err := mac.Write([]byte(payload)); err != nil {
|
||||
if _, err := mac.Write(payload); err != nil {
|
||||
return err
|
||||
}
|
||||
if !hmac.Equal(signature, mac.Sum([]byte{})) {
|
||||
@@ -945,26 +950,26 @@ func commonBuiltinJWTEncodeSign(bctx BuiltinContext, inputHeaders, jwsPayload, j
|
||||
|
||||
}
|
||||
|
||||
func builtinJWTEncodeSign(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
func builtinJWTEncodeSign(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
|
||||
inputHeaders := args[0].String()
|
||||
jwsPayload := args[1].String()
|
||||
jwkSrc := args[2].String()
|
||||
inputHeaders := operands[0].String()
|
||||
jwsPayload := operands[1].String()
|
||||
jwkSrc := operands[2].String()
|
||||
return commonBuiltinJWTEncodeSign(bctx, inputHeaders, jwsPayload, jwkSrc, iter)
|
||||
|
||||
}
|
||||
|
||||
func builtinJWTEncodeSignRaw(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
func builtinJWTEncodeSignRaw(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
|
||||
jwkSrc, err := builtins.StringOperand(args[2].Value, 3)
|
||||
jwkSrc, err := builtins.StringOperand(operands[2].Value, 3)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
inputHeaders, err := builtins.StringOperand(args[0].Value, 1)
|
||||
inputHeaders, err := builtins.StringOperand(operands[0].Value, 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
jwsPayload, err := builtins.StringOperand(args[1].Value, 2)
|
||||
jwsPayload, err := builtins.StringOperand(operands[1].Value, 2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -972,7 +977,7 @@ func builtinJWTEncodeSignRaw(bctx BuiltinContext, args []*ast.Term, iter func(*a
|
||||
}
|
||||
|
||||
// Implements full JWT decoding, validation and verification.
|
||||
func builtinJWTDecodeVerify(bctx BuiltinContext, args []*ast.Term, iter func(*ast.Term) error) error {
|
||||
func builtinJWTDecodeVerify(bctx BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error {
|
||||
// io.jwt.decode_verify(string, constraints, [valid, header, payload])
|
||||
//
|
||||
// If valid is true then the signature verifies and all constraints are met.
|
||||
@@ -980,9 +985,9 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, args []*ast.Term, iter func(*as
|
||||
// was not met.
|
||||
//
|
||||
// Decoding errors etc are returned as errors.
|
||||
a := args[0].Value
|
||||
a := operands[0].Value
|
||||
|
||||
b, err := builtins.ObjectOperand(args[1].Value, 2)
|
||||
b, err := builtins.ObjectOperand(operands[1].Value, 2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1000,7 +1005,7 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, args []*ast.Term, iter func(*as
|
||||
return err
|
||||
}
|
||||
var token *JSONWebToken
|
||||
var p ast.Value
|
||||
var p *ast.Term
|
||||
for {
|
||||
// RFC7519 7.2 #1-2 split into parts
|
||||
if token, err = decodeJWT(a); err != nil {
|
||||
@@ -1034,21 +1039,21 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, args []*ast.Term, iter func(*as
|
||||
return err
|
||||
}
|
||||
// RFC7159 7.2 #9-10 decode the payload
|
||||
p, err = builtinBase64UrlDecode(ast.String(token.payload))
|
||||
p, err = getResult(builtinBase64UrlDecode, ast.StringTerm(token.payload))
|
||||
if err != nil {
|
||||
return fmt.Errorf("JWT payload had invalid encoding: %v", err)
|
||||
}
|
||||
// RFC7159 7.2 #8 and 5.2 cty
|
||||
if strings.ToUpper(header.cty) == headerJwt {
|
||||
// Nested JWT, go round again with payload as first argument
|
||||
a = p
|
||||
a = p.Value
|
||||
continue
|
||||
} else {
|
||||
// Non-nested JWT (or we've reached the bottom of the nesting).
|
||||
break
|
||||
}
|
||||
}
|
||||
payload, err := extractJSONObject(string(p.(ast.String)))
|
||||
payload, err := extractJSONObject(string(p.Value.(ast.String)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1077,7 +1082,7 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, args []*ast.Term, iter func(*as
|
||||
switch exp.Value.(type) {
|
||||
case ast.Number:
|
||||
// constraints.time is in nanoseconds but exp Value is in seconds
|
||||
compareTime := ast.FloatNumberTerm(float64(constraints.time) / 1000000000)
|
||||
compareTime := ast.FloatNumberTerm(constraints.time / 1000000000)
|
||||
if ast.Compare(compareTime, exp.Value.(ast.Number)) != -1 {
|
||||
return iter(unverified)
|
||||
}
|
||||
@@ -1090,7 +1095,7 @@ func builtinJWTDecodeVerify(bctx BuiltinContext, args []*ast.Term, iter func(*as
|
||||
switch nbf.Value.(type) {
|
||||
case ast.Number:
|
||||
// constraints.time is in nanoseconds but nbf Value is in seconds
|
||||
compareTime := ast.FloatNumberTerm(float64(constraints.time) / 1000000000)
|
||||
compareTime := ast.FloatNumberTerm(constraints.time / 1000000000)
|
||||
if ast.Compare(compareTime, nbf.Value.(ast.Number)) == -1 {
|
||||
return iter(unverified)
|
||||
}
|
||||
@@ -1130,12 +1135,12 @@ func decodeJWT(a ast.Value) (*JSONWebToken, error) {
|
||||
}
|
||||
|
||||
func (token *JSONWebToken) decodeSignature() (string, error) {
|
||||
decodedSignature, err := builtinBase64UrlDecode(ast.String(token.signature))
|
||||
decodedSignature, err := getResult(builtinBase64UrlDecode, ast.StringTerm(token.signature))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
signatureAst, err := builtins.StringOperand(decodedSignature, 1)
|
||||
signatureAst, err := builtins.StringOperand(decodedSignature.Value, 1)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1169,12 +1174,12 @@ func extractJSONObject(s string) (ast.Object, error) {
|
||||
// to parsing it ourselves, we're relying on the Go implementation
|
||||
// using the last occurring instance of the key, which is the behavior
|
||||
// as of Go 1.8.1.
|
||||
v, err := builtinJSONUnmarshal(ast.String(s))
|
||||
v, err := getResult(builtinJSONUnmarshal, ast.StringTerm(s))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid JSON: %v", err)
|
||||
}
|
||||
|
||||
o, ok := v.(ast.Object)
|
||||
o, ok := v.Value.(ast.Object)
|
||||
if !ok {
|
||||
return nil, errors.New("decoded JSON type was not an Object")
|
||||
}
|
||||
@@ -1190,7 +1195,7 @@ func getInputSHA(input []byte, h func() hash.Hash) []byte {
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterFunctionalBuiltin1(ast.JWTDecode.Name, builtinJWTDecode)
|
||||
RegisterBuiltinFunc(ast.JWTDecode.Name, builtinJWTDecode)
|
||||
RegisterBuiltinFunc(ast.JWTVerifyRS256.Name, builtinJWTVerifyRS256)
|
||||
RegisterBuiltinFunc(ast.JWTVerifyRS384.Name, builtinJWTVerifyRS384)
|
||||
RegisterBuiltinFunc(ast.JWTVerifyRS512.Name, builtinJWTVerifyRS512)
|
||||
|
||||
Reference in New Issue
Block a user