jose

package module
v0.0.0-...-45b0afe Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 20, 2015 License: Apache-2.0 Imports: 28 Imported by: 3

README

Go JOSE

godoc license build coverage

Package jose aims to provide an implementation of the Javascript Object Signing and Encryption set of standards. For the moment, it mainly focuses on encryption and signing based on the JSON Web Encryption and JSON Web Signature standards.

Disclaimer: This library contains encryption software that is subject to the U.S. Export Administration Regulations. You may not export, re-export, transfer or download this code or any part of it in violation of any United States law, directive or regulation. In particular this software may not be exported or re-exported in any form or on any media to Iran, North Sudan, Syria, Cuba, or North Korea, or to denied persons or entities mentioned on any US maintained blocked list.

Overview

The implementation follows the JSON Web Encryption standard (RFC 7516) and JSON Web Signature standard (RFC 7515). Tables of supported algorithms are shown below. The library supports both the compact and full serialization formats, and has optional support for multiple recipients. It also comes with a small command-line utility (jose-util) for encrypting/decrypting JWE messages in a shell.

Supported algorithms

See below for a table of supported algorithms. Algorithm identifiers match the names in the JSON Web Algorithms standard where possible. The Godoc reference has a list of constants.

Key encryption Algorithm identifier(s)
RSA-PKCS#1v1.5 RSA1_5
RSA-OAEP RSA-OAEP, RSA-OAEP-256
AES key wrap A128KW, A192KW, A256KW
AES-GCM key wrap A128GCMKW, A192GCMKW, A256GCMKW
ECDH-ES + AES key wrap ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW
ECDH-ES (direct) ECDH-ES1
Direct encryption dir1

1. Not supported in multi-recipient mode

Signing / MAC Algorithm identifier(s)
RSASSA-PKCS#1v1.5 RS256, RS384, RS512
RSASSA-PSS PS256, PS384, PS512
HMAC HS256, HS384, HS512
ECDSA ES256, ES384, ES512
Content encryption Algorithm identifier(s)
AES-CBC+HMAC A128CBC-HS256, A192CBC-HS384, A256CBC-HS512
AES-GCM A128GCM, A192GCM, A256GCM
Compression Algorithm identifiers(s)
DEFLATE (RFC 1951) DEF
Supported key types

See below for a table of supported key types. These are understood by the library, and can be passed to corresponding functions such as NewEncrypter or NewSigner. Note that if you are creating a new encrypter or signer with a JsonWebKey, the key id of the JsonWebKey (if present) will be added to any resulting messages.

Algorithm(s) Corresponding types
RSA *rsa.PublicKey, *rsa.PrivateKey, *jose.JsonWebKey
ECDH, ECDSA *ecdsa.PublicKey, *ecdsa.PrivateKey, *jose.JsonWebKey
AES, HMAC []byte, *jose.JsonWebKey

Examples

Encryption/decryption example using RSA:

// Generate a public/private key pair to use for this example. The library
// also provides two utility functions (LoadPublicKey and LoadPrivateKey)
// that can be used to load keys from PEM/DER-encoded data.
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
	panic(err)
}

// Instantiate an encrypter using RSA-OAEP with AES128-GCM. An error would
// indicate that the selected algorithm(s) are not currently supported.
publicKey := &privateKey.PublicKey
encrypter, err := NewEncrypter(RSA_OAEP, A128GCM, publicKey)
if err != nil {
	panic(err)
}

// Encrypt a sample plaintext. Calling the encrypter returns an encrypted
// JWE object, which can then be serialized for output afterwards. An error
// would indicate a problem in an underlying cryptographic primitive.
var plaintext = []byte("Lorem ipsum dolor sit amet")
object, err := encrypter.Encrypt(plaintext)
if err != nil {
	panic(err)
}

// Serialize the encrypted object using the full serialization format.
// Alternatively you can also use the compact format here by calling
// object.CompactSerialize() instead.
serialized := object.FullSerialize()

// Parse the serialized, encrypted JWE object. An error would indicate that
// the given input did not represent a valid message.
object, err = ParseEncrypted(serialized)
if err != nil {
	panic(err)
}

// Now we can decrypt and get back our original plaintext. An error here
// would indicate the the message failed to decrypt, e.g. because the auth
// tag was broken or the message was tampered with.
decrypted, err := object.Decrypt(privateKey)
if err != nil {
	panic(err)
}

fmt.Printf(string(decrypted))
// output: Lorem ipsum dolor sit amet

Signing/verification example using RSA:

// Generate a public/private key pair to use for this example. The library
// also provides two utility functions (LoadPublicKey and LoadPrivateKey)
// that can be used to load keys from PEM/DER-encoded data.
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
	panic(err)
}

// Instantiate a signer using RSASSA-PSS (SHA512) with the given private key.
signer, err := NewSigner(PS512, privateKey)
if err != nil {
	panic(err)
}

