a685e3fc98
Vndr has a simpler configuration and allows pointing to forked packages. Additionally other docker projects are now using vndr making vendoring in distribution more consistent. Updates letsencrypt to use fork. No longer uses sub-vendored packages. Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
225 lines
7.7 KiB
Go
225 lines
7.7 KiB
Go
/*-
|
|
* 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"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// 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
|
|
|
|
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")
|
|
|
|
// 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 (
|
|
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 (
|
|
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)
|
|
)
|
|
|
|
// rawHeader represents the JOSE header for JWE/JWS objects (used for parsing).
|
|
type rawHeader struct {
|
|
Alg string `json:"alg,omitempty"`
|
|
Enc ContentEncryption `json:"enc,omitempty"`
|
|
Zip CompressionAlgorithm `json:"zip,omitempty"`
|
|
Crit []string `json:"crit,omitempty"`
|
|
Apu *byteBuffer `json:"apu,omitempty"`
|
|
Apv *byteBuffer `json:"apv,omitempty"`
|
|
Epk *JsonWebKey `json:"epk,omitempty"`
|
|
Iv *byteBuffer `json:"iv,omitempty"`
|
|
Tag *byteBuffer `json:"tag,omitempty"`
|
|
Jwk *JsonWebKey `json:"jwk,omitempty"`
|
|
Kid string `json:"kid,omitempty"`
|
|
Nonce string `json:"nonce,omitempty"`
|
|
}
|
|
|
|
// JoseHeader represents the read-only JOSE header for JWE/JWS objects.
|
|
type JoseHeader struct {
|
|
KeyID string
|
|
JsonWebKey *JsonWebKey
|
|
Algorithm string
|
|
Nonce string
|
|
}
|
|
|
|
// sanitized produces a cleaned-up header object from the raw JSON.
|
|
func (parsed rawHeader) sanitized() JoseHeader {
|
|
return JoseHeader{
|
|
KeyID: parsed.Kid,
|
|
JsonWebKey: parsed.Jwk,
|
|
Algorithm: parsed.Alg,
|
|
Nonce: parsed.Nonce,
|
|
}
|
|
}
|
|
|
|
// Merge headers from src into dst, giving precedence to headers from l.
|
|
func (dst *rawHeader) merge(src *rawHeader) {
|
|
if src == nil {
|
|
return
|
|
}
|
|
|
|
if dst.Alg == "" {
|
|
dst.Alg = src.Alg
|
|
}
|
|
if dst.Enc == "" {
|
|
dst.Enc = src.Enc
|
|
}
|
|
if dst.Zip == "" {
|
|
dst.Zip = src.Zip
|
|
}
|
|
if dst.Crit == nil {
|
|
dst.Crit = src.Crit
|
|
}
|
|
if dst.Crit == nil {
|
|
dst.Crit = src.Crit
|
|
}
|
|
if dst.Apu == nil {
|
|
dst.Apu = src.Apu
|
|
}
|
|
if dst.Apv == nil {
|
|
dst.Apv = src.Apv
|
|
}
|
|
if dst.Epk == nil {
|
|
dst.Epk = src.Epk
|
|
}
|
|
if dst.Iv == nil {
|
|
dst.Iv = src.Iv
|
|
}
|
|
if dst.Tag == nil {
|
|
dst.Tag = src.Tag
|
|
}
|
|
if dst.Kid == "" {
|
|
dst.Kid = src.Kid
|
|
}
|
|
if dst.Jwk == nil {
|
|
dst.Jwk = src.Jwk
|
|
}
|
|
if dst.Nonce == "" {
|
|
dst.Nonce = src.Nonce
|
|
}
|
|
}
|
|
|
|
// 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
|
|
}
|