summaryrefslogtreecommitdiff
path: root/vendor/gopkg.in/square/go-jose.v2/shared.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gopkg.in/square/go-jose.v2/shared.go')
-rw-r--r--vendor/gopkg.in/square/go-jose.v2/shared.go499
1 files changed, 499 insertions, 0 deletions
diff --git a/vendor/gopkg.in/square/go-jose.v2/shared.go b/vendor/gopkg.in/square/go-jose.v2/shared.go
new file mode 100644
index 000000000..b0a6255ec
--- /dev/null
+++ b/vendor/gopkg.in/square/go-jose.v2/shared.go
@@ -0,0 +1,499 @@
+/*-
+ * Copyright 2014 Square Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package jose
+
+import (
+ "crypto/elliptic"
+ "crypto/x509"
+ "encoding/base64"
+ "errors"
+ "fmt"
+
+ "gopkg.in/square/go-jose.v2/json"
+)
+
+// KeyAlgorithm represents a key management algorithm.
+type KeyAlgorithm string
+
+// SignatureAlgorithm represents a signature (or MAC) algorithm.
+type SignatureAlgorithm string
+
+// ContentEncryption represents a content encryption algorithm.
+type ContentEncryption string
+
+// CompressionAlgorithm represents an algorithm used for plaintext compression.
+type CompressionAlgorithm string
+
+// ContentType represents type of the contained data.
+type ContentType string
+
+var (
+ // ErrCryptoFailure represents an error in cryptographic primitive. This
+ // occurs when, for example, a message had an invalid authentication tag or
+ // could not be decrypted.
+ ErrCryptoFailure = errors.New("square/go-jose: error in cryptographic primitive")
+
+ // ErrUnsupportedAlgorithm indicates that a selected algorithm is not
+ // supported. This occurs when trying to instantiate an encrypter for an
+ // algorithm that is not yet implemented.
+ ErrUnsupportedAlgorithm = errors.New("square/go-jose: unknown/unsupported algorithm")
+
+ // ErrUnsupportedKeyType indicates that the given key type/format is not
+ // supported. This occurs when trying to instantiate an encrypter and passing
+ // it a key of an unrecognized type or with unsupported parameters, such as
+ // an RSA private key with more than two primes.
+ ErrUnsupportedKeyType = errors.New("square/go-jose: unsupported key type/format")
+
+ // ErrInvalidKeySize indicates that the given key is not the correct size
+ // for the selected algorithm. This can occur, for example, when trying to
+ // encrypt with AES-256 but passing only a 128-bit key as input.
+ ErrInvalidKeySize = errors.New("square/go-jose: invalid key size for algorithm")
+
+ // ErrNotSupported serialization of object is not supported. This occurs when
+ // trying to compact-serialize an object which can't be represented in
+ // compact form.
+ ErrNotSupported = errors.New("square/go-jose: compact serialization not supported for object")
+
+ // ErrUnprotectedNonce indicates that while parsing a JWS or JWE object, a
+ // nonce header parameter was included in an unprotected header object.
+ ErrUnprotectedNonce = errors.New("square/go-jose: Nonce parameter included in unprotected header")
+)
+
+// Key management algorithms
+const (
+ ED25519 = KeyAlgorithm("ED25519")
+ RSA1_5 = KeyAlgorithm("RSA1_5") // RSA-PKCS1v1.5
+ RSA_OAEP = KeyAlgorithm("RSA-OAEP") // RSA-OAEP-SHA1
+ RSA_OAEP_256 = KeyAlgorithm("RSA-OAEP-256") // RSA-OAEP-SHA256
+ A128KW = KeyAlgorithm("A128KW") // AES key wrap (128)
+ A192KW = KeyAlgorithm("A192KW") // AES key wrap (192)
+ A256KW = KeyAlgorithm("A256KW") // AES key wrap (256)
+ DIRECT = KeyAlgorithm("dir") // Direct encryption
+ ECDH_ES = KeyAlgorithm("ECDH-ES") // ECDH-ES
+ ECDH_ES_A128KW = KeyAlgorithm("ECDH-ES+A128KW") // ECDH-ES + AES key wrap (128)
+ ECDH_ES_A192KW = KeyAlgorithm("ECDH-ES+A192KW") // ECDH-ES + AES key wrap (192)
+ ECDH_ES_A256KW = KeyAlgorithm("ECDH-ES+A256KW") // ECDH-ES + AES key wrap (256)
+ A128GCMKW = KeyAlgorithm("A128GCMKW") // AES-GCM key wrap (128)
+ A192GCMKW = KeyAlgorithm("A192GCMKW") // AES-GCM key wrap (192)
+ A256GCMKW = KeyAlgorithm("A256GCMKW") // AES-GCM key wrap (256)
+ PBES2_HS256_A128KW = KeyAlgorithm("PBES2-HS256+A128KW") // PBES2 + HMAC-SHA256 + AES key wrap (128)
+ PBES2_HS384_A192KW = KeyAlgorithm("PBES2-HS384+A192KW") // PBES2 + HMAC-SHA384 + AES key wrap (192)
+ PBES2_HS512_A256KW = KeyAlgorithm("PBES2-HS512+A256KW") // PBES2 + HMAC-SHA512 + AES key wrap (256)
+)
+
+// Signature algorithms
+const (
+ EdDSA = SignatureAlgorithm("EdDSA")
+ HS256 = SignatureAlgorithm("HS256") // HMAC using SHA-256
+ HS384 = SignatureAlgorithm("HS384") // HMAC using SHA-384
+ HS512 = SignatureAlgorithm("HS512") // HMAC using SHA-512
+ 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
+ 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
+ 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
+)
+
+// Content encryption algorithms
+const (
+ A128CBC_HS256 = ContentEncryption("A128CBC-HS256") // AES-CBC + HMAC-SHA256 (128)
+ A192CBC_HS384 = ContentEncryption("A192CBC-HS384") // AES-CBC + HMAC-SHA384 (192)
+ A256CBC_HS512 = ContentEncryption("A256CBC-HS512") // AES-CBC + HMAC-SHA512 (256)
+ A128GCM = ContentEncryption("A128GCM") // AES-GCM (128)
+ A192GCM = ContentEncryption("A192GCM") // AES-GCM (192)
+ A256GCM = ContentEncryption("A256GCM") // AES-GCM (256)
+)
+
+// Compression algorithms
+const (
+ NONE = CompressionAlgorithm("") // No compression
+ DEFLATE = CompressionAlgorithm("DEF") // DEFLATE (RFC 1951)
+)
+
+// A key in the protected header of a JWS object. Use of the Header...
+// constants is preferred to enhance type safety.
+type HeaderKey string
+
+const (
+ HeaderType HeaderKey = "typ" // string
+ HeaderContentType = "cty" // string
+
+ // These are set by go-jose and shouldn't need to be set by consumers of the
+ // library.
+ headerAlgorithm = "alg" // string
+ headerEncryption = "enc" // ContentEncryption
+ headerCompression = "zip" // CompressionAlgorithm
+ headerCritical = "crit" // []string
+
+ headerAPU = "apu" // *byteBuffer
+ headerAPV = "apv" // *byteBuffer
+ headerEPK = "epk" // *JSONWebKey
+ headerIV = "iv" // *byteBuffer
+ headerTag = "tag" // *byteBuffer
+ headerX5c = "x5c" // []*x509.Certificate
+
+ headerJWK = "jwk" // *JSONWebKey
+ headerKeyID = "kid" // string
+ headerNonce = "nonce" // string
+
+ headerP2C = "p2c" // *byteBuffer (int)
+ headerP2S = "p2s" // *byteBuffer ([]byte)
+
+)
+
+// rawHeader represents the JOSE header for JWE/JWS objects (used for parsing).
+//
+// The decoding of the constituent items is deferred because we want to marshal
+// some members into particular structs rather than generic maps, but at the
+// same time we need to receive any extra fields unhandled by this library to
+// pass through to consuming code in case it wants to examine them.
+type rawHeader map[HeaderKey]*json.RawMessage
+
+// Header represents the read-only JOSE header for JWE/JWS objects.
+type Header struct {
+ KeyID string
+ JSONWebKey *JSONWebKey
+ Algorithm string
+ Nonce string
+
+ // Unverified certificate chain parsed from x5c header.
+ certificates []*x509.Certificate
+
+ // Any headers not recognised above get unmarshaled
+ // from JSON in a generic manner and placed in this map.
+ ExtraHeaders map[HeaderKey]interface{}
+}
+
+// Certificates verifies & returns the certificate chain present
+// in the x5c header field of a message, if one was present. Returns
+// an error if there was no x5c header present or the chain could
+// not be validated with the given verify options.
+func (h Header) Certificates(opts x509.VerifyOptions) ([][]*x509.Certificate, error) {
+ if len(h.certificates) == 0 {
+ return nil, errors.New("square/go-jose: no x5c header present in message")
+ }
+
+ leaf := h.certificates[0]
+ if opts.Intermediates == nil {
+ opts.Intermediates = x509.NewCertPool()
+ for _, intermediate := range h.certificates[1:] {
+ opts.Intermediates.AddCert(intermediate)
+ }
+ }
+
+ return leaf.Verify(opts)
+}
+
+func (parsed rawHeader) set(k HeaderKey, v interface{}) error {
+ b, err := json.Marshal(v)
+ if err != nil {
+ return err
+ }
+
+ parsed[k] = makeRawMessage(b)
+ return nil
+}
+
+// getString gets a string from the raw JSON, defaulting to "".
+func (parsed rawHeader) getString(k HeaderKey) string {
+ v, ok := parsed[k]
+ if !ok || v == nil {
+ return ""
+ }
+ var s string
+ err := json.Unmarshal(*v, &s)
+ if err != nil {
+ return ""
+ }
+ return s
+}
+
+// getByteBuffer gets a byte buffer from the raw JSON. Returns (nil, nil) if
+// not specified.
+func (parsed rawHeader) getByteBuffer(k HeaderKey) (*byteBuffer, error) {
+ v := parsed[k]
+ if v == nil {
+ return nil, nil
+ }
+ var bb *byteBuffer
+ err := json.Unmarshal(*v, &bb)
+ if err != nil {
+ return nil, err
+ }
+ return bb, nil
+}
+
+// getAlgorithm extracts parsed "alg" from the raw JSON as a KeyAlgorithm.
+func (parsed rawHeader) getAlgorithm() KeyAlgorithm {
+ return KeyAlgorithm(parsed.getString(headerAlgorithm))
+}
+
+// getSignatureAlgorithm extracts parsed "alg" from the raw JSON as a SignatureAlgorithm.
+func (parsed rawHeader) getSignatureAlgorithm() SignatureAlgorithm {
+ return SignatureAlgorithm(parsed.getString(headerAlgorithm))
+}
+
+// getEncryption extracts parsed "enc" from the raw JSON.
+func (parsed rawHeader) getEncryption() ContentEncryption {
+ return ContentEncryption(parsed.getString(headerEncryption))
+}
+
+// getCompression extracts parsed "zip" from the raw JSON.
+func (parsed rawHeader) getCompression() CompressionAlgorithm {
+ return CompressionAlgorithm(parsed.getString(headerCompression))
+}
+
+func (parsed rawHeader) getNonce() string {
+ return parsed.getString(headerNonce)
+}
+
+// getEPK extracts parsed "epk" from the raw JSON.
+func (parsed rawHeader) getEPK() (*JSONWebKey, error) {
+ v := parsed[headerEPK]
+ if v == nil {
+ return nil, nil
+ }
+ var epk *JSONWebKey
+ err := json.Unmarshal(*v, &epk)
+ if err != nil {
+ return nil, err
+ }
+ return epk, nil
+}
+
+// getAPU extracts parsed "apu" from the raw JSON.
+func (parsed rawHeader) getAPU() (*byteBuffer, error) {
+ return parsed.getByteBuffer(headerAPU)
+}
+
+// getAPV extracts parsed "apv" from the raw JSON.
+func (parsed rawHeader) getAPV() (*byteBuffer, error) {
+ return parsed.getByteBuffer(headerAPV)
+}
+
+// getIV extracts parsed "iv" frpom the raw JSON.
+func (parsed rawHeader) getIV() (*byteBuffer, error) {
+ return parsed.getByteBuffer(headerIV)
+}
+
+// getTag extracts parsed "tag" frpom the raw JSON.
+func (parsed rawHeader) getTag() (*byteBuffer, error) {
+ return parsed.getByteBuffer(headerTag)
+}
+
+// getJWK extracts parsed "jwk" from the raw JSON.
+func (parsed rawHeader) getJWK() (*JSONWebKey, error) {
+ v := parsed[headerJWK]
+ if v == nil {
+ return nil, nil
+ }
+ var jwk *JSONWebKey
+ err := json.Unmarshal(*v, &jwk)
+ if err != nil {
+ return nil, err
+ }
+ return jwk, nil
+}
+
+// getCritical extracts parsed "crit" from the raw JSON. If omitted, it
+// returns an empty slice.
+func (parsed rawHeader) getCritical() ([]string, error) {
+ v := parsed[headerCritical]
+ if v == nil {
+ return nil, nil
+ }
+
+ var q []string
+ err := json.Unmarshal(*v, &q)
+ if err != nil {
+ return nil, err
+ }
+ return q, nil
+}
+
+// getS2C extracts parsed "p2c" from the raw JSON.
+func (parsed rawHeader) getP2C() (int, error) {
+ v := parsed[headerP2C]
+ if v == nil {
+ return 0, nil
+ }
+
+ var p2c int
+ err := json.Unmarshal(*v, &p2c)
+ if err != nil {
+ return 0, err
+ }
+ return p2c, nil
+}
+
+// getS2S extracts parsed "p2s" from the raw JSON.
+func (parsed rawHeader) getP2S() (*byteBuffer, error) {
+ return parsed.getByteBuffer(headerP2S)
+}
+
+// sanitized produces a cleaned-up header object from the raw JSON.
+func (parsed rawHeader) sanitized() (h Header, err error) {
+ for k, v := range parsed {
+ if v == nil {
+ continue
+ }
+ switch k {
+ case headerJWK:
+ var jwk *JSONWebKey
+ err = json.Unmarshal(*v, &jwk)
+ if err != nil {
+ err = fmt.Errorf("failed to unmarshal JWK: %v: %#v", err, string(*v))
+ return
+ }
+ h.JSONWebKey = jwk
+ case headerKeyID:
+ var s string
+ err = json.Unmarshal(*v, &s)
+ if err != nil {
+ err = fmt.Errorf("failed to unmarshal key ID: %v: %#v", err, string(*v))
+ return
+ }
+ h.KeyID = s
+ case headerAlgorithm:
+ var s string
+ err = json.Unmarshal(*v, &s)
+ if err != nil {
+ err = fmt.Errorf("failed to unmarshal algorithm: %v: %#v", err, string(*v))
+ return
+ }
+ h.Algorithm = s
+ case headerNonce:
+ var s string
+ err = json.Unmarshal(*v, &s)
+ if err != nil {
+ err = fmt.Errorf("failed to unmarshal nonce: %v: %#v", err, string(*v))
+ return
+ }
+ h.Nonce = s
+ case headerX5c:
+ c := []string{}
+ err = json.Unmarshal(*v, &c)
+ if err != nil {
+ err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v))
+ return
+ }
+ h.certificates, err = parseCertificateChain(c)
+ if err != nil {
+ err = fmt.Errorf("failed to unmarshal x5c header: %v: %#v", err, string(*v))
+ return
+ }
+ default:
+ if h.ExtraHeaders == nil {
+ h.ExtraHeaders = map[HeaderKey]interface{}{}
+ }
+ var v2 interface{}
+ err = json.Unmarshal(*v, &v2)
+ if err != nil {
+ err = fmt.Errorf("failed to unmarshal value: %v: %#v", err, string(*v))
+ return
+ }
+ h.ExtraHeaders[k] = v2
+ }
+ }
+ return
+}
+
+func parseCertificateChain(chain []string) ([]*x509.Certificate, error) {
+ out := make([]*x509.Certificate, len(chain))
+ for i, cert := range chain {
+ raw, err := base64.StdEncoding.DecodeString(cert)
+ if err != nil {
+ return nil, err
+ }
+ out[i], err = x509.ParseCertificate(raw)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return out, nil
+}
+
+func (dst rawHeader) isSet(k HeaderKey) bool {
+ dvr := dst[k]
+ if dvr == nil {
+ return false
+ }
+
+ var dv interface{}
+ err := json.Unmarshal(*dvr, &dv)
+ if err != nil {
+ return true
+ }
+
+ if dvStr, ok := dv.(string); ok {
+ return dvStr != ""
+ }
+
+ return true
+}
+
+// Merge headers from src into dst, giving precedence to headers from l.
+func (dst rawHeader) merge(src *rawHeader) {
+ if src == nil {
+ return
+ }
+
+ for k, v := range *src {
+ if dst.isSet(k) {
+ continue
+ }
+
+ dst[k] = v
+ }
+}
+
+// Get JOSE name of curve
+func curveName(crv elliptic.Curve) (string, error) {
+ switch crv {
+ case elliptic.P256():
+ return "P-256", nil
+ case elliptic.P384():
+ return "P-384", nil
+ case elliptic.P521():
+ return "P-521", nil
+ default:
+ return "", fmt.Errorf("square/go-jose: unsupported/unknown elliptic curve")
+ }
+}
+
+// Get size of curve in bytes
+func curveSize(crv elliptic.Curve) int {
+ bits := crv.Params().BitSize
+
+ div := bits / 8
+ mod := bits % 8
+
+ if mod == 0 {
+ return div
+ }
+
+ return div + 1
+}
+
+func makeRawMessage(b []byte) *json.RawMessage {
+ rm := json.RawMessage(b)
+ return &rm
+}