// Sign a sample payload. Calling the signer returns a protected JWS object,
// which can then be serialized for output afterwards. An error would
// indicate a problem in an underlying cryptographic primitive.
var payload = []byte("Lorem ipsum dolor sit amet")
object, err := signer.Sign(payload)
if err != nil {
	panic(err)
}

// Serialize the encrypted object using the full serialization format.
// Alternatively you can also use the compact format here by calling
// object.CompactSerialize() instead.
serialized := object.FullSerialize()

// Parse the serialized, protected JWS object. An error would indicate that
// the given input did not represent a valid message.
object, err = ParseSigned(serialized)
if err != nil {
	panic(err)
}

// Now we can verify the signature on the payload. An error here would
// indicate the the message failed to verify, e.g. because the signature was
// broken or the message was tampered with.
output, err := object.Verify(&privateKey.PublicKey)
if err != nil {
	panic(err)
}

fmt.Printf(string(output))
// output: Lorem ipsum dolor sit amet

More examples can be found in the Godoc reference for this package. The jose-util subdirectory also contains a small command-line utility for encrypting/decrypting JWE messages which might be useful as an example.

Documentation

Overview

Package jose aims to provide an implementation of the Javascript Object Signing and Encryption set of standards. For the moment, it mainly focuses on encryption and signing based on the JSON Web Encryption and JSON Web Signature standards. The library supports both the compact and full serialization formats, and has optional support for multiple recipients.

Example (JWE)
// Generate a public/private key pair to use for this example. The library
// also provides two utility functions (LoadPublicKey and LoadPrivateKey)
// that can be used to load keys from PEM/DER-encoded data.
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
	panic(err)
}

// Instantiate an encrypter using RSA-OAEP with AES128-GCM. An error would
// indicate that the selected algorithm(s) are not currently supported.
publicKey := &privateKey.PublicKey
encrypter, err := NewEncrypter(RSA_OAEP, A128GCM, publicKey)
if err != nil {
	panic(err)
}

// Encrypt a sample plaintext. Calling the encrypter returns an encrypted
// JWE object, which can then be serialized for output afterwards. An error
// would indicate a problem in an underlying cryptographic primitive.
var plaintext = []byte("Lorem ipsum dolor sit amet")
object, err := encrypter.Encrypt(plaintext)
if err != nil {
	panic(err)
}

// Serialize the encrypted object using the full serialization format.
// Alternatively you can also use the compact format here by calling
// object.CompactSerialize() instead.
serialized := object.FullSerialize()

// Parse the serialized, encrypted JWE object. An error would indicate that
// the given input did not represent a valid message.
object, err = ParseEncrypted(serialized)
if err != nil {
	panic(err)
}

// Now we can decrypt and get back our original plaintext. An error here
// would indicate the the message failed to decrypt, e.g. because the auth
// tag was broken or the message was tampered with.
decrypted, err := object.Decrypt(privateKey)
if err != nil {
	panic(err)
}

fmt.Printf(string(decrypted))
Output:

Lorem ipsum dolor sit amet
Example (JWS)
// Generate a public/private key pair to use for this example. The library
// also provides two utility functions (LoadPublicKey and LoadPrivateKey)
// that can be used to load keys from PEM/DER-encoded data.
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
	panic(err)
}

// Instantiate a signer using RSASSA-PSS (SHA512) with the given private key.
signer, err := NewSigner(PS512, privateKey)
if err != nil {
	panic(err)
}

// Sign a sample payload. Calling the signer returns a protected JWS object,
// which can then be serialized for output afterwards. An error would
// indicate a problem in an underlying cryptographic primitive.
var payload = []byte("Lorem ipsum dolor sit amet")
object, err := signer.Sign(payload)
if err != nil {
	panic(err)
}

// Serialize the encrypted object using the full serialization format.
// Alternatively you can also use the compact format here by calling
// object.CompactSerialize() instead.
serialized := object.FullSerialize()

// Parse the serialized, protected JWS object. An error would indicate that
// the given input did not represent a valid message.
object, err = ParseSigned(serialized)
if err != nil {
	panic(err)
}

// Now we can verify the signature on the payload. An error here would
// indicate the the message failed to verify, e.g. because the signature was
// broken or the message was tampered with.
output, err := object.Verify(&privateKey.PublicKey)
if err != nil {
	panic(err)
}

fmt.Printf(string(output))
Output:

Lorem ipsum dolor sit amet

Index

Examples

Constants

View Source
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)
)

Key management algorithms

View Source
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
)

Signature algorithms

View Source
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)
)

Content encryption algorithms

View Source
const (
	NONE    = CompressionAlgorithm("")    // No compression
	DEFLATE = CompressionAlgorithm("DEF") // DEFLATE (RFC 1951)
)

Compression algorithms

