Initial QSfera import
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
load("@rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "base64",
|
||||
srcs = ["base64.go"],
|
||||
importpath = "github.com/lestrrat-go/jwx/v3/internal/base64",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "base64_test",
|
||||
srcs = ["base64_test.go"],
|
||||
embed = [":base64"],
|
||||
deps = ["@com_github_stretchr_testify//require"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":base64",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
//go:build jwx_asmbase64
|
||||
|
||||
package base64
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
asmbase64 "github.com/segmentio/asm/base64"
|
||||
)
|
||||
|
||||
func init() {
|
||||
SetEncoder(asmEncoder{asmbase64.RawURLEncoding})
|
||||
SetDecoder(asmDecoder{})
|
||||
}
|
||||
|
||||
type asmEncoder struct {
|
||||
*asmbase64.Encoding
|
||||
}
|
||||
|
||||
func (e asmEncoder) AppendEncode(dst, src []byte) []byte {
|
||||
n := e.Encoding.EncodedLen(len(src))
|
||||
dst = slices.Grow(dst, n)
|
||||
e.Encoding.Encode(dst[len(dst):][:n], src)
|
||||
return dst[:len(dst)+n]
|
||||
}
|
||||
|
||||
type asmDecoder struct{}
|
||||
|
||||
func (d asmDecoder) Decode(src []byte) ([]byte, error) {
|
||||
var enc *asmbase64.Encoding
|
||||
switch Guess(src) {
|
||||
case Std:
|
||||
enc = asmbase64.StdEncoding
|
||||
case RawStd:
|
||||
enc = asmbase64.RawStdEncoding
|
||||
case URL:
|
||||
enc = asmbase64.URLEncoding
|
||||
case RawURL:
|
||||
enc = asmbase64.RawURLEncoding
|
||||
default:
|
||||
return nil, fmt.Errorf(`invalid encoding`)
|
||||
}
|
||||
|
||||
dst := make([]byte, enc.DecodedLen(len(src)))
|
||||
n, err := enc.Decode(dst, src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`failed to decode source: %w`, err)
|
||||
}
|
||||
return dst[:n], nil
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
package base64
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Decoder interface {
|
||||
Decode([]byte) ([]byte, error)
|
||||
}
|
||||
|
||||
type Encoder interface {
|
||||
Encode([]byte, []byte)
|
||||
EncodedLen(int) int
|
||||
EncodeToString([]byte) string
|
||||
AppendEncode([]byte, []byte) []byte
|
||||
}
|
||||
|
||||
var muEncoder sync.RWMutex
|
||||
var encoder Encoder = base64.RawURLEncoding
|
||||
var muDecoder sync.RWMutex
|
||||
var decoder Decoder = defaultDecoder{}
|
||||
|
||||
func SetEncoder(enc Encoder) {
|
||||
muEncoder.Lock()
|
||||
defer muEncoder.Unlock()
|
||||
encoder = enc
|
||||
}
|
||||
|
||||
func getEncoder() Encoder {
|
||||
muEncoder.RLock()
|
||||
defer muEncoder.RUnlock()
|
||||
return encoder
|
||||
}
|
||||
|
||||
func DefaultEncoder() Encoder {
|
||||
return getEncoder()
|
||||
}
|
||||
|
||||
func SetDecoder(dec Decoder) {
|
||||
muDecoder.Lock()
|
||||
defer muDecoder.Unlock()
|
||||
decoder = dec
|
||||
}
|
||||
|
||||
func getDecoder() Decoder {
|
||||
muDecoder.RLock()
|
||||
defer muDecoder.RUnlock()
|
||||
return decoder
|
||||
}
|
||||
|
||||
func Encode(src []byte) []byte {
|
||||
encoder := getEncoder()
|
||||
dst := make([]byte, encoder.EncodedLen(len(src)))
|
||||
encoder.Encode(dst, src)
|
||||
return dst
|
||||
}
|
||||
|
||||
func EncodeToString(src []byte) string {
|
||||
return getEncoder().EncodeToString(src)
|
||||
}
|
||||
|
||||
func EncodeUint64ToString(v uint64) string {
|
||||
data := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(data, v)
|
||||
|
||||
i := 0
|
||||
for ; i < len(data); i++ {
|
||||
if data[i] != 0x0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return EncodeToString(data[i:])
|
||||
}
|
||||
|
||||
const (
|
||||
InvalidEncoding = iota
|
||||
Std
|
||||
URL
|
||||
RawStd
|
||||
RawURL
|
||||
)
|
||||
|
||||
func Guess(src []byte) int {
|
||||
var isRaw = !bytes.HasSuffix(src, []byte{'='})
|
||||
var isURL = !bytes.ContainsAny(src, "+/")
|
||||
switch {
|
||||
case isRaw && isURL:
|
||||
return RawURL
|
||||
case isURL:
|
||||
return URL
|
||||
case isRaw:
|
||||
return RawStd
|
||||
default:
|
||||
return Std
|
||||
}
|
||||
}
|
||||
|
||||
// defaultDecoder is a Decoder that detects the encoding of the source and
|
||||
// decodes it accordingly. This shouldn't really be required per the spec, but
|
||||
// it exist because we have seen in the wild JWTs that are encoded using
|
||||
// various versions of the base64 encoding.
|
||||
type defaultDecoder struct{}
|
||||
|
||||
func (defaultDecoder) Decode(src []byte) ([]byte, error) {
|
||||
var enc *base64.Encoding
|
||||
|
||||
switch Guess(src) {
|
||||
case RawURL:
|
||||
enc = base64.RawURLEncoding
|
||||
case URL:
|
||||
enc = base64.URLEncoding
|
||||
case RawStd:
|
||||
enc = base64.RawStdEncoding
|
||||
case Std:
|
||||
enc = base64.StdEncoding
|
||||
default:
|
||||
return nil, fmt.Errorf(`invalid encoding`)
|
||||
}
|
||||
|
||||
dst := make([]byte, enc.DecodedLen(len(src)))
|
||||
n, err := enc.Decode(dst, src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`failed to decode source: %w`, err)
|
||||
}
|
||||
return dst[:n], nil
|
||||
}
|
||||
|
||||
func Decode(src []byte) ([]byte, error) {
|
||||
return getDecoder().Decode(src)
|
||||
}
|
||||
|
||||
func DecodeString(src string) ([]byte, error) {
|
||||
return getDecoder().Decode([]byte(src))
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
load("@rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "ecutil",
|
||||
srcs = ["ecutil.go"],
|
||||
importpath = "github.com/lestrrat-go/jwx/v3/internal/ecutil",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":ecutil",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// Package ecutil defines tools that help with elliptic curve related
|
||||
// computation
|
||||
package ecutil
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"math/big"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// size of buffer that needs to be allocated for EC521 curve
|
||||
ec521BufferSize = 66 // (521 / 8) + 1
|
||||
)
|
||||
|
||||
var ecpointBufferPool = sync.Pool{
|
||||
New: func() any {
|
||||
// In most cases the curve bit size will be less than this length
|
||||
// so allocate the maximum, and keep reusing
|
||||
buf := make([]byte, 0, ec521BufferSize)
|
||||
return &buf
|
||||
},
|
||||
}
|
||||
|
||||
func getCrvFixedBuffer(size int) []byte {
|
||||
//nolint:forcetypeassert
|
||||
buf := *(ecpointBufferPool.Get().(*[]byte))
|
||||
if size > ec521BufferSize && cap(buf) < size {
|
||||
buf = append(buf, make([]byte, size-cap(buf))...)
|
||||
}
|
||||
return buf[:size]
|
||||
}
|
||||
|
||||
// ReleaseECPointBuffer releases the []byte buffer allocated.
|
||||
func ReleaseECPointBuffer(buf []byte) {
|
||||
buf = buf[:cap(buf)]
|
||||
buf[0] = 0x0
|
||||
for i := 1; i < len(buf); i *= 2 {
|
||||
copy(buf[i:], buf[:i])
|
||||
}
|
||||
buf = buf[:0]
|
||||
ecpointBufferPool.Put(&buf)
|
||||
}
|
||||
|
||||
func CalculateKeySize(crv elliptic.Curve) int {
|
||||
// We need to create a buffer that fits the entire curve.
|
||||
// If the curve size is 66, that fits in 9 bytes. If the curve
|
||||
// size is 64, it fits in 8 bytes.
|
||||
bits := crv.Params().BitSize
|
||||
|
||||
// For most common cases we know before hand what the byte length
|
||||
// is going to be. optimize
|
||||
var inBytes int
|
||||
switch bits {
|
||||
case 224, 256, 384: // TODO: use constant?
|
||||
inBytes = bits / 8
|
||||
case 521:
|
||||
inBytes = ec521BufferSize
|
||||
default:
|
||||
inBytes = bits / 8
|
||||
if (bits % 8) != 0 {
|
||||
inBytes++
|
||||
}
|
||||
}
|
||||
|
||||
return inBytes
|
||||
}
|
||||
|
||||
// AllocECPointBuffer allocates a buffer for the given point in the given
|
||||
// curve. This buffer should be released using the ReleaseECPointBuffer
|
||||
// function.
|
||||
func AllocECPointBuffer(v *big.Int, crv elliptic.Curve) []byte {
|
||||
buf := getCrvFixedBuffer(CalculateKeySize(crv))
|
||||
v.FillBytes(buf)
|
||||
return buf
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
load("@rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "json",
|
||||
srcs = [
|
||||
"json.go",
|
||||
"registry.go",
|
||||
"stdlib.go",
|
||||
],
|
||||
importpath = "github.com/lestrrat-go/jwx/v3/internal/json",
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = ["//internal/base64"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":json",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
//go:build jwx_goccy
|
||||
|
||||
package json
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
)
|
||||
|
||||
type Decoder = json.Decoder
|
||||
type Delim = json.Delim
|
||||
type Encoder = json.Encoder
|
||||
type Marshaler = json.Marshaler
|
||||
type Number = json.Number
|
||||
type RawMessage = json.RawMessage
|
||||
type Unmarshaler = json.Unmarshaler
|
||||
|
||||
func Engine() string {
|
||||
return "github.com/goccy/go-json"
|
||||
}
|
||||
|
||||
// NewDecoder respects the values specified in DecoderSettings,
|
||||
// and creates a Decoder that has certain features turned on/off
|
||||
func NewDecoder(r io.Reader) *json.Decoder {
|
||||
dec := json.NewDecoder(r)
|
||||
|
||||
if UseNumber() {
|
||||
dec.UseNumber()
|
||||
}
|
||||
|
||||
return dec
|
||||
}
|
||||
|
||||
// NewEncoder is just a proxy for "encoding/json".NewEncoder
|
||||
func NewEncoder(w io.Writer) *json.Encoder {
|
||||
return json.NewEncoder(w)
|
||||
}
|
||||
|
||||
// Marshal is just a proxy for "encoding/json".Marshal
|
||||
func Marshal(v any) ([]byte, error) {
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
// MarshalIndent is just a proxy for "encoding/json".MarshalIndent
|
||||
func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
|
||||
return json.MarshalIndent(v, prefix, indent)
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/lestrrat-go/jwx/v3/internal/base64"
|
||||
)
|
||||
|
||||
var useNumber uint32 // TODO: at some point, change to atomic.Bool
|
||||
|
||||
func UseNumber() bool {
|
||||
return atomic.LoadUint32(&useNumber) == 1
|
||||
}
|
||||
|
||||
// Sets the global configuration for json decoding
|
||||
func DecoderSettings(inUseNumber bool) {
|
||||
var val uint32
|
||||
if inUseNumber {
|
||||
val = 1
|
||||
}
|
||||
atomic.StoreUint32(&useNumber, val)
|
||||
}
|
||||
|
||||
// Unmarshal respects the values specified in DecoderSettings,
|
||||
// and uses a Decoder that has certain features turned on/off
|
||||
func Unmarshal(b []byte, v any) error {
|
||||
dec := NewDecoder(bytes.NewReader(b))
|
||||
return dec.Decode(v)
|
||||
}
|
||||
|
||||
func AssignNextBytesToken(dst *[]byte, dec *Decoder) error {
|
||||
var val string
|
||||
if err := dec.Decode(&val); err != nil {
|
||||
return fmt.Errorf(`error reading next value: %w`, err)
|
||||
}
|
||||
|
||||
buf, err := base64.DecodeString(val)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`expected base64 encoded []byte (%T)`, val)
|
||||
}
|
||||
*dst = buf
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadNextStringToken(dec *Decoder) (string, error) {
|
||||
var val string
|
||||
if err := dec.Decode(&val); err != nil {
|
||||
return "", fmt.Errorf(`error reading next value: %w`, err)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func AssignNextStringToken(dst **string, dec *Decoder) error {
|
||||
val, err := ReadNextStringToken(dec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*dst = &val
|
||||
return nil
|
||||
}
|
||||
|
||||
// FlattenAudience is a flag to specify if we should flatten the "aud"
|
||||
// entry to a string when there's only one entry.
|
||||
// In jwx < 1.1.8 we just dumped everything as an array of strings,
|
||||
// but apparently AWS Cognito doesn't handle this well.
|
||||
//
|
||||
// So now we have the ability to dump "aud" as a string if there's
|
||||
// only one entry, but we need to retain the old behavior so that
|
||||
// we don't accidentally break somebody else's code. (e.g. messing
|
||||
// up how signatures are calculated)
|
||||
var FlattenAudience uint32
|
||||
|
||||
func MarshalAudience(aud []string, flatten bool) ([]byte, error) {
|
||||
var val any
|
||||
if len(aud) == 1 && flatten {
|
||||
val = aud[0]
|
||||
} else {
|
||||
val = aud
|
||||
}
|
||||
return Marshal(val)
|
||||
}
|
||||
|
||||
func EncodeAudience(enc *Encoder, aud []string, flatten bool) error {
|
||||
var val any
|
||||
if len(aud) == 1 && flatten {
|
||||
val = aud[0]
|
||||
} else {
|
||||
val = aud
|
||||
}
|
||||
return enc.Encode(val)
|
||||
}
|
||||
|
||||
// DecodeCtx is an interface for objects that needs that extra something
|
||||
// when decoding JSON into an object.
|
||||
type DecodeCtx interface {
|
||||
Registry() *Registry
|
||||
}
|
||||
|
||||
// DecodeCtxContainer is used to differentiate objects that can carry extra
|
||||
// decoding hints and those who can't.
|
||||
type DecodeCtxContainer interface {
|
||||
DecodeCtx() DecodeCtx
|
||||
SetDecodeCtx(DecodeCtx)
|
||||
}
|
||||
|
||||
// stock decodeCtx. should cover 80% of the cases
|
||||
type decodeCtx struct {
|
||||
registry *Registry
|
||||
}
|
||||
|
||||
func NewDecodeCtx(r *Registry) DecodeCtx {
|
||||
return &decodeCtx{registry: r}
|
||||
}
|
||||
|
||||
func (dc *decodeCtx) Registry() *Registry {
|
||||
return dc.registry
|
||||
}
|
||||
|
||||
func Dump(v any) {
|
||||
enc := NewEncoder(os.Stdout)
|
||||
enc.SetIndent("", " ")
|
||||
//nolint:errchkjson
|
||||
_ = enc.Encode(v)
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package json
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// CustomDecoder is the interface we expect from RegisterCustomField in jws, jwe, jwk, and jwt packages.
|
||||
type CustomDecoder interface {
|
||||
// Decode takes a JSON encoded byte slice and returns the desired
|
||||
// decoded value,which will be used as the value for that field
|
||||
// registered through RegisterCustomField
|
||||
Decode([]byte) (any, error)
|
||||
}
|
||||
|
||||
// CustomDecodeFunc is a stateless, function-based implementation of CustomDecoder
|
||||
type CustomDecodeFunc func([]byte) (any, error)
|
||||
|
||||
func (fn CustomDecodeFunc) Decode(data []byte) (any, error) {
|
||||
return fn(data)
|
||||
}
|
||||
|
||||
type objectTypeDecoder struct {
|
||||
typ reflect.Type
|
||||
name string
|
||||
}
|
||||
|
||||
func (dec *objectTypeDecoder) Decode(data []byte) (any, error) {
|
||||
ptr := reflect.New(dec.typ).Interface()
|
||||
if err := Unmarshal(data, ptr); err != nil {
|
||||
return nil, fmt.Errorf(`failed to decode field %s: %w`, dec.name, err)
|
||||
}
|
||||
return reflect.ValueOf(ptr).Elem().Interface(), nil
|
||||
}
|
||||
|
||||
type Registry struct {
|
||||
mu *sync.RWMutex
|
||||
ctrs map[string]CustomDecoder
|
||||
}
|
||||
|
||||
func NewRegistry() *Registry {
|
||||
return &Registry{
|
||||
mu: &sync.RWMutex{},
|
||||
ctrs: make(map[string]CustomDecoder),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Registry) Register(name string, object any) {
|
||||
if object == nil {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
delete(r.ctrs, name)
|
||||
return
|
||||
}
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
if ctr, ok := object.(CustomDecoder); ok {
|
||||
r.ctrs[name] = ctr
|
||||
} else {
|
||||
r.ctrs[name] = &objectTypeDecoder{
|
||||
typ: reflect.TypeOf(object),
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Registry) Decode(dec *Decoder, name string) (any, error) {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
if ctr, ok := r.ctrs[name]; ok {
|
||||
var raw RawMessage
|
||||
if err := dec.Decode(&raw); err != nil {
|
||||
return nil, fmt.Errorf(`failed to decode field %s: %w`, name, err)
|
||||
}
|
||||
v, err := ctr.Decode([]byte(raw))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(`failed to decode field %s: %w`, name, err)
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
var decoded any
|
||||
if err := dec.Decode(&decoded); err != nil {
|
||||
return nil, fmt.Errorf(`failed to decode field %s: %w`, name, err)
|
||||
}
|
||||
return decoded, nil
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
//go:build !jwx_goccy
|
||||
|
||||
//nolint:revive
|
||||
package json
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Decoder = json.Decoder
|
||||
type Delim = json.Delim
|
||||
type Encoder = json.Encoder
|
||||
type Marshaler = json.Marshaler
|
||||
type Number = json.Number
|
||||
type RawMessage = json.RawMessage
|
||||
type Unmarshaler = json.Unmarshaler
|
||||
|
||||
func Engine() string {
|
||||
return "encoding/json"
|
||||
}
|
||||
|
||||
// NewDecoder respects the values specified in DecoderSettings,
|
||||
// and creates a Decoder that has certain features turned on/off
|
||||
func NewDecoder(r io.Reader) *json.Decoder {
|
||||
dec := json.NewDecoder(r)
|
||||
|
||||
if UseNumber() {
|
||||
dec.UseNumber()
|
||||
}
|
||||
|
||||
return dec
|
||||
}
|
||||
|
||||
func NewEncoder(w io.Writer) *json.Encoder {
|
||||
return json.NewEncoder(w)
|
||||
}
|
||||
|
||||
// Marshal is just a proxy for "encoding/json".Marshal
|
||||
func Marshal(v any) ([]byte, error) {
|
||||
return json.Marshal(v)
|
||||
}
|
||||
|
||||
// MarshalIndent is just a proxy for "encoding/json".MarshalIndent
|
||||
func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
|
||||
return json.MarshalIndent(v, prefix, indent)
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
load("@rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "jwxio",
|
||||
srcs = ["jwxio.go"],
|
||||
importpath = "github.com/lestrrat-go/jwx/v3/internal/jwxio",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package jwxio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var errNonFiniteSource = errors.New(`cannot read from non-finite source`)
|
||||
|
||||
func NonFiniteSourceError() error {
|
||||
return errNonFiniteSource
|
||||
}
|
||||
|
||||
// ReadAllFromFiniteSource reads all data from a io.Reader _if_ it comes from a
|
||||
// finite source.
|
||||
func ReadAllFromFiniteSource(rdr io.Reader) ([]byte, error) {
|
||||
switch rdr.(type) {
|
||||
case *bytes.Reader, *bytes.Buffer, *strings.Reader:
|
||||
data, err := io.ReadAll(rdr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
default:
|
||||
return nil, errNonFiniteSource
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
load("@rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "keyconv",
|
||||
srcs = ["keyconv.go"],
|
||||
importpath = "github.com/lestrrat-go/jwx/v3/internal/keyconv",
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"//jwk",
|
||||
"@com_github_lestrrat_go_blackmagic//:blackmagic",
|
||||
"@org_golang_x_crypto//ed25519",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "keyconv_test",
|
||||
srcs = ["keyconv_test.go"],
|
||||
deps = [
|
||||
":keyconv",
|
||||
"//internal/jwxtest",
|
||||
"//jwa",
|
||||
"//jwk",
|
||||
"@com_github_stretchr_testify//require",
|
||||
],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":keyconv",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
package keyconv
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdh"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/lestrrat-go/blackmagic"
|
||||
"github.com/lestrrat-go/jwx/v3/jwk"
|
||||
)
|
||||
|
||||
// RSAPrivateKey assigns src to dst.
|
||||
// `dst` should be a pointer to a rsa.PrivateKey.
|
||||
// `src` may be rsa.PrivateKey, *rsa.PrivateKey, or a jwk.Key
|
||||
func RSAPrivateKey(dst, src any) error {
|
||||
if jwkKey, ok := src.(jwk.Key); ok {
|
||||
var raw rsa.PrivateKey
|
||||
if err := jwk.Export(jwkKey, &raw); err != nil {
|
||||
return fmt.Errorf(`failed to produce rsa.PrivateKey from %T: %w`, src, err)
|
||||
}
|
||||
src = &raw
|
||||
}
|
||||
|
||||
var ptr *rsa.PrivateKey
|
||||
switch src := src.(type) {
|
||||
case rsa.PrivateKey:
|
||||
ptr = &src
|
||||
case *rsa.PrivateKey:
|
||||
ptr = src
|
||||
default:
|
||||
return fmt.Errorf(`keyconv: expected rsa.PrivateKey or *rsa.PrivateKey, got %T`, src)
|
||||
}
|
||||
|
||||
return blackmagic.AssignIfCompatible(dst, ptr)
|
||||
}
|
||||
|
||||
// RSAPublicKey assigns src to dst
|
||||
// `dst` should be a pointer to a non-zero rsa.PublicKey.
|
||||
// `src` may be rsa.PublicKey, *rsa.PublicKey, or a jwk.Key
|
||||
func RSAPublicKey(dst, src any) error {
|
||||
if jwkKey, ok := src.(jwk.Key); ok {
|
||||
pk, err := jwk.PublicRawKeyOf(jwkKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`keyconv: failed to produce public key from %T: %w`, src, err)
|
||||
}
|
||||
src = pk
|
||||
}
|
||||
|
||||
var ptr *rsa.PublicKey
|
||||
switch src := src.(type) {
|
||||
case rsa.PrivateKey:
|
||||
ptr = &src.PublicKey
|
||||
case *rsa.PrivateKey:
|
||||
ptr = &src.PublicKey
|
||||
case rsa.PublicKey:
|
||||
ptr = &src
|
||||
case *rsa.PublicKey:
|
||||
ptr = src
|
||||
default:
|
||||
return fmt.Errorf(`keyconv: expected rsa.PublicKey/rsa.PrivateKey or *rsa.PublicKey/*rsa.PrivateKey, got %T`, src)
|
||||
}
|
||||
|
||||
return blackmagic.AssignIfCompatible(dst, ptr)
|
||||
}
|
||||
|
||||
// ECDSAPrivateKey assigns src to dst, converting its type from a
|
||||
// non-pointer to a pointer
|
||||
func ECDSAPrivateKey(dst, src any) error {
|
||||
if jwkKey, ok := src.(jwk.Key); ok {
|
||||
var raw ecdsa.PrivateKey
|
||||
if err := jwk.Export(jwkKey, &raw); err != nil {
|
||||
return fmt.Errorf(`keyconv: failed to produce ecdsa.PrivateKey from %T: %w`, src, err)
|
||||
}
|
||||
src = &raw
|
||||
}
|
||||
|
||||
var ptr *ecdsa.PrivateKey
|
||||
switch src := src.(type) {
|
||||
case ecdsa.PrivateKey:
|
||||
ptr = &src
|
||||
case *ecdsa.PrivateKey:
|
||||
ptr = src
|
||||
default:
|
||||
return fmt.Errorf(`keyconv: expected ecdsa.PrivateKey or *ecdsa.PrivateKey, got %T`, src)
|
||||
}
|
||||
return blackmagic.AssignIfCompatible(dst, ptr)
|
||||
}
|
||||
|
||||
// ECDSAPublicKey assigns src to dst, converting its type from a
|
||||
// non-pointer to a pointer
|
||||
func ECDSAPublicKey(dst, src any) error {
|
||||
if jwkKey, ok := src.(jwk.Key); ok {
|
||||
pk, err := jwk.PublicRawKeyOf(jwkKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`keyconv: failed to produce public key from %T: %w`, src, err)
|
||||
}
|
||||
src = pk
|
||||
}
|
||||
|
||||
var ptr *ecdsa.PublicKey
|
||||
switch src := src.(type) {
|
||||
case ecdsa.PrivateKey:
|
||||
ptr = &src.PublicKey
|
||||
case *ecdsa.PrivateKey:
|
||||
ptr = &src.PublicKey
|
||||
case ecdsa.PublicKey:
|
||||
ptr = &src
|
||||
case *ecdsa.PublicKey:
|
||||
ptr = src
|
||||
default:
|
||||
return fmt.Errorf(`keyconv: expected ecdsa.PublicKey/ecdsa.PrivateKey or *ecdsa.PublicKey/*ecdsa.PrivateKey, got %T`, src)
|
||||
}
|
||||
return blackmagic.AssignIfCompatible(dst, ptr)
|
||||
}
|
||||
|
||||
func ByteSliceKey(dst, src any) error {
|
||||
if jwkKey, ok := src.(jwk.Key); ok {
|
||||
var raw []byte
|
||||
if err := jwk.Export(jwkKey, &raw); err != nil {
|
||||
return fmt.Errorf(`keyconv: failed to produce []byte from %T: %w`, src, err)
|
||||
}
|
||||
src = raw
|
||||
}
|
||||
|
||||
if _, ok := src.([]byte); !ok {
|
||||
return fmt.Errorf(`keyconv: expected []byte, got %T`, src)
|
||||
}
|
||||
return blackmagic.AssignIfCompatible(dst, src)
|
||||
}
|
||||
|
||||
func Ed25519PrivateKey(dst, src any) error {
|
||||
if jwkKey, ok := src.(jwk.Key); ok {
|
||||
var raw ed25519.PrivateKey
|
||||
if err := jwk.Export(jwkKey, &raw); err != nil {
|
||||
return fmt.Errorf(`failed to produce ed25519.PrivateKey from %T: %w`, src, err)
|
||||
}
|
||||
src = &raw
|
||||
}
|
||||
|
||||
var ptr *ed25519.PrivateKey
|
||||
switch src := src.(type) {
|
||||
case ed25519.PrivateKey:
|
||||
ptr = &src
|
||||
case *ed25519.PrivateKey:
|
||||
ptr = src
|
||||
default:
|
||||
return fmt.Errorf(`expected ed25519.PrivateKey or *ed25519.PrivateKey, got %T`, src)
|
||||
}
|
||||
return blackmagic.AssignIfCompatible(dst, ptr)
|
||||
}
|
||||
|
||||
func Ed25519PublicKey(dst, src any) error {
|
||||
if jwkKey, ok := src.(jwk.Key); ok {
|
||||
pk, err := jwk.PublicRawKeyOf(jwkKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`keyconv: failed to produce public key from %T: %w`, src, err)
|
||||
}
|
||||
src = pk
|
||||
}
|
||||
|
||||
switch key := src.(type) {
|
||||
case ed25519.PrivateKey:
|
||||
src = key.Public()
|
||||
case *ed25519.PrivateKey:
|
||||
src = key.Public()
|
||||
}
|
||||
|
||||
var ptr *ed25519.PublicKey
|
||||
switch src := src.(type) {
|
||||
case ed25519.PublicKey:
|
||||
ptr = &src
|
||||
case *ed25519.PublicKey:
|
||||
ptr = src
|
||||
case *crypto.PublicKey:
|
||||
tmp, ok := (*src).(ed25519.PublicKey)
|
||||
if !ok {
|
||||
return fmt.Errorf(`failed to retrieve ed25519.PublicKey out of *crypto.PublicKey`)
|
||||
}
|
||||
ptr = &tmp
|
||||
case crypto.PublicKey:
|
||||
tmp, ok := src.(ed25519.PublicKey)
|
||||
if !ok {
|
||||
return fmt.Errorf(`failed to retrieve ed25519.PublicKey out of crypto.PublicKey`)
|
||||
}
|
||||
ptr = &tmp
|
||||
default:
|
||||
return fmt.Errorf(`expected ed25519.PublicKey or *ed25519.PublicKey, got %T`, src)
|
||||
}
|
||||
return blackmagic.AssignIfCompatible(dst, ptr)
|
||||
}
|
||||
|
||||
type privECDHer interface {
|
||||
ECDH() (*ecdh.PrivateKey, error)
|
||||
}
|
||||
|
||||
func ECDHPrivateKey(dst, src any) error {
|
||||
var privECDH *ecdh.PrivateKey
|
||||
if jwkKey, ok := src.(jwk.Key); ok {
|
||||
var rawECDH ecdh.PrivateKey
|
||||
if err := jwk.Export(jwkKey, &rawECDH); err == nil {
|
||||
privECDH = &rawECDH
|
||||
} else {
|
||||
// If we cannot export the key as an ecdh.PrivateKey, we try to export it as an ecdsa.PrivateKey
|
||||
var rawECDSA ecdsa.PrivateKey
|
||||
if err := jwk.Export(jwkKey, &rawECDSA); err != nil {
|
||||
return fmt.Errorf(`keyconv: failed to produce ecdh.PrivateKey or ecdsa.PrivateKey from %T: %w`, src, err)
|
||||
}
|
||||
src = &rawECDSA
|
||||
}
|
||||
}
|
||||
|
||||
switch src := src.(type) {
|
||||
case ecdh.PrivateKey:
|
||||
privECDH = &src
|
||||
case *ecdh.PrivateKey:
|
||||
privECDH = src
|
||||
case privECDHer:
|
||||
priv, err := src.ECDH()
|
||||
if err != nil {
|
||||
return fmt.Errorf(`keyconv: failed to convert ecdsa.PrivateKey to ecdh.PrivateKey: %w`, err)
|
||||
}
|
||||
privECDH = priv
|
||||
}
|
||||
|
||||
return blackmagic.AssignIfCompatible(dst, privECDH)
|
||||
}
|
||||
|
||||
type pubECDHer interface {
|
||||
ECDH() (*ecdh.PublicKey, error)
|
||||
}
|
||||
|
||||
func ECDHPublicKey(dst, src any) error {
|
||||
var pubECDH *ecdh.PublicKey
|
||||
if jwkKey, ok := src.(jwk.Key); ok {
|
||||
var rawECDH ecdh.PublicKey
|
||||
if err := jwk.Export(jwkKey, &rawECDH); err == nil {
|
||||
pubECDH = &rawECDH
|
||||
} else {
|
||||
// If we cannot export the key as an ecdh.PublicKey, we try to export it as an ecdsa.PublicKey
|
||||
var rawECDSA ecdsa.PublicKey
|
||||
if err := jwk.Export(jwkKey, &rawECDSA); err != nil {
|
||||
return fmt.Errorf(`keyconv: failed to produce ecdh.PublicKey or ecdsa.PublicKey from %T: %w`, src, err)
|
||||
}
|
||||
src = &rawECDSA
|
||||
}
|
||||
}
|
||||
|
||||
switch src := src.(type) {
|
||||
case ecdh.PublicKey:
|
||||
pubECDH = &src
|
||||
case *ecdh.PublicKey:
|
||||
pubECDH = src
|
||||
case pubECDHer:
|
||||
pub, err := src.ECDH()
|
||||
if err != nil {
|
||||
return fmt.Errorf(`keyconv: failed to convert ecdsa.PublicKey to ecdh.PublicKey: %w`, err)
|
||||
}
|
||||
pubECDH = pub
|
||||
}
|
||||
|
||||
return blackmagic.AssignIfCompatible(dst, pubECDH)
|
||||
}
|
||||
|
||||
// ecdhCurveToElliptic maps ECDH curves to elliptic curves
|
||||
func ecdhCurveToElliptic(ecdhCurve ecdh.Curve) (elliptic.Curve, error) {
|
||||
switch ecdhCurve {
|
||||
case ecdh.P256():
|
||||
return elliptic.P256(), nil
|
||||
case ecdh.P384():
|
||||
return elliptic.P384(), nil
|
||||
case ecdh.P521():
|
||||
return elliptic.P521(), nil
|
||||
default:
|
||||
return nil, fmt.Errorf(`keyconv: unsupported ECDH curve: %v`, ecdhCurve)
|
||||
}
|
||||
}
|
||||
|
||||
// ecdhPublicKeyToECDSA converts an ECDH public key to an ECDSA public key
|
||||
func ecdhPublicKeyToECDSA(ecdhPubKey *ecdh.PublicKey) (*ecdsa.PublicKey, error) {
|
||||
curve, err := ecdhCurveToElliptic(ecdhPubKey.Curve())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pubBytes := ecdhPubKey.Bytes()
|
||||
|
||||
// Parse the uncompressed point format (0x04 prefix + X + Y coordinates)
|
||||
if len(pubBytes) == 0 || pubBytes[0] != 0x04 {
|
||||
return nil, fmt.Errorf(`keyconv: invalid ECDH public key format`)
|
||||
}
|
||||
|
||||
keyLen := (len(pubBytes) - 1) / 2
|
||||
if len(pubBytes) != 1+2*keyLen {
|
||||
return nil, fmt.Errorf(`keyconv: invalid ECDH public key length`)
|
||||
}
|
||||
|
||||
x := new(big.Int).SetBytes(pubBytes[1 : 1+keyLen])
|
||||
y := new(big.Int).SetBytes(pubBytes[1+keyLen:])
|
||||
|
||||
return &ecdsa.PublicKey{
|
||||
Curve: curve,
|
||||
X: x,
|
||||
Y: y,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ECDHToECDSA(dst, src any) error {
|
||||
// convert ecdh.PublicKey to ecdsa.PublicKey, ecdh.PrivateKey to ecdsa.PrivateKey
|
||||
|
||||
// First, handle value types by converting to pointers
|
||||
switch s := src.(type) {
|
||||
case ecdh.PrivateKey:
|
||||
src = &s
|
||||
case ecdh.PublicKey:
|
||||
src = &s
|
||||
}
|
||||
|
||||
var privBytes []byte
|
||||
var pubkey *ecdh.PublicKey
|
||||
// Now handle the actual conversion with pointer types
|
||||
switch src := src.(type) {
|
||||
case *ecdh.PrivateKey:
|
||||
pubkey = src.PublicKey()
|
||||
privBytes = src.Bytes()
|
||||
case *ecdh.PublicKey:
|
||||
pubkey = src
|
||||
default:
|
||||
return fmt.Errorf(`keyconv: expected ecdh.PrivateKey, *ecdh.PrivateKey, ecdh.PublicKey, or *ecdh.PublicKey, got %T`, src)
|
||||
}
|
||||
|
||||
// convert the public key
|
||||
ecdsaPubKey, err := ecdhPublicKeyToECDSA(pubkey)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`keyconv.ECDHToECDSA: failed to convert ECDH public key to ECDSA public key: %w`, err)
|
||||
}
|
||||
|
||||
// return if we were being asked to convert *ecdh.PublicKey
|
||||
if privBytes == nil {
|
||||
return blackmagic.AssignIfCompatible(dst, ecdsaPubKey)
|
||||
}
|
||||
|
||||
// Then create the private key with the public key embedded
|
||||
ecdsaPrivKey := &ecdsa.PrivateKey{
|
||||
D: new(big.Int).SetBytes(privBytes),
|
||||
PublicKey: *ecdsaPubKey,
|
||||
}
|
||||
|
||||
return blackmagic.AssignIfCompatible(dst, ecdsaPrivKey)
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
load("@rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "pool",
|
||||
srcs = [
|
||||
"big_int.go",
|
||||
"byte_slice.go",
|
||||
"bytes_buffer.go",
|
||||
"error_slice.go",
|
||||
"key_to_error_map.go",
|
||||
"pool.go",
|
||||
],
|
||||
importpath = "github.com/lestrrat-go/jwx/v3/internal/pool",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":pool",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "pool_test",
|
||||
srcs = [
|
||||
"byte_slice_test.go",
|
||||
],
|
||||
deps = [
|
||||
":pool",
|
||||
"@com_github_stretchr_testify//require",
|
||||
],
|
||||
)
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package pool
|
||||
|
||||
import "math/big"
|
||||
|
||||
var bigIntPool = New[*big.Int](allocBigInt, freeBigInt)
|
||||
|
||||
func allocBigInt() *big.Int {
|
||||
return &big.Int{}
|
||||
}
|
||||
|
||||
func freeBigInt(b *big.Int) *big.Int {
|
||||
b.SetInt64(0) // Reset the value to zero
|
||||
return b
|
||||
}
|
||||
|
||||
// BigInt returns a pool of *big.Int instances.
|
||||
func BigInt() *Pool[*big.Int] {
|
||||
return bigIntPool
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package pool
|
||||
|
||||
var byteSlicePool = SlicePool[byte]{
|
||||
pool: New[[]byte](allocByteSlice, freeByteSlice),
|
||||
}
|
||||
|
||||
func allocByteSlice() []byte {
|
||||
return make([]byte, 0, 64) // Default capacity of 64 bytes
|
||||
}
|
||||
|
||||
func freeByteSlice(b []byte) []byte {
|
||||
clear(b)
|
||||
b = b[:0] // Reset the slice to zero length
|
||||
return b
|
||||
}
|
||||
|
||||
func ByteSlice() SlicePool[byte] {
|
||||
return byteSlicePool
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package pool
|
||||
|
||||
import "bytes"
|
||||
|
||||
var bytesBufferPool = New[*bytes.Buffer](allocBytesBuffer, freeBytesBuffer)
|
||||
|
||||
func allocBytesBuffer() *bytes.Buffer {
|
||||
return &bytes.Buffer{}
|
||||
}
|
||||
|
||||
func freeBytesBuffer(b *bytes.Buffer) *bytes.Buffer {
|
||||
b.Reset()
|
||||
return b
|
||||
}
|
||||
|
||||
func BytesBuffer() *Pool[*bytes.Buffer] {
|
||||
return bytesBufferPool
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package pool
|
||||
|
||||
var errorSlicePool = New[[]error](allocErrorSlice, freeErrorSlice)
|
||||
|
||||
func allocErrorSlice() []error {
|
||||
return make([]error, 0, 1)
|
||||
}
|
||||
|
||||
func freeErrorSlice(s []error) []error {
|
||||
// Reset the slice to its zero value
|
||||
return s[:0]
|
||||
}
|
||||
|
||||
func ErrorSlice() *Pool[[]error] {
|
||||
return errorSlicePool
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package pool
|
||||
|
||||
var keyToErrorMapPool = New[map[string]error](allocKeyToErrorMap, freeKeyToErrorMap)
|
||||
|
||||
func allocKeyToErrorMap() map[string]error {
|
||||
return make(map[string]error)
|
||||
}
|
||||
|
||||
func freeKeyToErrorMap(m map[string]error) map[string]error {
|
||||
for k := range m {
|
||||
delete(m, k) // Clear the map
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// KeyToErrorMap returns a pool of map[string]error instances.
|
||||
func KeyToErrorMap() *Pool[map[string]error] {
|
||||
return keyToErrorMapPool
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package pool
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Pool[T any] struct {
|
||||
pool sync.Pool
|
||||
destructor func(T) T
|
||||
}
|
||||
|
||||
// New creates a new Pool instance for the type T.
|
||||
// The allocator function is used to create new instances of T when the pool is empty.
|
||||
// The destructor function is used to clean up instances of T before they are returned to the pool.
|
||||
// The destructor should reset the state of T to a clean state, so it can be reused, and
|
||||
// return the modified instance of T. This is required for cases when you reset operations
|
||||
// can modify the underlying data structure, such as slices or maps.
|
||||
func New[T any](allocator func() T, destructor func(T) T) *Pool[T] {
|
||||
return &Pool[T]{
|
||||
pool: sync.Pool{
|
||||
New: func() any {
|
||||
return allocator()
|
||||
},
|
||||
},
|
||||
destructor: destructor,
|
||||
}
|
||||
}
|
||||
|
||||
// Get retrieves an item of type T from the pool.
|
||||
func (p *Pool[T]) Get() T {
|
||||
//nolint:forcetypeassert
|
||||
return p.pool.Get().(T)
|
||||
}
|
||||
|
||||
// Put returns an item of type T to the pool.
|
||||
// The item is first processed by the destructor function to ensure it is in a clean state.
|
||||
func (p *Pool[T]) Put(item T) {
|
||||
p.pool.Put(p.destructor(item))
|
||||
}
|
||||
|
||||
// SlicePool is a specialized pool for slices of type T. It is identical to Pool[T] but
|
||||
// provides additional functionality to get slices with a specific capacity.
|
||||
type SlicePool[T any] struct {
|
||||
pool *Pool[[]T]
|
||||
}
|
||||
|
||||
func NewSlicePool[T any](allocator func() []T, destructor func([]T) []T) SlicePool[T] {
|
||||
return SlicePool[T]{
|
||||
pool: New(allocator, destructor),
|
||||
}
|
||||
}
|
||||
|
||||
func (p SlicePool[T]) Get() []T {
|
||||
return p.pool.Get()
|
||||
}
|
||||
|
||||
func (p SlicePool[T]) GetCapacity(capacity int) []T {
|
||||
if capacity <= 0 {
|
||||
return p.Get()
|
||||
}
|
||||
s := p.Get()
|
||||
if cap(s) < capacity {
|
||||
s = make([]T, 0, capacity)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (p SlicePool[T]) Put(s []T) {
|
||||
p.pool.Put(s)
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
load("@rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "tokens",
|
||||
srcs = [
|
||||
"jwe_tokens.go",
|
||||
"tokens.go",
|
||||
],
|
||||
importpath = "github.com/lestrrat-go/jwx/v3/internal/tokens",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":tokens",
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package tokens
|
||||
|
||||
// JWE Key Encryption Algorithms
|
||||
const (
|
||||
// RSA algorithms
|
||||
RSA1_5 = "RSA1_5"
|
||||
RSA_OAEP = "RSA-OAEP"
|
||||
RSA_OAEP_256 = "RSA-OAEP-256"
|
||||
RSA_OAEP_384 = "RSA-OAEP-384"
|
||||
RSA_OAEP_512 = "RSA-OAEP-512"
|
||||
|
||||
// AES Key Wrap algorithms
|
||||
A128KW = "A128KW"
|
||||
A192KW = "A192KW"
|
||||
A256KW = "A256KW"
|
||||
|
||||
// AES GCM Key Wrap algorithms
|
||||
A128GCMKW = "A128GCMKW"
|
||||
A192GCMKW = "A192GCMKW"
|
||||
A256GCMKW = "A256GCMKW"
|
||||
|
||||
// ECDH-ES algorithms
|
||||
ECDH_ES = "ECDH-ES"
|
||||
ECDH_ES_A128KW = "ECDH-ES+A128KW"
|
||||
ECDH_ES_A192KW = "ECDH-ES+A192KW"
|
||||
ECDH_ES_A256KW = "ECDH-ES+A256KW"
|
||||
|
||||
// PBES2 algorithms
|
||||
PBES2_HS256_A128KW = "PBES2-HS256+A128KW"
|
||||
PBES2_HS384_A192KW = "PBES2-HS384+A192KW"
|
||||
PBES2_HS512_A256KW = "PBES2-HS512+A256KW"
|
||||
|
||||
// Direct key agreement
|
||||
DIRECT = "dir"
|
||||
)
|
||||
|
||||
// JWE Content Encryption Algorithms
|
||||
const (
|
||||
// AES GCM algorithms
|
||||
A128GCM = "A128GCM"
|
||||
A192GCM = "A192GCM"
|
||||
A256GCM = "A256GCM"
|
||||
|
||||
// AES CBC + HMAC algorithms
|
||||
A128CBC_HS256 = "A128CBC-HS256"
|
||||
A192CBC_HS384 = "A192CBC-HS384"
|
||||
A256CBC_HS512 = "A256CBC-HS512"
|
||||
)
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
package tokens
|
||||
|
||||
const (
|
||||
CloseCurlyBracket = '}'
|
||||
CloseSquareBracket = ']'
|
||||
Colon = ':'
|
||||
Comma = ','
|
||||
DoubleQuote = '"'
|
||||
OpenCurlyBracket = '{'
|
||||
OpenSquareBracket = '['
|
||||
Period = '.'
|
||||
)
|
||||
|
||||
// Cryptographic key sizes
|
||||
const (
|
||||
KeySize16 = 16
|
||||
KeySize24 = 24
|
||||
KeySize32 = 32
|
||||
KeySize48 = 48 // A192CBC_HS384 key size
|
||||
KeySize64 = 64 // A256CBC_HS512 key size
|
||||
)
|
||||
|
||||
// Bit/byte conversion factors
|
||||
const (
|
||||
BitsPerByte = 8
|
||||
BytesPerBit = 1.0 / 8
|
||||
)
|
||||
|
||||
// Key wrapping constants
|
||||
const (
|
||||
KeywrapChunkLen = 8
|
||||
KeywrapRounds = 6 // RFC 3394 key wrap rounds
|
||||
KeywrapBlockSize = 8 // Key wrap block size in bytes
|
||||
)
|
||||
|
||||
// AES-GCM constants
|
||||
const (
|
||||
GCMIVSize = 12 // GCM IV size in bytes (96 bits)
|
||||
GCMTagSize = 16 // GCM tag size in bytes (128 bits)
|
||||
)
|
||||
|
||||
// PBES2 constants
|
||||
const (
|
||||
PBES2DefaultIterations = 10000 // Default PBKDF2 iteration count
|
||||
PBES2NullByteSeparator = 0 // Null byte separator for PBES2
|
||||
)
|
||||
|
||||
// RSA key generation constants
|
||||
const (
|
||||
RSAKeyGenMultiplier = 2 // RSA key generation size multiplier
|
||||
)
|
||||
Reference in New Issue
Block a user