21
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/LICENSE
generated
vendored
Normal file
21
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 lestrrat
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
113
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/buffer/buffer.go
generated
vendored
Normal file
113
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/buffer/buffer.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
// Package buffer provides a very thin wrapper around []byte buffer called
|
||||
// `Buffer`, to provide functionalities that are often used within the jwx
|
||||
// related packages
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Buffer wraps `[]byte` and provides functions that are often used in
|
||||
// the jwx related packages. One notable difference is that while
|
||||
// encoding/json marshalls `[]byte` using base64.StdEncoding, this
|
||||
// module uses base64.RawURLEncoding as mandated by the spec
|
||||
type Buffer []byte
|
||||
|
||||
// FromUint creates a `Buffer` from an unsigned int
|
||||
func FromUint(v uint64) Buffer {
|
||||
data := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(data, v)
|
||||
|
||||
i := 0
|
||||
for ; i < len(data); i++ {
|
||||
if data[i] != 0x0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return Buffer(data[i:])
|
||||
}
|
||||
|
||||
// FromBase64 constructs a new Buffer from a base64 encoded data
|
||||
func FromBase64(v []byte) (Buffer, error) {
|
||||
b := Buffer{}
|
||||
if err := b.Base64Decode(v); err != nil {
|
||||
return Buffer(nil), errors.Wrap(err, "failed to decode from base64")
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// FromNData constructs a new Buffer from a "n:data" format
|
||||
// (I made that name up)
|
||||
func FromNData(v []byte) (Buffer, error) {
|
||||
size := binary.BigEndian.Uint32(v)
|
||||
buf := make([]byte, int(size))
|
||||
copy(buf, v[4:4+size])
|
||||
return Buffer(buf), nil
|
||||
}
|
||||
|
||||
// Bytes returns the raw bytes that comprises the Buffer
|
||||
func (b Buffer) Bytes() []byte {
|
||||
return []byte(b)
|
||||
}
|
||||
|
||||
// NData returns Datalen || Data, where Datalen is a 32 bit counter for
|
||||
// the length of the following data, and Data is the octets that comprise
|
||||
// the buffer data
|
||||
func (b Buffer) NData() []byte {
|
||||
buf := make([]byte, 4+b.Len())
|
||||
binary.BigEndian.PutUint32(buf, uint32(b.Len()))
|
||||
|
||||
copy(buf[4:], b.Bytes())
|
||||
return buf
|
||||
}
|
||||
|
||||
// Len returns the number of bytes that the Buffer holds
|
||||
func (b Buffer) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
// Base64Encode encodes the contents of the Buffer using base64.RawURLEncoding
|
||||
func (b Buffer) Base64Encode() ([]byte, error) {
|
||||
enc := base64.RawURLEncoding
|
||||
out := make([]byte, enc.EncodedLen(len(b)))
|
||||
enc.Encode(out, b)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// Base64Decode decodes the contents of the Buffer using base64.RawURLEncoding
|
||||
func (b *Buffer) Base64Decode(v []byte) error {
|
||||
enc := base64.RawURLEncoding
|
||||
out := make([]byte, enc.DecodedLen(len(v)))
|
||||
n, err := enc.Decode(out, v)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to decode from base64")
|
||||
}
|
||||
out = out[:n]
|
||||
*b = Buffer(out)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON marshals the buffer into JSON format after encoding the buffer
|
||||
// with base64.RawURLEncoding
|
||||
func (b Buffer) MarshalJSON() ([]byte, error) {
|
||||
v, err := b.Base64Encode()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to encode to base64")
|
||||
}
|
||||
return json.Marshal(string(v))
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from a JSON string into a Buffer, after decoding it
|
||||
// with base64.RawURLEncoding
|
||||
func (b *Buffer) UnmarshalJSON(data []byte) error {
|
||||
var x string
|
||||
if err := json.Unmarshal(data, &x); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal JSON")
|
||||
}
|
||||
return b.Base64Decode([]byte(x))
|
||||
}
|
||||
11
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwa/elliptic.go
generated
vendored
Normal file
11
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwa/elliptic.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package jwa
|
||||
|
||||
// EllipticCurveAlgorithm represents the algorithms used for EC keys
|
||||
type EllipticCurveAlgorithm string
|
||||
|
||||
// Supported values for EllipticCurveAlgorithm
|
||||
const (
|
||||
P256 EllipticCurveAlgorithm = "P-256"
|
||||
P384 EllipticCurveAlgorithm = "P-384"
|
||||
P521 EllipticCurveAlgorithm = "P-521"
|
||||
)
|
||||
67
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwa/key_type.go
generated
vendored
Normal file
67
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwa/key_type.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package jwa
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// KeyType represents the key type ("kty") that are supported
|
||||
type KeyType string
|
||||
|
||||
var keyTypeAlg = map[string]struct{}{"EC": {}, "oct": {}, "RSA": {}}
|
||||
|
||||
// Supported values for KeyType
|
||||
const (
|
||||
EC KeyType = "EC" // Elliptic Curve
|
||||
InvalidKeyType KeyType = "" // Invalid KeyType
|
||||
OctetSeq KeyType = "oct" // Octet sequence (used to represent symmetric keys)
|
||||
RSA KeyType = "RSA" // RSA
|
||||
)
|
||||
|
||||
// Accept is used when conversion from values given by
|
||||
// outside sources (such as JSON payloads) is required
|
||||
func (keyType *KeyType) Accept(value interface{}) error {
|
||||
var tmp KeyType
|
||||
switch x := value.(type) {
|
||||
case string:
|
||||
tmp = KeyType(x)
|
||||
case KeyType:
|
||||
tmp = x
|
||||
default:
|
||||
return errors.Errorf(`invalid type for jwa.KeyType: %T`, value)
|
||||
}
|
||||
_, ok := keyTypeAlg[tmp.String()]
|
||||
if !ok {
|
||||
return errors.Errorf("Unknown Key Type algorithm")
|
||||
}
|
||||
|
||||
*keyType = tmp
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the string representation of a KeyType
|
||||
func (keyType KeyType) String() string {
|
||||
return string(keyType)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals and checks data as KeyType Algorithm
|
||||
func (keyType *KeyType) UnmarshalJSON(data []byte) error {
|
||||
var quote byte = '"'
|
||||
var quoted string
|
||||
if data[0] == quote {
|
||||
var err error
|
||||
quoted, err = strconv.Unquote(string(data))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to process signature algorithm")
|
||||
}
|
||||
} else {
|
||||
quoted = string(data)
|
||||
}
|
||||
_, ok := keyTypeAlg[quoted]
|
||||
if !ok {
|
||||
return errors.Errorf("Unknown signature algorithm")
|
||||
}
|
||||
*keyType = KeyType(quoted)
|
||||
return nil
|
||||
}
|
||||
29
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwa/parameters.go
generated
vendored
Normal file
29
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwa/parameters.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package jwa
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/buffer"
|
||||
)
|
||||
|
||||
// EllipticCurve provides a indirect type to standard elliptic curve such that we can
|
||||
// use it for unmarshal
|
||||
type EllipticCurve struct {
|
||||
elliptic.Curve
|
||||
}
|
||||
|
||||
// AlgorithmParameters provides a single structure suitable to unmarshaling any JWK
|
||||
type AlgorithmParameters struct {
|
||||
N buffer.Buffer `json:"n,omitempty"`
|
||||
E buffer.Buffer `json:"e,omitempty"`
|
||||
D buffer.Buffer `json:"d,omitempty"`
|
||||
P buffer.Buffer `json:"p,omitempty"`
|
||||
Q buffer.Buffer `json:"q,omitempty"`
|
||||
Dp buffer.Buffer `json:"dp,omitempty"`
|
||||
Dq buffer.Buffer `json:"dq,omitempty"`
|
||||
Qi buffer.Buffer `json:"qi,omitempty"`
|
||||
Crv EllipticCurveAlgorithm `json:"crv,omitempty"`
|
||||
X buffer.Buffer `json:"x,omitempty"`
|
||||
Y buffer.Buffer `json:"y,omitempty"`
|
||||
K buffer.Buffer `json:"k,omitempty"`
|
||||
}
|
||||
76
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwa/signature.go
generated
vendored
Normal file
76
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwa/signature.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package jwa
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// SignatureAlgorithm represents the various signature algorithms as described in https://tools.ietf.org/html/rfc7518#section-3.1
|
||||
type SignatureAlgorithm string
|
||||
|
||||
var signatureAlg = map[string]struct{}{"ES256": {}, "ES384": {}, "ES512": {}, "HS256": {}, "HS384": {}, "HS512": {}, "PS256": {}, "PS384": {}, "PS512": {}, "RS256": {}, "RS384": {}, "RS512": {}, "none": {}}
|
||||
|
||||
// Supported values for SignatureAlgorithm
|
||||
const (
|
||||
ES256 SignatureAlgorithm = "ES256" // ECDSA using P-256 and SHA-256
|
||||
ES384 SignatureAlgorithm = "ES384" // ECDSA using P-384 and SHA-384
|
||||
ES512 SignatureAlgorithm = "ES512" // ECDSA using P-521 and SHA-512
|
||||
HS256 SignatureAlgorithm = "HS256" // HMAC using SHA-256
|
||||
HS384 SignatureAlgorithm = "HS384" // HMAC using SHA-384
|
||||
HS512 SignatureAlgorithm = "HS512" // HMAC using SHA-512
|
||||
NoSignature SignatureAlgorithm = "none"
|
||||
PS256 SignatureAlgorithm = "PS256" // RSASSA-PSS using SHA256 and MGF1-SHA256
|
||||
PS384 SignatureAlgorithm = "PS384" // RSASSA-PSS using SHA384 and MGF1-SHA384
|
||||
PS512 SignatureAlgorithm = "PS512" // RSASSA-PSS using SHA512 and MGF1-SHA512
|
||||
RS256 SignatureAlgorithm = "RS256" // RSASSA-PKCS-v1.5 using SHA-256
|
||||
RS384 SignatureAlgorithm = "RS384" // RSASSA-PKCS-v1.5 using SHA-384
|
||||
RS512 SignatureAlgorithm = "RS512" // RSASSA-PKCS-v1.5 using SHA-512
|
||||
NoValue SignatureAlgorithm = "" // No value is different from none
|
||||
)
|
||||
|
||||
// Accept is used when conversion from values given by
|
||||
// outside sources (such as JSON payloads) is required
|
||||
func (signature *SignatureAlgorithm) Accept(value interface{}) error {
|
||||
var tmp SignatureAlgorithm
|
||||
switch x := value.(type) {
|
||||
case string:
|
||||
tmp = SignatureAlgorithm(x)
|
||||
case SignatureAlgorithm:
|
||||
tmp = x
|
||||
default:
|
||||
return errors.Errorf(`invalid type for jwa.SignatureAlgorithm: %T`, value)
|
||||
}
|
||||
_, ok := signatureAlg[tmp.String()]
|
||||
if !ok {
|
||||
return errors.Errorf("Unknown signature algorithm")
|
||||
}
|
||||
*signature = tmp
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the string representation of a SignatureAlgorithm
|
||||
func (signature SignatureAlgorithm) String() string {
|
||||
return string(signature)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals and checks data as Signature Algorithm
|
||||
func (signature *SignatureAlgorithm) UnmarshalJSON(data []byte) error {
|
||||
var quote byte = '"'
|
||||
var quoted string
|
||||
if data[0] == quote {
|
||||
var err error
|
||||
quoted, err = strconv.Unquote(string(data))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to process signature algorithm")
|
||||
}
|
||||
} else {
|
||||
quoted = string(data)
|
||||
}
|
||||
_, ok := signatureAlg[quoted]
|
||||
if !ok {
|
||||
return errors.Errorf("Unknown signature algorithm")
|
||||
}
|
||||
*signature = SignatureAlgorithm(quoted)
|
||||
return nil
|
||||
}
|
||||
120
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/ecdsa.go
generated
vendored
Normal file
120
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/ecdsa.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
package jwk
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"math/big"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
func newECDSAPublicKey(key *ecdsa.PublicKey) (*ECDSAPublicKey, error) {
|
||||
|
||||
var hdr StandardHeaders
|
||||
err := hdr.Set(KeyTypeKey, jwa.EC)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to set Key Type")
|
||||
}
|
||||
|
||||
return &ECDSAPublicKey{
|
||||
StandardHeaders: &hdr,
|
||||
key: key,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newECDSAPrivateKey(key *ecdsa.PrivateKey) (*ECDSAPrivateKey, error) {
|
||||
|
||||
var hdr StandardHeaders
|
||||
err := hdr.Set(KeyTypeKey, jwa.EC)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to set Key Type")
|
||||
}
|
||||
|
||||
return &ECDSAPrivateKey{
|
||||
StandardHeaders: &hdr,
|
||||
key: key,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Materialize returns the EC-DSA public key represented by this JWK
|
||||
func (k ECDSAPublicKey) Materialize() (interface{}, error) {
|
||||
return k.key, nil
|
||||
}
|
||||
|
||||
// Materialize returns the EC-DSA private key represented by this JWK
|
||||
func (k ECDSAPrivateKey) Materialize() (interface{}, error) {
|
||||
return k.key, nil
|
||||
}
|
||||
|
||||
// GenerateKey creates a ECDSAPublicKey from JWK format
|
||||
func (k *ECDSAPublicKey) GenerateKey(keyJSON *RawKeyJSON) error {
|
||||
|
||||
var x, y big.Int
|
||||
|
||||
if keyJSON.X == nil || keyJSON.Y == nil || keyJSON.Crv == "" {
|
||||
return errors.Errorf("Missing mandatory key parameters X, Y or Crv")
|
||||
}
|
||||
|
||||
x.SetBytes(keyJSON.X.Bytes())
|
||||
y.SetBytes(keyJSON.Y.Bytes())
|
||||
|
||||
var curve elliptic.Curve
|
||||
switch keyJSON.Crv {
|
||||
case jwa.P256:
|
||||
curve = elliptic.P256()
|
||||
case jwa.P384:
|
||||
curve = elliptic.P384()
|
||||
case jwa.P521:
|
||||
curve = elliptic.P521()
|
||||
default:
|
||||
return errors.Errorf(`invalid curve name %s`, keyJSON.Crv)
|
||||
}
|
||||
|
||||
*k = ECDSAPublicKey{
|
||||
StandardHeaders: &keyJSON.StandardHeaders,
|
||||
key: &ecdsa.PublicKey{
|
||||
Curve: curve,
|
||||
X: &x,
|
||||
Y: &y,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateKey creates a ECDSAPrivateKey from JWK format
|
||||
func (k *ECDSAPrivateKey) GenerateKey(keyJSON *RawKeyJSON) error {
|
||||
|
||||
if keyJSON.D == nil {
|
||||
return errors.Errorf("Missing mandatory key parameter D")
|
||||
}
|
||||
eCDSAPublicKey := &ECDSAPublicKey{}
|
||||
err := eCDSAPublicKey.GenerateKey(keyJSON)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, `failed to generate public key`)
|
||||
}
|
||||
dBytes := keyJSON.D.Bytes()
|
||||
// The length of this octet string MUST be ceiling(log-base-2(n)/8)
|
||||
// octets (where n is the order of the curve). This is because the private
|
||||
// key d must be in the interval [1, n-1] so the bitlength of d should be
|
||||
// no larger than the bitlength of n-1. The easiest way to find the octet
|
||||
// length is to take bitlength(n-1), add 7 to force a carry, and shift this
|
||||
// bit sequence right by 3, which is essentially dividing by 8 and adding
|
||||
// 1 if there is any remainder. Thus, the private key value d should be
|
||||
// output to (bitlength(n-1)+7)>>3 octets.
|
||||
n := eCDSAPublicKey.key.Params().N
|
||||
octetLength := (new(big.Int).Sub(n, big.NewInt(1)).BitLen() + 7) >> 3
|
||||
if octetLength-len(dBytes) != 0 {
|
||||
return errors.Errorf("Failed to generate private key. Incorrect D value")
|
||||
}
|
||||
privateKey := &ecdsa.PrivateKey{
|
||||
PublicKey: *eCDSAPublicKey.key,
|
||||
D: (&big.Int{}).SetBytes(keyJSON.D.Bytes()),
|
||||
}
|
||||
|
||||
k.key = privateKey
|
||||
k.StandardHeaders = &keyJSON.StandardHeaders
|
||||
|
||||
return nil
|
||||
}
|
||||
178
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/headers.go
generated
vendored
Normal file
178
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/headers.go
generated
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
package jwk
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
// Convenience constants for common JWK parameters
|
||||
const (
|
||||
AlgorithmKey = "alg"
|
||||
KeyIDKey = "kid"
|
||||
KeyOpsKey = "key_ops"
|
||||
KeyTypeKey = "kty"
|
||||
KeyUsageKey = "use"
|
||||
PrivateParamsKey = "privateParams"
|
||||
)
|
||||
|
||||
// Headers provides a common interface to all future possible headers
|
||||
type Headers interface {
|
||||
Get(string) (interface{}, bool)
|
||||
Set(string, interface{}) error
|
||||
Walk(func(string, interface{}) error) error
|
||||
GetAlgorithm() jwa.SignatureAlgorithm
|
||||
GetKeyID() string
|
||||
GetKeyOps() KeyOperationList
|
||||
GetKeyType() jwa.KeyType
|
||||
GetKeyUsage() string
|
||||
GetPrivateParams() map[string]interface{}
|
||||
}
|
||||
|
||||
// StandardHeaders stores the common JWK parameters
|
||||
type StandardHeaders struct {
|
||||
Algorithm *jwa.SignatureAlgorithm `json:"alg,omitempty"` // https://tools.ietf.org/html/rfc7517#section-4.4
|
||||
KeyID string `json:"kid,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.4
|
||||
KeyOps KeyOperationList `json:"key_ops,omitempty"` // https://tools.ietf.org/html/rfc7517#section-4.3
|
||||
KeyType jwa.KeyType `json:"kty,omitempty"` // https://tools.ietf.org/html/rfc7517#section-4.1
|
||||
KeyUsage string `json:"use,omitempty"` // https://tools.ietf.org/html/rfc7517#section-4.2
|
||||
PrivateParams map[string]interface{} `json:"privateParams,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.4
|
||||
}
|
||||
|
||||
// GetAlgorithm is a convenience function to retrieve the corresponding value stored in the StandardHeaders
|
||||
func (h *StandardHeaders) GetAlgorithm() jwa.SignatureAlgorithm {
|
||||
if v := h.Algorithm; v != nil {
|
||||
return *v
|
||||
}
|
||||
return jwa.NoValue
|
||||
}
|
||||
|
||||
// GetKeyID is a convenience function to retrieve the corresponding value stored in the StandardHeaders
|
||||
func (h *StandardHeaders) GetKeyID() string {
|
||||
return h.KeyID
|
||||
}
|
||||
|
||||
// GetKeyOps is a convenience function to retrieve the corresponding value stored in the StandardHeaders
|
||||
func (h *StandardHeaders) GetKeyOps() KeyOperationList {
|
||||
return h.KeyOps
|
||||
}
|
||||
|
||||
// GetKeyType is a convenience function to retrieve the corresponding value stored in the StandardHeaders
|
||||
func (h *StandardHeaders) GetKeyType() jwa.KeyType {
|
||||
return h.KeyType
|
||||
}
|
||||
|
||||
// GetKeyUsage is a convenience function to retrieve the corresponding value stored in the StandardHeaders
|
||||
func (h *StandardHeaders) GetKeyUsage() string {
|
||||
return h.KeyUsage
|
||||
}
|
||||
|
||||
// GetPrivateParams is a convenience function to retrieve the corresponding value stored in the StandardHeaders
|
||||
func (h *StandardHeaders) GetPrivateParams() map[string]interface{} {
|
||||
return h.PrivateParams
|
||||
}
|
||||
|
||||
// Get is a general getter function for JWK StandardHeaders structure
|
||||
func (h *StandardHeaders) Get(name string) (interface{}, bool) {
|
||||
switch name {
|
||||
case AlgorithmKey:
|
||||
alg := h.GetAlgorithm()
|
||||
if alg != jwa.NoValue {
|
||||
return alg, true
|
||||
}
|
||||
return nil, false
|
||||
case KeyIDKey:
|
||||
v := h.KeyID
|
||||
if v == "" {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case KeyOpsKey:
|
||||
v := h.KeyOps
|
||||
if v == nil {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case KeyTypeKey:
|
||||
v := h.KeyType
|
||||
if v == jwa.InvalidKeyType {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case KeyUsageKey:
|
||||
v := h.KeyUsage
|
||||
if v == "" {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case PrivateParamsKey:
|
||||
v := h.PrivateParams
|
||||
if len(v) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
// Set is a general getter function for JWK StandardHeaders structure
|
||||
func (h *StandardHeaders) Set(name string, value interface{}) error {
|
||||
switch name {
|
||||
case AlgorithmKey:
|
||||
var acceptor jwa.SignatureAlgorithm
|
||||
if err := acceptor.Accept(value); err != nil {
|
||||
return errors.Wrapf(err, `invalid value for %s key`, AlgorithmKey)
|
||||
}
|
||||
h.Algorithm = &acceptor
|
||||
return nil
|
||||
case KeyIDKey:
|
||||
if v, ok := value.(string); ok {
|
||||
h.KeyID = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf("invalid value for %s key: %T", KeyIDKey, value)
|
||||
case KeyOpsKey:
|
||||
if err := h.KeyOps.Accept(value); err != nil {
|
||||
return errors.Wrapf(err, "invalid value for %s key", KeyOpsKey)
|
||||
}
|
||||
return nil
|
||||
case KeyTypeKey:
|
||||
if err := h.KeyType.Accept(value); err != nil {
|
||||
return errors.Wrapf(err, "invalid value for %s key", KeyTypeKey)
|
||||
}
|
||||
return nil
|
||||
case KeyUsageKey:
|
||||
if v, ok := value.(string); ok {
|
||||
h.KeyUsage = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf("invalid value for %s key: %T", KeyUsageKey, value)
|
||||
case PrivateParamsKey:
|
||||
if v, ok := value.(map[string]interface{}); ok {
|
||||
h.PrivateParams = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf("invalid value for %s key: %T", PrivateParamsKey, value)
|
||||
default:
|
||||
return errors.Errorf(`invalid key: %s`, name)
|
||||
}
|
||||
}
|
||||
|
||||
// Walk iterates over all JWK standard headers fields while applying a function to its value.
|
||||
func (h StandardHeaders) Walk(f func(string, interface{}) error) error {
|
||||
for _, key := range []string{AlgorithmKey, KeyIDKey, KeyOpsKey, KeyTypeKey, KeyUsageKey, PrivateParamsKey} {
|
||||
if v, ok := h.Get(key); ok {
|
||||
if err := f(key, v); err != nil {
|
||||
return errors.Wrapf(err, `walk function returned error for %s`, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range h.PrivateParams {
|
||||
if err := f(k, v); err != nil {
|
||||
return errors.Wrapf(err, `walk function returned error for %s`, k)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
70
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/interface.go
generated
vendored
Normal file
70
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/interface.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package jwk
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
// Set is a convenience struct to allow generating and parsing
|
||||
// JWK sets as opposed to single JWKs
|
||||
type Set struct {
|
||||
Keys []Key `json:"keys"`
|
||||
}
|
||||
|
||||
// Key defines the minimal interface for each of the
|
||||
// key types. Their use and implementation differ significantly
|
||||
// between each key types, so you should use type assertions
|
||||
// to perform more specific tasks with each key
|
||||
type Key interface {
|
||||
Headers
|
||||
|
||||
// Materialize creates the corresponding key. For example,
|
||||
// RSA types would create *rsa.PublicKey or *rsa.PrivateKey,
|
||||
// EC types would create *ecdsa.PublicKey or *ecdsa.PrivateKey,
|
||||
// and OctetSeq types create a []byte key.
|
||||
Materialize() (interface{}, error)
|
||||
GenerateKey(*RawKeyJSON) error
|
||||
}
|
||||
|
||||
// RawKeyJSON is generic type that represents any kind JWK
|
||||
type RawKeyJSON struct {
|
||||
StandardHeaders
|
||||
jwa.AlgorithmParameters
|
||||
}
|
||||
|
||||
// RawKeySetJSON is generic type that represents a JWK Set
|
||||
type RawKeySetJSON struct {
|
||||
Keys []RawKeyJSON `json:"keys"`
|
||||
}
|
||||
|
||||
// RSAPublicKey is a type of JWK generated from RSA public keys
|
||||
type RSAPublicKey struct {
|
||||
*StandardHeaders
|
||||
key *rsa.PublicKey
|
||||
}
|
||||
|
||||
// RSAPrivateKey is a type of JWK generated from RSA private keys
|
||||
type RSAPrivateKey struct {
|
||||
*StandardHeaders
|
||||
key *rsa.PrivateKey
|
||||
}
|
||||
|
||||
// SymmetricKey is a type of JWK generated from symmetric keys
|
||||
type SymmetricKey struct {
|
||||
*StandardHeaders
|
||||
key []byte
|
||||
}
|
||||
|
||||
// ECDSAPublicKey is a type of JWK generated from ECDSA public keys
|
||||
type ECDSAPublicKey struct {
|
||||
*StandardHeaders
|
||||
key *ecdsa.PublicKey
|
||||
}
|
||||
|
||||
// ECDSAPrivateKey is a type of JWK generated from ECDH-ES private keys
|
||||
type ECDSAPrivateKey struct {
|
||||
*StandardHeaders
|
||||
key *ecdsa.PrivateKey
|
||||
}
|
||||
150
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/jwk.go
generated
vendored
Normal file
150
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/jwk.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
// Package jwk implements JWK as described in https://tools.ietf.org/html/rfc7517
|
||||
package jwk
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
// GetPublicKey returns the public key based on the private key type.
|
||||
// For rsa key types *rsa.PublicKey is returned; for ecdsa key types *ecdsa.PublicKey;
|
||||
// for byte slice (raw) keys, the key itself is returned. If the corresponding
|
||||
// public key cannot be deduced, an error is returned
|
||||
func GetPublicKey(key interface{}) (interface{}, error) {
|
||||
if key == nil {
|
||||
return nil, errors.New(`jwk.New requires a non-nil key`)
|
||||
}
|
||||
|
||||
switch v := key.(type) {
|
||||
// Mental note: although Public() is defined in both types,
|
||||
// you can not coalesce the clauses for rsa.PrivateKey and
|
||||
// ecdsa.PrivateKey, as then `v` becomes interface{}
|
||||
// b/c the compiler cannot deduce the exact type.
|
||||
case *rsa.PrivateKey:
|
||||
return v.Public(), nil
|
||||
case *ecdsa.PrivateKey:
|
||||
return v.Public(), nil
|
||||
case []byte:
|
||||
return v, nil
|
||||
default:
|
||||
return nil, errors.Errorf(`invalid key type %T`, key)
|
||||
}
|
||||
}
|
||||
|
||||
// GetKeyTypeFromKey creates a jwk.Key from the given key.
|
||||
func GetKeyTypeFromKey(key interface{}) jwa.KeyType {
|
||||
|
||||
switch key.(type) {
|
||||
case *rsa.PrivateKey, *rsa.PublicKey:
|
||||
return jwa.RSA
|
||||
case *ecdsa.PrivateKey, *ecdsa.PublicKey:
|
||||
return jwa.EC
|
||||
case []byte:
|
||||
return jwa.OctetSeq
|
||||
default:
|
||||
return jwa.InvalidKeyType
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a jwk.Key from the given key.
|
||||
func New(key interface{}) (Key, error) {
|
||||
if key == nil {
|
||||
return nil, errors.New(`jwk.New requires a non-nil key`)
|
||||
}
|
||||
|
||||
switch v := key.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return newRSAPrivateKey(v)
|
||||
case *rsa.PublicKey:
|
||||
return newRSAPublicKey(v)
|
||||
case *ecdsa.PrivateKey:
|
||||
return newECDSAPrivateKey(v)
|
||||
case *ecdsa.PublicKey:
|
||||
return newECDSAPublicKey(v)
|
||||
case []byte:
|
||||
return newSymmetricKey(v)
|
||||
default:
|
||||
return nil, errors.Errorf(`invalid key type %T`, key)
|
||||
}
|
||||
}
|
||||
|
||||
func parse(jwkSrc string) (*Set, error) {
|
||||
|
||||
var jwkKeySet Set
|
||||
var jwkKey Key
|
||||
rawKeySetJSON := &RawKeySetJSON{}
|
||||
err := json.Unmarshal([]byte(jwkSrc), rawKeySetJSON)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to unmarshal JWK Set")
|
||||
}
|
||||
if len(rawKeySetJSON.Keys) == 0 {
|
||||
|
||||
// It might be a single key
|
||||
rawKeyJSON := &RawKeyJSON{}
|
||||
err := json.Unmarshal([]byte(jwkSrc), rawKeyJSON)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to unmarshal JWK")
|
||||
}
|
||||
jwkKey, err = rawKeyJSON.GenerateKey()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to generate key")
|
||||
}
|
||||
// Add to set
|
||||
jwkKeySet.Keys = append(jwkKeySet.Keys, jwkKey)
|
||||
} else {
|
||||
for i := range rawKeySetJSON.Keys {
|
||||
rawKeyJSON := rawKeySetJSON.Keys[i]
|
||||
jwkKey, err = rawKeyJSON.GenerateKey()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to generate key: %s")
|
||||
}
|
||||
jwkKeySet.Keys = append(jwkKeySet.Keys, jwkKey)
|
||||
}
|
||||
}
|
||||
return &jwkKeySet, nil
|
||||
}
|
||||
|
||||
// ParseBytes parses JWK from the incoming byte buffer.
|
||||
func ParseBytes(buf []byte) (*Set, error) {
|
||||
return parse(string(buf[:]))
|
||||
}
|
||||
|
||||
// ParseString parses JWK from the incoming string.
|
||||
func ParseString(s string) (*Set, error) {
|
||||
return parse(s)
|
||||
}
|
||||
|
||||
// GenerateKey creates an internal representation of a key from a raw JWK JSON
|
||||
func (r *RawKeyJSON) GenerateKey() (Key, error) {
|
||||
|
||||
var key Key
|
||||
|
||||
switch r.KeyType {
|
||||
case jwa.RSA:
|
||||
if r.D != nil {
|
||||
key = &RSAPrivateKey{}
|
||||
} else {
|
||||
key = &RSAPublicKey{}
|
||||
}
|
||||
case jwa.EC:
|
||||
if r.D != nil {
|
||||
key = &ECDSAPrivateKey{}
|
||||
} else {
|
||||
key = &ECDSAPublicKey{}
|
||||
}
|
||||
case jwa.OctetSeq:
|
||||
key = &SymmetricKey{}
|
||||
default:
|
||||
return nil, errors.Errorf(`Unrecognized key type`)
|
||||
}
|
||||
err := key.GenerateKey(r)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to generate key from JWK")
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
68
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/key_ops.go
generated
vendored
Normal file
68
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/key_ops.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package jwk
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// KeyUsageType is used to denote what this key should be used for
|
||||
type KeyUsageType string
|
||||
|
||||
const (
|
||||
// ForSignature is the value used in the headers to indicate that
|
||||
// this key should be used for signatures
|
||||
ForSignature KeyUsageType = "sig"
|
||||
// ForEncryption is the value used in the headers to indicate that
|
||||
// this key should be used for encryptiong
|
||||
ForEncryption KeyUsageType = "enc"
|
||||
)
|
||||
|
||||
// KeyOperation is used to denote the allowed operations for a Key
|
||||
type KeyOperation string
|
||||
|
||||
// KeyOperationList represents an slice of KeyOperation
|
||||
type KeyOperationList []KeyOperation
|
||||
|
||||
var keyOps = map[string]struct{}{"sign": {}, "verify": {}, "encrypt": {}, "decrypt": {}, "wrapKey": {}, "unwrapKey": {}, "deriveKey": {}, "deriveBits": {}}
|
||||
|
||||
// KeyOperation constants
|
||||
const (
|
||||
KeyOpSign KeyOperation = "sign" // (compute digital signature or MAC)
|
||||
KeyOpVerify = "verify" // (verify digital signature or MAC)
|
||||
KeyOpEncrypt = "encrypt" // (encrypt content)
|
||||
KeyOpDecrypt = "decrypt" // (decrypt content and validate decryption, if applicable)
|
||||
KeyOpWrapKey = "wrapKey" // (encrypt key)
|
||||
KeyOpUnwrapKey = "unwrapKey" // (decrypt key and validate decryption, if applicable)
|
||||
KeyOpDeriveKey = "deriveKey" // (derive key)
|
||||
KeyOpDeriveBits = "deriveBits" // (derive bits not to be used as a key)
|
||||
)
|
||||
|
||||
// Accept determines if Key Operation is valid
|
||||
func (keyOperationList *KeyOperationList) Accept(v interface{}) error {
|
||||
switch x := v.(type) {
|
||||
case KeyOperationList:
|
||||
*keyOperationList = x
|
||||
return nil
|
||||
default:
|
||||
return errors.Errorf(`invalid value %T`, v)
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals and checks data as KeyType Algorithm
|
||||
func (keyOperationList *KeyOperationList) UnmarshalJSON(data []byte) error {
|
||||
var tempKeyOperationList []string
|
||||
err := json.Unmarshal(data, &tempKeyOperationList)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid key operation")
|
||||
}
|
||||
for _, value := range tempKeyOperationList {
|
||||
_, ok := keyOps[value]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown key operation")
|
||||
}
|
||||
*keyOperationList = append(*keyOperationList, KeyOperation(value))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
103
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/rsa.go
generated
vendored
Normal file
103
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/rsa.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
package jwk
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"math/big"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
func newRSAPublicKey(key *rsa.PublicKey) (*RSAPublicKey, error) {
|
||||
|
||||
var hdr StandardHeaders
|
||||
err := hdr.Set(KeyTypeKey, jwa.RSA)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to set Key Type")
|
||||
}
|
||||
return &RSAPublicKey{
|
||||
StandardHeaders: &hdr,
|
||||
key: key,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newRSAPrivateKey(key *rsa.PrivateKey) (*RSAPrivateKey, error) {
|
||||
|
||||
var hdr StandardHeaders
|
||||
err := hdr.Set(KeyTypeKey, jwa.RSA)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to set Key Type")
|
||||
}
|
||||
return &RSAPrivateKey{
|
||||
StandardHeaders: &hdr,
|
||||
key: key,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Materialize returns the standard RSA Public Key representation stored in the internal representation
|
||||
func (k *RSAPublicKey) Materialize() (interface{}, error) {
|
||||
if k.key == nil {
|
||||
return nil, errors.New(`key has no rsa.PublicKey associated with it`)
|
||||
}
|
||||
return k.key, nil
|
||||
}
|
||||
|
||||
// Materialize returns the standard RSA Private Key representation stored in the internal representation
|
||||
func (k *RSAPrivateKey) Materialize() (interface{}, error) {
|
||||
if k.key == nil {
|
||||
return nil, errors.New(`key has no rsa.PrivateKey associated with it`)
|
||||
}
|
||||
return k.key, nil
|
||||
}
|
||||
|
||||
// GenerateKey creates a RSAPublicKey from a RawKeyJSON
|
||||
func (k *RSAPublicKey) GenerateKey(keyJSON *RawKeyJSON) error {
|
||||
|
||||
if keyJSON.N == nil || keyJSON.E == nil {
|
||||
return errors.Errorf("Missing mandatory key parameters N or E")
|
||||
}
|
||||
rsaPublicKey := &rsa.PublicKey{
|
||||
N: (&big.Int{}).SetBytes(keyJSON.N.Bytes()),
|
||||
E: int((&big.Int{}).SetBytes(keyJSON.E.Bytes()).Int64()),
|
||||
}
|
||||
k.key = rsaPublicKey
|
||||
k.StandardHeaders = &keyJSON.StandardHeaders
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateKey creates a RSAPublicKey from a RawKeyJSON
|
||||
func (k *RSAPrivateKey) GenerateKey(keyJSON *RawKeyJSON) error {
|
||||
|
||||
rsaPublicKey := &RSAPublicKey{}
|
||||
err := rsaPublicKey.GenerateKey(keyJSON)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to generate public key")
|
||||
}
|
||||
|
||||
if keyJSON.D == nil || keyJSON.P == nil || keyJSON.Q == nil {
|
||||
return errors.Errorf("Missing mandatory key parameters D, P or Q")
|
||||
}
|
||||
privateKey := &rsa.PrivateKey{
|
||||
PublicKey: *rsaPublicKey.key,
|
||||
D: (&big.Int{}).SetBytes(keyJSON.D.Bytes()),
|
||||
Primes: []*big.Int{
|
||||
(&big.Int{}).SetBytes(keyJSON.P.Bytes()),
|
||||
(&big.Int{}).SetBytes(keyJSON.Q.Bytes()),
|
||||
},
|
||||
}
|
||||
|
||||
if keyJSON.Dp.Len() > 0 {
|
||||
privateKey.Precomputed.Dp = (&big.Int{}).SetBytes(keyJSON.Dp.Bytes())
|
||||
}
|
||||
if keyJSON.Dq.Len() > 0 {
|
||||
privateKey.Precomputed.Dq = (&big.Int{}).SetBytes(keyJSON.Dq.Bytes())
|
||||
}
|
||||
if keyJSON.Qi.Len() > 0 {
|
||||
privateKey.Precomputed.Qinv = (&big.Int{}).SetBytes(keyJSON.Qi.Bytes())
|
||||
}
|
||||
|
||||
k.key = privateKey
|
||||
k.StandardHeaders = &keyJSON.StandardHeaders
|
||||
return nil
|
||||
}
|
||||
41
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/symmetric.go
generated
vendored
Normal file
41
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jwk/symmetric.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package jwk
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
func newSymmetricKey(key []byte) (*SymmetricKey, error) {
|
||||
var hdr StandardHeaders
|
||||
|
||||
err := hdr.Set(KeyTypeKey, jwa.OctetSeq)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Failed to set Key Type")
|
||||
}
|
||||
return &SymmetricKey{
|
||||
StandardHeaders: &hdr,
|
||||
key: key,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Materialize returns the octets for this symmetric key.
|
||||
// Since this is a symmetric key, this just calls Octets
|
||||
func (s SymmetricKey) Materialize() (interface{}, error) {
|
||||
return s.Octets(), nil
|
||||
}
|
||||
|
||||
// Octets returns the octets in the key
|
||||
func (s SymmetricKey) Octets() []byte {
|
||||
return s.key
|
||||
}
|
||||
|
||||
// GenerateKey creates a Symmetric key from a RawKeyJSON
|
||||
func (s *SymmetricKey) GenerateKey(keyJSON *RawKeyJSON) error {
|
||||
|
||||
*s = SymmetricKey{
|
||||
StandardHeaders: &keyJSON.StandardHeaders,
|
||||
key: keyJSON.K,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
154
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/headers.go
generated
vendored
Normal file
154
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/headers.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
package jws
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
// Constants for JWS Common parameters
|
||||
const (
|
||||
AlgorithmKey = "alg"
|
||||
ContentTypeKey = "cty"
|
||||
CriticalKey = "crit"
|
||||
JWKKey = "jwk"
|
||||
JWKSetURLKey = "jku"
|
||||
KeyIDKey = "kid"
|
||||
PrivateParamsKey = "privateParams"
|
||||
TypeKey = "typ"
|
||||
)
|
||||
|
||||
// Headers provides a common interface for common header parameters
|
||||
type Headers interface {
|
||||
Get(string) (interface{}, bool)
|
||||
Set(string, interface{}) error
|
||||
GetAlgorithm() jwa.SignatureAlgorithm
|
||||
}
|
||||
|
||||
// StandardHeaders contains JWS common parameters.
|
||||
type StandardHeaders struct {
|
||||
Algorithm jwa.SignatureAlgorithm `json:"alg,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.1
|
||||
ContentType string `json:"cty,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.10
|
||||
Critical []string `json:"crit,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.11
|
||||
JWK string `json:"jwk,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.3
|
||||
JWKSetURL string `json:"jku,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.2
|
||||
KeyID string `json:"kid,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.4
|
||||
PrivateParams map[string]interface{} `json:"privateParams,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.9
|
||||
Type string `json:"typ,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.9
|
||||
}
|
||||
|
||||
// GetAlgorithm returns algorithm
|
||||
func (h *StandardHeaders) GetAlgorithm() jwa.SignatureAlgorithm {
|
||||
return h.Algorithm
|
||||
}
|
||||
|
||||
// Get is a general getter function for StandardHeaders structure
|
||||
func (h *StandardHeaders) Get(name string) (interface{}, bool) {
|
||||
switch name {
|
||||
case AlgorithmKey:
|
||||
v := h.Algorithm
|
||||
if v == "" {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case ContentTypeKey:
|
||||
v := h.ContentType
|
||||
if v == "" {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case CriticalKey:
|
||||
v := h.Critical
|
||||
if len(v) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case JWKKey:
|
||||
v := h.JWK
|
||||
if v == "" {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case JWKSetURLKey:
|
||||
v := h.JWKSetURL
|
||||
if v == "" {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case KeyIDKey:
|
||||
v := h.KeyID
|
||||
if v == "" {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case PrivateParamsKey:
|
||||
v := h.PrivateParams
|
||||
if len(v) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
case TypeKey:
|
||||
v := h.Type
|
||||
if v == "" {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
// Set is a general setter function for StandardHeaders structure
|
||||
func (h *StandardHeaders) Set(name string, value interface{}) error {
|
||||
switch name {
|
||||
case AlgorithmKey:
|
||||
if err := h.Algorithm.Accept(value); err != nil {
|
||||
return errors.Wrapf(err, `invalid value for %s key`, AlgorithmKey)
|
||||
}
|
||||
return nil
|
||||
case ContentTypeKey:
|
||||
if v, ok := value.(string); ok {
|
||||
h.ContentType = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf(`invalid value for %s key: %T`, ContentTypeKey, value)
|
||||
case CriticalKey:
|
||||
if v, ok := value.([]string); ok {
|
||||
h.Critical = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf(`invalid value for %s key: %T`, CriticalKey, value)
|
||||
case JWKKey:
|
||||
if v, ok := value.(string); ok {
|
||||
h.JWK = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf(`invalid value for %s key: %T`, JWKKey, value)
|
||||
case JWKSetURLKey:
|
||||
if v, ok := value.(string); ok {
|
||||
h.JWKSetURL = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf(`invalid value for %s key: %T`, JWKSetURLKey, value)
|
||||
case KeyIDKey:
|
||||
if v, ok := value.(string); ok {
|
||||
h.KeyID = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf(`invalid value for %s key: %T`, KeyIDKey, value)
|
||||
case PrivateParamsKey:
|
||||
if v, ok := value.(map[string]interface{}); ok {
|
||||
h.PrivateParams = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf(`invalid value for %s key: %T`, PrivateParamsKey, value)
|
||||
case TypeKey:
|
||||
if v, ok := value.(string); ok {
|
||||
h.Type = v
|
||||
return nil
|
||||
}
|
||||
return errors.Errorf(`invalid value for %s key: %T`, TypeKey, value)
|
||||
default:
|
||||
return errors.Errorf(`invalid key: %s`, name)
|
||||
}
|
||||
}
|
||||
22
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/interface.go
generated
vendored
Normal file
22
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/interface.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package jws
|
||||
|
||||
// Message represents a full JWS encoded message. Flattened serialization
|
||||
// is not supported as a struct, but rather it's represented as a
|
||||
// Message struct with only one `Signature` element.
|
||||
//
|
||||
// Do not expect to use the Message object to verify or construct a
|
||||
// signed payloads with. You should only use this when you want to actually
|
||||
// want to programmatically view the contents for the full JWS Payload.
|
||||
//
|
||||
// To sign and verify, use the appropriate `SignWithOption()` nad `Verify()` functions
|
||||
type Message struct {
|
||||
Payload []byte `json:"payload"`
|
||||
Signatures []*Signature `json:"signatures,omitempty"`
|
||||
}
|
||||
|
||||
// Signature represents the headers and signature of a JWS message
|
||||
type Signature struct {
|
||||
Headers Headers `json:"header,omitempty"` // Unprotected Headers
|
||||
Protected Headers `json:"Protected,omitempty"` // Protected Headers
|
||||
Signature []byte `json:"signature,omitempty"` // GetSignature
|
||||
}
|
||||
210
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/jws.go
generated
vendored
Normal file
210
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/jws.go
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
// Package jws implements the digital Signature on JSON based data
|
||||
// structures as described in https://tools.ietf.org/html/rfc7515
|
||||
//
|
||||
// If you do not care about the details, the only things that you
|
||||
// would need to use are the following functions:
|
||||
//
|
||||
// jws.SignWithOption(Payload, algorithm, key)
|
||||
// jws.Verify(encodedjws, algorithm, key)
|
||||
//
|
||||
// To sign, simply use `jws.SignWithOption`. `Payload` is a []byte buffer that
|
||||
// contains whatever data you want to sign. `alg` is one of the
|
||||
// jwa.SignatureAlgorithm constants from package jwa. For RSA and
|
||||
// ECDSA family of algorithms, you will need to prepare a private key.
|
||||
// For HMAC family, you just need a []byte value. The `jws.SignWithOption`
|
||||
// function will return the encoded JWS message on success.
|
||||
//
|
||||
// To verify, use `jws.Verify`. It will parse the `encodedjws` buffer
|
||||
// and verify the result using `algorithm` and `key`. Upon successful
|
||||
// verification, the original Payload is returned, so you can work on it.
|
||||
package jws
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwk"
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign"
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// SignLiteral generates a Signature for the given Payload and Headers, and serializes
|
||||
// it in compact serialization format. In this format you may NOT use
|
||||
// multiple signers.
|
||||
//
|
||||
func SignLiteral(payload []byte, alg jwa.SignatureAlgorithm, key interface{}, hdrBuf []byte) ([]byte, error) {
|
||||
encodedHdr := base64.RawURLEncoding.EncodeToString(hdrBuf)
|
||||
encodedPayload := base64.RawURLEncoding.EncodeToString(payload)
|
||||
signingInput := strings.Join(
|
||||
[]string{
|
||||
encodedHdr,
|
||||
encodedPayload,
|
||||
}, ".",
|
||||
)
|
||||
signer, err := sign.New(alg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `failed to create signer`)
|
||||
}
|
||||
signature, err := signer.Sign([]byte(signingInput), key)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `failed to sign Payload`)
|
||||
}
|
||||
encodedSignature := base64.RawURLEncoding.EncodeToString(signature)
|
||||
compactSerialization := strings.Join(
|
||||
[]string{
|
||||
signingInput,
|
||||
encodedSignature,
|
||||
}, ".",
|
||||
)
|
||||
return []byte(compactSerialization), nil
|
||||
}
|
||||
|
||||
// SignWithOption generates a Signature for the given Payload, and serializes
|
||||
// it in compact serialization format. In this format you may NOT use
|
||||
// multiple signers.
|
||||
//
|
||||
// If you would like to pass custom Headers, use the WithHeaders option.
|
||||
func SignWithOption(payload []byte, alg jwa.SignatureAlgorithm, key interface{}) ([]byte, error) {
|
||||
var headers Headers = &StandardHeaders{}
|
||||
|
||||
err := headers.Set(AlgorithmKey, alg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to set alg value")
|
||||
}
|
||||
|
||||
hdrBuf, err := json.Marshal(headers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `failed to marshal Headers`)
|
||||
}
|
||||
return SignLiteral(payload, alg, key, hdrBuf)
|
||||
}
|
||||
|
||||
// Verify checks if the given JWS message is verifiable using `alg` and `key`.
|
||||
// If the verification is successful, `err` is nil, and the content of the
|
||||
// Payload that was signed is returned. If you need more fine-grained
|
||||
// control of the verification process, manually call `Parse`, generate a
|
||||
// verifier, and call `Verify` on the parsed JWS message object.
|
||||
func Verify(buf []byte, alg jwa.SignatureAlgorithm, key interface{}) (ret []byte, err error) {
|
||||
|
||||
verifier, err := verify.New(alg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create verifier")
|
||||
}
|
||||
|
||||
buf = bytes.TrimSpace(buf)
|
||||
if len(buf) == 0 {
|
||||
return nil, errors.New(`attempt to verify empty buffer`)
|
||||
}
|
||||
|
||||
parts, err := SplitCompact(string(buf[:]))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `failed extract from compact serialization format`)
|
||||
}
|
||||
|
||||
signingInput := strings.Join(
|
||||
[]string{
|
||||
parts[0],
|
||||
parts[1],
|
||||
}, ".",
|
||||
)
|
||||
|
||||
decodedSignature, err := base64.RawURLEncoding.DecodeString(parts[2])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to decode signature")
|
||||
}
|
||||
if err := verifier.Verify([]byte(signingInput), decodedSignature, key); err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to verify message")
|
||||
}
|
||||
|
||||
if decodedPayload, err := base64.RawURLEncoding.DecodeString(parts[1]); err == nil {
|
||||
return decodedPayload, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "Failed to decode Payload")
|
||||
}
|
||||
|
||||
// VerifyWithJWK verifies the JWS message using the specified JWK
|
||||
func VerifyWithJWK(buf []byte, key jwk.Key) (payload []byte, err error) {
|
||||
|
||||
keyVal, err := key.Materialize()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to materialize key")
|
||||
}
|
||||
return Verify(buf, key.GetAlgorithm(), keyVal)
|
||||
}
|
||||
|
||||
// VerifyWithJWKSet verifies the JWS message using JWK key set.
|
||||
// By default it will only pick up keys that have the "use" key
|
||||
// set to either "sig" or "enc", but you can override it by
|
||||
// providing a keyaccept function.
|
||||
func VerifyWithJWKSet(buf []byte, keyset *jwk.Set) (payload []byte, err error) {
|
||||
|
||||
for _, key := range keyset.Keys {
|
||||
payload, err := VerifyWithJWK(buf, key)
|
||||
if err == nil {
|
||||
return payload, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("failed to verify with any of the keys")
|
||||
}
|
||||
|
||||
// ParseByte parses a JWS value serialized via compact serialization and provided as []byte.
|
||||
func ParseByte(jwsCompact []byte) (m *Message, err error) {
|
||||
return parseCompact(string(jwsCompact[:]))
|
||||
}
|
||||
|
||||
// ParseString parses a JWS value serialized via compact serialization and provided as string.
|
||||
func ParseString(s string) (*Message, error) {
|
||||
return parseCompact(s)
|
||||
}
|
||||
|
||||
// SplitCompact splits a JWT and returns its three parts
|
||||
// separately: Protected Headers, Payload and Signature.
|
||||
func SplitCompact(jwsCompact string) ([]string, error) {
|
||||
|
||||
parts := strings.Split(jwsCompact, ".")
|
||||
if len(parts) < 3 {
|
||||
return nil, errors.New("Failed to split compact serialization")
|
||||
}
|
||||
return parts, nil
|
||||
}
|
||||
|
||||
// parseCompact parses a JWS value serialized via compact serialization.
|
||||
func parseCompact(str string) (m *Message, err error) {
|
||||
|
||||
var decodedHeader, decodedPayload, decodedSignature []byte
|
||||
parts, err := SplitCompact(str)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `invalid compact serialization format`)
|
||||
}
|
||||
|
||||
if decodedHeader, err = base64.RawURLEncoding.DecodeString(parts[0]); err != nil {
|
||||
return nil, errors.Wrap(err, `failed to decode Headers`)
|
||||
}
|
||||
var hdr StandardHeaders
|
||||
if err := json.Unmarshal(decodedHeader, &hdr); err != nil {
|
||||
return nil, errors.Wrap(err, `failed to parse JOSE Headers`)
|
||||
}
|
||||
|
||||
if decodedPayload, err = base64.RawURLEncoding.DecodeString(parts[1]); err != nil {
|
||||
return nil, errors.Wrap(err, `failed to decode Payload`)
|
||||
}
|
||||
|
||||
if len(parts) > 2 {
|
||||
if decodedSignature, err = base64.RawURLEncoding.DecodeString(parts[2]); err != nil {
|
||||
return nil, errors.Wrap(err, `failed to decode Signature`)
|
||||
}
|
||||
}
|
||||
|
||||
var msg Message
|
||||
msg.Payload = decodedPayload
|
||||
msg.Signatures = append(msg.Signatures, &Signature{
|
||||
Protected: &hdr,
|
||||
Signature: decodedSignature,
|
||||
})
|
||||
return &msg, nil
|
||||
}
|
||||
26
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/message.go
generated
vendored
Normal file
26
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/message.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package jws
|
||||
|
||||
// PublicHeaders returns the public headers in a JWS
|
||||
func (s Signature) PublicHeaders() Headers {
|
||||
return s.Headers
|
||||
}
|
||||
|
||||
// ProtectedHeaders returns the protected headers in a JWS
|
||||
func (s Signature) ProtectedHeaders() Headers {
|
||||
return s.Protected
|
||||
}
|
||||
|
||||
// GetSignature returns the signature in a JWS
|
||||
func (s Signature) GetSignature() []byte {
|
||||
return s.Signature
|
||||
}
|
||||
|
||||
// GetPayload returns the payload in a JWS
|
||||
func (m Message) GetPayload() []byte {
|
||||
return m.Payload
|
||||
}
|
||||
|
||||
// GetSignatures returns the all signatures in a JWS
|
||||
func (m Message) GetSignatures() []*Signature {
|
||||
return m.Signatures
|
||||
}
|
||||
84
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/ecdsa.go
generated
vendored
Normal file
84
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/ecdsa.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package sign
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var ecdsaSignFuncs = map[jwa.SignatureAlgorithm]ecdsaSignFunc{}
|
||||
|
||||
func init() {
|
||||
algs := map[jwa.SignatureAlgorithm]crypto.Hash{
|
||||
jwa.ES256: crypto.SHA256,
|
||||
jwa.ES384: crypto.SHA384,
|
||||
jwa.ES512: crypto.SHA512,
|
||||
}
|
||||
|
||||
for alg, h := range algs {
|
||||
ecdsaSignFuncs[alg] = makeECDSASignFunc(h)
|
||||
}
|
||||
}
|
||||
|
||||
func makeECDSASignFunc(hash crypto.Hash) ecdsaSignFunc {
|
||||
return ecdsaSignFunc(func(payload []byte, key *ecdsa.PrivateKey) ([]byte, error) {
|
||||
curveBits := key.Curve.Params().BitSize
|
||||
keyBytes := curveBits / 8
|
||||
// Curve bits do not need to be a multiple of 8.
|
||||
if curveBits%8 > 0 {
|
||||
keyBytes++
|
||||
}
|
||||
h := hash.New()
|
||||
h.Write(payload)
|
||||
r, s, err := ecdsa.Sign(rand.Reader, key, h.Sum(nil))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to sign payload using ecdsa")
|
||||
}
|
||||
|
||||
rBytes := r.Bytes()
|
||||
rBytesPadded := make([]byte, keyBytes)
|
||||
copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
|
||||
|
||||
sBytes := s.Bytes()
|
||||
sBytesPadded := make([]byte, keyBytes)
|
||||
copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
|
||||
|
||||
out := append(rBytesPadded, sBytesPadded...)
|
||||
return out, nil
|
||||
})
|
||||
}
|
||||
|
||||
func newECDSA(alg jwa.SignatureAlgorithm) (*ECDSASigner, error) {
|
||||
signfn, ok := ecdsaSignFuncs[alg]
|
||||
if !ok {
|
||||
return nil, errors.Errorf(`unsupported algorithm while trying to create ECDSA signer: %s`, alg)
|
||||
}
|
||||
|
||||
return &ECDSASigner{
|
||||
alg: alg,
|
||||
sign: signfn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Algorithm returns the signer algorithm
|
||||
func (s ECDSASigner) Algorithm() jwa.SignatureAlgorithm {
|
||||
return s.alg
|
||||
}
|
||||
|
||||
// Sign signs payload with a ECDSA private key
|
||||
func (s ECDSASigner) Sign(payload []byte, key interface{}) ([]byte, error) {
|
||||
if key == nil {
|
||||
return nil, errors.New(`missing private key while signing payload`)
|
||||
}
|
||||
|
||||
privateKey, ok := key.(*ecdsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, errors.Errorf(`invalid key type %T. *ecdsa.PrivateKey is required`, key)
|
||||
}
|
||||
|
||||
return s.sign(payload, privateKey)
|
||||
}
|
||||
66
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/hmac.go
generated
vendored
Normal file
66
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/hmac.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package sign
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"hash"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var hmacSignFuncs = map[jwa.SignatureAlgorithm]hmacSignFunc{}
|
||||
|
||||
func init() {
|
||||
algs := map[jwa.SignatureAlgorithm]func() hash.Hash{
|
||||
jwa.HS256: sha256.New,
|
||||
jwa.HS384: sha512.New384,
|
||||
jwa.HS512: sha512.New,
|
||||
}
|
||||
|
||||
for alg, h := range algs {
|
||||
hmacSignFuncs[alg] = makeHMACSignFunc(h)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func newHMAC(alg jwa.SignatureAlgorithm) (*HMACSigner, error) {
|
||||
signer, ok := hmacSignFuncs[alg]
|
||||
if !ok {
|
||||
return nil, errors.Errorf(`unsupported algorithm while trying to create HMAC signer: %s`, alg)
|
||||
}
|
||||
|
||||
return &HMACSigner{
|
||||
alg: alg,
|
||||
sign: signer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func makeHMACSignFunc(hfunc func() hash.Hash) hmacSignFunc {
|
||||
return hmacSignFunc(func(payload []byte, key []byte) ([]byte, error) {
|
||||
h := hmac.New(hfunc, key)
|
||||
h.Write(payload)
|
||||
return h.Sum(nil), nil
|
||||
})
|
||||
}
|
||||
|
||||
// Algorithm returns the signer algorithm
|
||||
func (s HMACSigner) Algorithm() jwa.SignatureAlgorithm {
|
||||
return s.alg
|
||||
}
|
||||
|
||||
// Sign signs payload with a Symmetric key
|
||||
func (s HMACSigner) Sign(payload []byte, key interface{}) ([]byte, error) {
|
||||
hmackey, ok := key.([]byte)
|
||||
if !ok {
|
||||
return nil, errors.Errorf(`invalid key type %T. []byte is required`, key)
|
||||
}
|
||||
|
||||
if len(hmackey) == 0 {
|
||||
return nil, errors.New(`missing key while signing payload`)
|
||||
}
|
||||
|
||||
return s.sign(payload, hmackey)
|
||||
}
|
||||
45
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/interface.go
generated
vendored
Normal file
45
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/interface.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package sign
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
// Signer provides a common interface for supported alg signing methods
|
||||
type Signer interface {
|
||||
// Sign creates a signature for the given `payload`.
|
||||
// `key` is the key used for signing the payload, and is usually
|
||||
// the private key type associated with the signature method. For example,
|
||||
// for `jwa.RSXXX` and `jwa.PSXXX` types, you need to pass the
|
||||
// `*"crypto/rsa".PrivateKey` type.
|
||||
// Check the documentation for each signer for details
|
||||
Sign(payload []byte, key interface{}) ([]byte, error)
|
||||
|
||||
Algorithm() jwa.SignatureAlgorithm
|
||||
}
|
||||
|
||||
type rsaSignFunc func([]byte, *rsa.PrivateKey) ([]byte, error)
|
||||
|
||||
// RSASigner uses crypto/rsa to sign the payloads.
|
||||
type RSASigner struct {
|
||||
alg jwa.SignatureAlgorithm
|
||||
sign rsaSignFunc
|
||||
}
|
||||
|
||||
type ecdsaSignFunc func([]byte, *ecdsa.PrivateKey) ([]byte, error)
|
||||
|
||||
// ECDSASigner uses crypto/ecdsa to sign the payloads.
|
||||
type ECDSASigner struct {
|
||||
alg jwa.SignatureAlgorithm
|
||||
sign ecdsaSignFunc
|
||||
}
|
||||
|
||||
type hmacSignFunc func([]byte, []byte) ([]byte, error)
|
||||
|
||||
// HMACSigner uses crypto/hmac to sign the payloads.
|
||||
type HMACSigner struct {
|
||||
alg jwa.SignatureAlgorithm
|
||||
sign hmacSignFunc
|
||||
}
|
||||
97
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/rsa.go
generated
vendored
Normal file
97
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/rsa.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
package sign
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var rsaSignFuncs = map[jwa.SignatureAlgorithm]rsaSignFunc{}
|
||||
|
||||
func init() {
|
||||
algs := map[jwa.SignatureAlgorithm]struct {
|
||||
Hash crypto.Hash
|
||||
SignFunc func(crypto.Hash) rsaSignFunc
|
||||
}{
|
||||
jwa.RS256: {
|
||||
Hash: crypto.SHA256,
|
||||
SignFunc: makeSignPKCS1v15,
|
||||
},
|
||||
jwa.RS384: {
|
||||
Hash: crypto.SHA384,
|
||||
SignFunc: makeSignPKCS1v15,
|
||||
},
|
||||
jwa.RS512: {
|
||||
Hash: crypto.SHA512,
|
||||
SignFunc: makeSignPKCS1v15,
|
||||
},
|
||||
jwa.PS256: {
|
||||
Hash: crypto.SHA256,
|
||||
SignFunc: makeSignPSS,
|
||||
},
|
||||
jwa.PS384: {
|
||||
Hash: crypto.SHA384,
|
||||
SignFunc: makeSignPSS,
|
||||
},
|
||||
jwa.PS512: {
|
||||
Hash: crypto.SHA512,
|
||||
SignFunc: makeSignPSS,
|
||||
},
|
||||
}
|
||||
|
||||
for alg, item := range algs {
|
||||
rsaSignFuncs[alg] = item.SignFunc(item.Hash)
|
||||
}
|
||||
}
|
||||
|
||||
func makeSignPKCS1v15(hash crypto.Hash) rsaSignFunc {
|
||||
return rsaSignFunc(func(payload []byte, key *rsa.PrivateKey) ([]byte, error) {
|
||||
h := hash.New()
|
||||
h.Write(payload)
|
||||
return rsa.SignPKCS1v15(rand.Reader, key, hash, h.Sum(nil))
|
||||
})
|
||||
}
|
||||
|
||||
func makeSignPSS(hash crypto.Hash) rsaSignFunc {
|
||||
return rsaSignFunc(func(payload []byte, key *rsa.PrivateKey) ([]byte, error) {
|
||||
h := hash.New()
|
||||
h.Write(payload)
|
||||
return rsa.SignPSS(rand.Reader, key, hash, h.Sum(nil), &rsa.PSSOptions{
|
||||
SaltLength: rsa.PSSSaltLengthAuto,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func newRSA(alg jwa.SignatureAlgorithm) (*RSASigner, error) {
|
||||
signfn, ok := rsaSignFuncs[alg]
|
||||
if !ok {
|
||||
return nil, errors.Errorf(`unsupported algorithm while trying to create RSA signer: %s`, alg)
|
||||
}
|
||||
return &RSASigner{
|
||||
alg: alg,
|
||||
sign: signfn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Algorithm returns the signer algorithm
|
||||
func (s RSASigner) Algorithm() jwa.SignatureAlgorithm {
|
||||
return s.alg
|
||||
}
|
||||
|
||||
// Sign creates a signature using crypto/rsa. key must be a non-nil instance of
|
||||
// `*"crypto/rsa".PrivateKey`.
|
||||
func (s RSASigner) Sign(payload []byte, key interface{}) ([]byte, error) {
|
||||
if key == nil {
|
||||
return nil, errors.New(`missing private key while signing payload`)
|
||||
}
|
||||
rsakey, ok := key.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
return nil, errors.Errorf(`invalid key type %T. *rsa.PrivateKey is required`, key)
|
||||
}
|
||||
|
||||
return s.sign(payload, rsakey)
|
||||
}
|
||||
21
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/sign.go
generated
vendored
Normal file
21
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign/sign.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package sign
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
// New creates a signer that signs payloads using the given signature algorithm.
|
||||
func New(alg jwa.SignatureAlgorithm) (Signer, error) {
|
||||
switch alg {
|
||||
case jwa.RS256, jwa.RS384, jwa.RS512, jwa.PS256, jwa.PS384, jwa.PS512:
|
||||
return newRSA(alg)
|
||||
case jwa.ES256, jwa.ES384, jwa.ES512:
|
||||
return newECDSA(alg)
|
||||
case jwa.HS256, jwa.HS384, jwa.HS512:
|
||||
return newHMAC(alg)
|
||||
default:
|
||||
return nil, errors.Errorf(`unsupported signature algorithm %s`, alg)
|
||||
}
|
||||
}
|
||||
67
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/ecdsa.go
generated
vendored
Normal file
67
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/ecdsa.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package verify
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"math/big"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
var ecdsaVerifyFuncs = map[jwa.SignatureAlgorithm]ecdsaVerifyFunc{}
|
||||
|
||||
func init() {
|
||||
algs := map[jwa.SignatureAlgorithm]crypto.Hash{
|
||||
jwa.ES256: crypto.SHA256,
|
||||
jwa.ES384: crypto.SHA384,
|
||||
jwa.ES512: crypto.SHA512,
|
||||
}
|
||||
|
||||
for alg, h := range algs {
|
||||
ecdsaVerifyFuncs[alg] = makeECDSAVerifyFunc(h)
|
||||
}
|
||||
}
|
||||
|
||||
func makeECDSAVerifyFunc(hash crypto.Hash) ecdsaVerifyFunc {
|
||||
return ecdsaVerifyFunc(func(payload []byte, signature []byte, key *ecdsa.PublicKey) error {
|
||||
|
||||
r, s := &big.Int{}, &big.Int{}
|
||||
n := len(signature) / 2
|
||||
r.SetBytes(signature[:n])
|
||||
s.SetBytes(signature[n:])
|
||||
|
||||
h := hash.New()
|
||||
h.Write(payload)
|
||||
|
||||
if !ecdsa.Verify(key, h.Sum(nil), r, s) {
|
||||
return errors.New(`failed to verify signature using ecdsa`)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func newECDSA(alg jwa.SignatureAlgorithm) (*ECDSAVerifier, error) {
|
||||
verifyfn, ok := ecdsaVerifyFuncs[alg]
|
||||
if !ok {
|
||||
return nil, errors.Errorf(`unsupported algorithm while trying to create ECDSA verifier: %s`, alg)
|
||||
}
|
||||
|
||||
return &ECDSAVerifier{
|
||||
verify: verifyfn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Verify checks whether the signature for a given input and key is correct
|
||||
func (v ECDSAVerifier) Verify(payload []byte, signature []byte, key interface{}) error {
|
||||
if key == nil {
|
||||
return errors.New(`missing public key while verifying payload`)
|
||||
}
|
||||
ecdsakey, ok := key.(*ecdsa.PublicKey)
|
||||
if !ok {
|
||||
return errors.Errorf(`invalid key type %T. *ecdsa.PublicKey is required`, key)
|
||||
}
|
||||
|
||||
return v.verify(payload, signature, ecdsakey)
|
||||
}
|
||||
33
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/hmac.go
generated
vendored
Normal file
33
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/hmac.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package verify
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign"
|
||||
)
|
||||
|
||||
func newHMAC(alg jwa.SignatureAlgorithm) (*HMACVerifier, error) {
|
||||
|
||||
s, err := sign.New(alg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, `failed to generate HMAC signer`)
|
||||
}
|
||||
return &HMACVerifier{signer: s}, nil
|
||||
}
|
||||
|
||||
// Verify checks whether the signature for a given input and key is correct
|
||||
func (v HMACVerifier) Verify(signingInput, signature []byte, key interface{}) (err error) {
|
||||
|
||||
expected, err := v.signer.Sign(signingInput, key)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, `failed to generated signature`)
|
||||
}
|
||||
|
||||
if !hmac.Equal(signature, expected) {
|
||||
return errors.New(`failed to match hmac signature`)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
39
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/interface.go
generated
vendored
Normal file
39
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/interface.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package verify
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jws/sign"
|
||||
)
|
||||
|
||||
// Verifier provides a common interface for supported alg verification methods
|
||||
type Verifier interface {
|
||||
// Verify checks whether the payload and signature are valid for
|
||||
// the given key.
|
||||
// `key` is the key used for verifying the payload, and is usually
|
||||
// the public key associated with the signature method. For example,
|
||||
// for `jwa.RSXXX` and `jwa.PSXXX` types, you need to pass the
|
||||
// `*"crypto/rsa".PublicKey` type.
|
||||
// Check the documentation for each verifier for details
|
||||
Verify(payload []byte, signature []byte, key interface{}) error
|
||||
}
|
||||
|
||||
type rsaVerifyFunc func([]byte, []byte, *rsa.PublicKey) error
|
||||
|
||||
// RSAVerifier implements the Verifier interface
|
||||
type RSAVerifier struct {
|
||||
verify rsaVerifyFunc
|
||||
}
|
||||
|
||||
type ecdsaVerifyFunc func([]byte, []byte, *ecdsa.PublicKey) error
|
||||
|
||||
// ECDSAVerifier implements the Verifier interface
|
||||
type ECDSAVerifier struct {
|
||||
verify ecdsaVerifyFunc
|
||||
}
|
||||
|
||||
// HMACVerifier implements the Verifier interface
|
||||
type HMACVerifier struct {
|
||||
signer sign.Signer
|
||||
}
|
||||
88
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/rsa.go
generated
vendored
Normal file
88
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/rsa.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package verify
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var rsaVerifyFuncs = map[jwa.SignatureAlgorithm]rsaVerifyFunc{}
|
||||
|
||||
func init() {
|
||||
algs := map[jwa.SignatureAlgorithm]struct {
|
||||
Hash crypto.Hash
|
||||
VerifyFunc func(crypto.Hash) rsaVerifyFunc
|
||||
}{
|
||||
jwa.RS256: {
|
||||
Hash: crypto.SHA256,
|
||||
VerifyFunc: makeVerifyPKCS1v15,
|
||||
},
|
||||
jwa.RS384: {
|
||||
Hash: crypto.SHA384,
|
||||
VerifyFunc: makeVerifyPKCS1v15,
|
||||
},
|
||||
jwa.RS512: {
|
||||
Hash: crypto.SHA512,
|
||||
VerifyFunc: makeVerifyPKCS1v15,
|
||||
},
|
||||
jwa.PS256: {
|
||||
Hash: crypto.SHA256,
|
||||
VerifyFunc: makeVerifyPSS,
|
||||
},
|
||||
jwa.PS384: {
|
||||
Hash: crypto.SHA384,
|
||||
VerifyFunc: makeVerifyPSS,
|
||||
},
|
||||
jwa.PS512: {
|
||||
Hash: crypto.SHA512,
|
||||
VerifyFunc: makeVerifyPSS,
|
||||
},
|
||||
}
|
||||
|
||||
for alg, item := range algs {
|
||||
rsaVerifyFuncs[alg] = item.VerifyFunc(item.Hash)
|
||||
}
|
||||
}
|
||||
|
||||
func makeVerifyPKCS1v15(hash crypto.Hash) rsaVerifyFunc {
|
||||
return rsaVerifyFunc(func(payload, signature []byte, key *rsa.PublicKey) error {
|
||||
h := hash.New()
|
||||
h.Write(payload)
|
||||
return rsa.VerifyPKCS1v15(key, hash, h.Sum(nil), signature)
|
||||
})
|
||||
}
|
||||
|
||||
func makeVerifyPSS(hash crypto.Hash) rsaVerifyFunc {
|
||||
return rsaVerifyFunc(func(payload, signature []byte, key *rsa.PublicKey) error {
|
||||
h := hash.New()
|
||||
h.Write(payload)
|
||||
return rsa.VerifyPSS(key, hash, h.Sum(nil), signature, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func newRSA(alg jwa.SignatureAlgorithm) (*RSAVerifier, error) {
|
||||
verifyfn, ok := rsaVerifyFuncs[alg]
|
||||
if !ok {
|
||||
return nil, errors.Errorf(`unsupported algorithm while trying to create RSA verifier: %s`, alg)
|
||||
}
|
||||
|
||||
return &RSAVerifier{
|
||||
verify: verifyfn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Verify checks if a JWS is valid.
|
||||
func (v RSAVerifier) Verify(payload, signature []byte, key interface{}) error {
|
||||
if key == nil {
|
||||
return errors.New(`missing public key while verifying payload`)
|
||||
}
|
||||
rsaKey, ok := key.(*rsa.PublicKey)
|
||||
if !ok {
|
||||
return errors.Errorf(`invalid key type %T. *rsa.PublicKey is required`, key)
|
||||
}
|
||||
|
||||
return v.verify(payload, signature, rsaKey)
|
||||
}
|
||||
22
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/verify.go
generated
vendored
Normal file
22
vendor/github.com/open-policy-agent/opa/topdown/internal/jwx/jws/verify/verify.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package verify
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/open-policy-agent/opa/topdown/internal/jwx/jwa"
|
||||
)
|
||||
|
||||
// New creates a new JWS verifier using the specified algorithm
|
||||
// and the public key
|
||||
func New(alg jwa.SignatureAlgorithm) (Verifier, error) {
|
||||
switch alg {
|
||||
case jwa.RS256, jwa.RS384, jwa.RS512, jwa.PS256, jwa.PS384, jwa.PS512:
|
||||
return newRSA(alg)
|
||||
case jwa.ES256, jwa.ES384, jwa.ES512:
|
||||
return newECDSA(alg)
|
||||
case jwa.HS256, jwa.HS384, jwa.HS512:
|
||||
return newHMAC(alg)
|
||||
default:
|
||||
return nil, errors.Errorf(`unsupported signature algorithm: %s`, alg)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user