Variables

View Source
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")
)

Functions

func LoadPrivateKey

func LoadPrivateKey(data []byte) (interface{}, error)

LoadPrivateKey loads a private key from PEM/DER-encoded data.

func LoadPublicKey

func LoadPublicKey(data []byte) (interface{}, error)

LoadPublicKey loads a public key from PEM/DER-encoded data.

Types

type CompressionAlgorithm

type CompressionAlgorithm string

CompressionAlgorithm represents an algorithm used for plaintext compression.

type ContentEncryption

type ContentEncryption string

ContentEncryption represents a content encryption algorithm.

type Encrypter

type Encrypter interface {
	Encrypt(plaintext []byte) (*JsonWebEncryption, error)
	EncryptWithAuthData(plaintext []byte, aad []byte) (*JsonWebEncryption, error)
	SetCompression(alg CompressionAlgorithm)
}

Encrypter represents an encrypter which produces an encrypted JWE object.

Example (Encrypt)
// Encrypt a plaintext in order to get an encrypted JWE object.
var plaintext = []byte("This is a secret message")

encrypter.Encrypt(plaintext)
Output:

Example (EncryptWithAuthData)
// Encrypt a plaintext in order to get an encrypted JWE object. Also attach
// some additional authenticated data (AAD) to the object. Note that objects
// with attached AAD can only be represented using full serialization.
var plaintext = []byte("This is a secret message")
var aad = []byte("This is authenticated, but public data")

encrypter.EncryptWithAuthData(plaintext, aad)
Output:

func NewEncrypter

func NewEncrypter(alg KeyAlgorithm, enc ContentEncryption, encryptionKey interface{}) (Encrypter, error)

NewEncrypter creates an appropriate encrypter based on the key type

Example (PublicKey)
var publicKey *rsa.PublicKey

// Instantiate an encrypter using RSA-OAEP with AES128-GCM.
NewEncrypter(RSA_OAEP, A128GCM, publicKey)

// Instantiate an encrypter using RSA-PKCS1v1.5 with AES128-CBC+HMAC.
NewEncrypter(RSA1_5, A128CBC_HS256, publicKey)
Output:

Example (Symmetric)
var sharedKey []byte

// Instantiate an encrypter using AES128-GCM with AES-GCM key wrap.
NewEncrypter(A128GCMKW, A128GCM, sharedKey)

// Instantiate an encrypter using AES256-GCM directly, w/o key wrapping.
NewEncrypter(DIRECT, A256GCM, sharedKey)
Output:

type JoseHeader

type JoseHeader struct {
	KeyID      string
	JsonWebKey *JsonWebKey
	Algorithm  string
	Nonce      string
}

JoseHeader represents the read-only JOSE header for JWE/JWS objects.

type JsonWebEncryption

type JsonWebEncryption struct {
	Header JoseHeader
	// contains filtered or unexported fields
}

JsonWebEncryption represents an encrypted JWE object after parsing.

func ParseEncrypted

func ParseEncrypted(input string) (*JsonWebEncryption, error)

ParseEncrypted parses an encrypted message in compact or full serialization format.

func (JsonWebEncryption) CompactSerialize

func (obj JsonWebEncryption) CompactSerialize() (string, error)

CompactSerialize serializes an object using the compact serialization format.

func (JsonWebEncryption) Decrypt

func (obj JsonWebEncryption) Decrypt(decryptionKey interface{}) ([]byte, error)

Decrypt and validate the object and return the plaintext.

func (JsonWebEncryption) FullSerialize

func (obj JsonWebEncryption) FullSerialize() string

FullSerialize serializes an object using the full JSON serialization format.

func (JsonWebEncryption) GetAuthData

func (obj JsonWebEncryption) GetAuthData() []byte

GetAuthData retrieves the (optional) authenticated data attached to the object.

type JsonWebKey

type JsonWebKey struct {
	Key       interface{}
	KeyID     string
	Algorithm string
	Use       string
}

JsonWebKey represents a public or private key in JWK format.

func (JsonWebKey) MarshalJSON

func (k JsonWebKey) MarshalJSON() ([]byte, error)

MarshalJSON serializes the given key to its JSON representation.

func (*JsonWebKey) Thumbprint

func (k *JsonWebKey) Thumbprint(hash crypto.Hash) ([]byte, error)

Thumbprint computes the JWK Thumbprint of a key using the indicated hash algorithm.

func (*JsonWebKey) UnmarshalJSON

func (k *JsonWebKey) UnmarshalJSON(data []byte) (err error)

UnmarshalJSON reads a key from its JSON representation.

type JsonWebKeySet

type JsonWebKeySet struct {
	Keys []JsonWebKey `json:"keys"`
}

JsonWebKeySet represents a JWK Set object.

func (*JsonWebKeySet) Key

func (s *JsonWebKeySet) Key(kid string) []JsonWebKey

Key convenience method returns keys by key ID. Specification states that a JWK Set "SHOULD" use distinct key IDs, but allows for some cases where they are not distinct. Hence method returns a slice of JsonWebKeys.

type JsonWebSignature

type JsonWebSignature struct {
	Signatures []Signature
	// contains filtered or unexported fields
}

JsonWebSignature represents a signed JWS object after parsing.

func ParseSigned

func ParseSigned(input string) (*JsonWebSignature, error)

ParseSigned parses an encrypted message in compact or full serialization format.

func (JsonWebSignature) CompactSerialize

func (obj JsonWebSignature) CompactSerialize() (string, error)

CompactSerialize serializes an object using the compact serialization format.

func (JsonWebSignature) FullSerialize

func (obj JsonWebSignature) FullSerialize() string

FullSerialize serializes an object using the full JSON serialization format.

func (JsonWebSignature) Verify

func (obj JsonWebSignature) Verify(verificationKey interface{}) ([]byte, error)

Verify validates the signature on the object and returns the payload.

type KeyAlgorithm

type KeyAlgorithm string

KeyAlgorithm represents a key management algorithm.

type MultiEncrypter

type MultiEncrypter interface {
	Encrypt(plaintext []byte) (*JsonWebEncryption, error)
	EncryptWithAuthData(plaintext []byte, aad []byte) (*JsonWebEncryption, error)
	SetCompression(alg CompressionAlgorithm)
	AddRecipient(alg KeyAlgorithm, encryptionKey interface{}) error
}

MultiEncrypter represents an encrypter which supports multiple recipients.

func NewMultiEncrypter

func NewMultiEncrypter(enc ContentEncryption) (MultiEncrypter, error)

NewMultiEncrypter creates a multi-encrypter based on the given parameters

Example
var publicKey *rsa.PublicKey
var sharedKey []byte

// Instantiate an encrypter using AES-GCM.
encrypter, err := NewMultiEncrypter(A128GCM)
if err != nil {
	panic(err)
}

// Add a recipient using a shared key with AES-GCM key wap
err = encrypter.AddRecipient(A128GCMKW, sharedKey)
if err != nil {
	panic(err)
}

// Add a recipient using an RSA public key with RSA-OAEP
err = encrypter.AddRecipient(RSA_OAEP, publicKey)
if err != nil {
	panic(err)
}
Output:

type MultiSigner

type MultiSigner interface {
	Sign(payload []byte) (*JsonWebSignature, error)
	SetNonceSource(source NonceSource)
	AddRecipient(alg SignatureAlgorithm, signingKey interface{}) error
}

MultiSigner represents a signer which supports multiple recipients.

func NewMultiSigner

func NewMultiSigner() MultiSigner

NewMultiSigner creates a signer for multiple recipients

Example
var privateKey *rsa.PrivateKey
var sharedKey []byte

// Instantiate a signer for multiple recipients.
signer := NewMultiSigner()

// Add a recipient using a shared key with HMAC-SHA256
err := signer.AddRecipient(HS256, sharedKey)
if err != nil {
	panic(err)
}

// Add a recipient using an RSA private key with RSASSA-PSS with SHA384
err = signer.AddRecipient(PS384, privateKey)
if err != nil {
	panic(err)
}
Output:

type NonceSource

type NonceSource interface {
	Nonce() (string, error)
}

NonceSource represents a source of random nonces to go into JWS objects

type Signature

type Signature struct {
	// Header fields, such as the signature algorithm
	Header JoseHeader

	// The actual signature value
	Signature []byte
	// contains filtered or unexported fields
}

Signature represents a single signature over the JWS payload and protected header.

type SignatureAlgorithm

type SignatureAlgorithm string

SignatureAlgorithm represents a signature (or MAC) algorithm.

type Signer

type Signer interface {
	Sign(payload []byte) (*JsonWebSignature, error)
	SetNonceSource(source NonceSource)
}

Signer represents a signer which takes a payload and produces a signed JWS object.

func NewSigner

func NewSigner(alg SignatureAlgorithm, signingKey interface{}) (Signer, error)

NewSigner creates an appropriate signer based on the key type

Example (PublicKey)
var rsaPrivateKey *rsa.PrivateKey
var ecdsaPrivateKey *ecdsa.PrivateKey

// Instantiate a signer using RSA-PKCS#1v1.5 with SHA-256.
NewSigner(RS256, rsaPrivateKey)

// Instantiate a signer using ECDSA with SHA-384.
NewSigner(ES384, ecdsaPrivateKey)
Output:

Example (Symmetric)
var sharedKey []byte

// Instantiate an signer using HMAC-SHA256.
NewSigner(HS256, sharedKey)

// Instantiate an signer using HMAC-SHA512.
NewSigner(HS512, sharedKey)
Output:

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL