Documentation ¶
Index ¶
- Constants
- Variables
- func I2OSP(x *big.Int, buf []byte) error
- func OS2IP(x []byte) *big.Int
- func Sign1(rand io.Reader, signer Signer, headers Headers, payload []byte, ...) ([]byte, error)
- func Sign1Untagged(rand io.Reader, signer Signer, headers Headers, payload []byte, ...) ([]byte, error)
- type Algorithm
- type Headers
- type ProtectedHeader
- type Sign1Message
- type SignMessage
- type Signature
- func (s *Signature) MarshalCBOR() ([]byte, error)
- func (s *Signature) Sign(rand io.Reader, signer Signer, protected cbor.RawMessage, ...) error
- func (s *Signature) UnmarshalCBOR(data []byte) error
- func (s *Signature) Verify(verifier Verifier, protected cbor.RawMessage, payload, external []byte) error
- type Signer
- type UnprotectedHeader
- type UntaggedSign1Message
- type Verifier
Examples ¶
Constants ¶
const ( CBORTagSignMessage = 98 CBORTagSign1Message = 18 )
CBOR Tags for COSE signatures registered in the IANA "CBOR Tags" registry.
Reference: https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml#tags
const ( HeaderLabelAlgorithm int64 = 1 HeaderLabelCritical int64 = 2 HeaderLabelContentType int64 = 3 HeaderLabelKeyID int64 = 4 HeaderLabelIV int64 = 5 HeaderLabelPartialIV int64 = 6 HeaderLabelCounterSignature int64 = 7 HeaderLabelCounterSignature0 int64 = 9 HeaderLabelX5Bag int64 = 32 HeaderLabelX5Chain int64 = 33 HeaderLabelX5T int64 = 34 HeaderLabelX5U int64 = 35 )
COSE Header labels registered in the IANA "COSE Header Parameters" registry.
Reference: https://www.iana.org/assignments/cose/cose.xhtml#header-parameters
Variables ¶
var ( ErrAlgorithmMismatch = errors.New("algorithm mismatch") ErrAlgorithmNotFound = errors.New("algorithm not found") ErrAlgorithmNotSupported = errors.New("algorithm not supported") ErrEmptySignature = errors.New("empty signature") ErrInvalidAlgorithm = errors.New("invalid algorithm") ErrMissingPayload = errors.New("missing payload") ErrNoSignatures = errors.New("no signatures attached") ErrVerification = errors.New("verification error") ErrInvalidPubKey = errors.New("invalid public key") )
Common errors
Functions ¶
func I2OSP ¶
I2OSP - Integer-to-Octet-String primitive converts a nonnegative integer to an octet string of a specified length `len(buf)`, and stores it in `buf`. I2OSP is used for encoding ECDSA signature (r, s) into byte strings.
Reference: https://datatracker.ietf.org/doc/html/rfc8017#section-4.1
func OS2IP ¶
OS2IP - Octet-String-to-Integer primitive converts an octet string to a nonnegative integer. OS2IP is used for decoding ECDSA signature (r, s) from byte strings.
Reference: https://datatracker.ietf.org/doc/html/rfc8017#section-4.2
func Sign1 ¶
func Sign1(rand io.Reader, signer Signer, headers Headers, payload []byte, external []byte) ([]byte, error)
Sign1 signs a Sign1Message using the provided Signer.
This method is a wrapper of `Sign1Message.Sign()`.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
Example ¶
This example demonstrates signing COSE_Sign1_Tagged signatures using Sign1().
// create a signer privateKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) if err != nil { panic(err) } signer, err := cose.NewSigner(cose.AlgorithmES512, privateKey) if err != nil { panic(err) } // sign message headers := cose.Headers{ Protected: cose.ProtectedHeader{ cose.HeaderLabelAlgorithm: cose.AlgorithmES512, }, Unprotected: cose.UnprotectedHeader{ cose.HeaderLabelKeyID: []byte("1"), }, } sig, err := cose.Sign1(rand.Reader, signer, headers, []byte("hello world"), nil) if err != nil { panic(err) } fmt.Println("message signed") _ = sig // further process on sig
Output: message signed
func Sign1Untagged ¶ added in v1.1.0
func Sign1Untagged(rand io.Reader, signer Signer, headers Headers, payload []byte, external []byte) ([]byte, error)
Sign1Untagged signs an UntaggedSign1Message using the provided Signer.
This method is a wrapper of `UntaggedSign1Message.Sign()`.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
Example ¶
This example demonstrates signing COSE_Sign1 signatures using Sign1Untagged().
// create a signer privateKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) if err != nil { panic(err) } signer, err := cose.NewSigner(cose.AlgorithmES512, privateKey) if err != nil { panic(err) } // sign message headers := cose.Headers{ Protected: cose.ProtectedHeader{ cose.HeaderLabelAlgorithm: cose.AlgorithmES512, }, Unprotected: cose.UnprotectedHeader{ cose.HeaderLabelKeyID: []byte("1"), }, } sig, err := cose.Sign1Untagged(rand.Reader, signer, headers, []byte("hello world"), nil) if err != nil { panic(err) } fmt.Println("message signed") _ = sig // further process on sig
Output: message signed
Types ¶
type Algorithm ¶
type Algorithm int64
Algorithm represents an IANA algorithm entry in the COSE Algorithms registry. Algorithms with string values are not supported.
See Also ¶
COSE Algorithms: https://www.iana.org/assignments/cose/cose.xhtml#algorithms
RFC 8152 16.4: https://datatracker.ietf.org/doc/html/rfc8152#section-16.4
const ( // RSASSA-PSS w/ SHA-256 by RFC 8230. // Requires an available crypto.SHA256. AlgorithmPS256 Algorithm = -37 // RSASSA-PSS w/ SHA-384 by RFC 8230. // Requires an available crypto.SHA384. AlgorithmPS384 Algorithm = -38 // RSASSA-PSS w/ SHA-512 by RFC 8230. // Requires an available crypto.SHA512. AlgorithmPS512 Algorithm = -39 // ECDSA w/ SHA-256 by RFC 8152. // Requires an available crypto.SHA256. AlgorithmES256 Algorithm = -7 // ECDSA w/ SHA-384 by RFC 8152. // Requires an available crypto.SHA384. AlgorithmES384 Algorithm = -35 // ECDSA w/ SHA-512 by RFC 8152. // Requires an available crypto.SHA512. AlgorithmES512 Algorithm = -36 // PureEdDSA by RFC 8152. AlgorithmEd25519 Algorithm = -8 )
Algorithms supported by this library.
When using an algorithm which requires hashing, make sure the associated hash function is linked to the binary.
type Headers ¶
type Headers struct { // RawProtected contains the raw CBOR encoded data for the protected header. // It is populated when decoding. // Applications can use this field for customized encoding / decoding of // the protected header in case the default decoder provided by this library // is not preferred. RawProtected cbor.RawMessage // Protected contains parameters that are to be cryptographically protected. // When encoding or signing, the protected header is encoded using the // default CBOR encoder if RawProtected is set to nil. Otherwise, // RawProtected will be used with Protected ignored. Protected ProtectedHeader // RawUnprotected contains the raw CBOR encoded data for the unprotected // header. It is populated when decoding. // Applications can use this field for customized encoding / decoding of // the unprotected header in case the default decoder provided by this // library is not preferred. RawUnprotected cbor.RawMessage // Unprotected contains parameters that are not cryptographically protected. // When encoding, the unprotected header is encoded using the default CBOR // encoder if RawUnprotected is set to nil. Otherwise, RawUnprotected will // be used with Unprotected ignored. Unprotected UnprotectedHeader }
Headers represents "two buckets of information that are not considered to be part of the payload itself, but are used for holding information about content, algorithms, keys, or evaluation hints for the processing of the layer."
It is represented by CDDL fragments:
Headers = ( protected : empty_or_serialized_map, unprotected : header_map ) header_map = { Generic_Headers, * label => values } label = int / tstr values = any empty_or_serialized_map = bstr .cbor header_map / bstr .size 0
See Also ¶
https://tools.ietf.org/html/rfc8152#section-3
func (*Headers) MarshalProtected ¶
MarshalProtected encodes the protected header. RawProtected is returned if it is not set to nil.
func (*Headers) MarshalUnprotected ¶
MarshalUnprotected encodes the unprotected header. RawUnprotected is returned if it is not set to nil.
func (*Headers) UnmarshalFromRaw ¶
UnmarshalFromRaw decodes Protected from RawProtected and Unprotected from RawUnprotected.
type ProtectedHeader ¶
type ProtectedHeader map[interface{}]interface{}
ProtectedHeader contains parameters that are to be cryptographically protected.
func (ProtectedHeader) Algorithm ¶
func (h ProtectedHeader) Algorithm() (Algorithm, error)
Algorithm gets the algorithm value from the algorithm header.
func (ProtectedHeader) Critical ¶
func (h ProtectedHeader) Critical() ([]interface{}, error)
Critical indicates which protected header labels an application that is processing a message is required to understand.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-3.1
func (ProtectedHeader) MarshalCBOR ¶
func (h ProtectedHeader) MarshalCBOR() ([]byte, error)
MarshalCBOR encodes the protected header into a CBOR bstr object. A zero-length header is encoded as a zero-length string rather than as a zero-length map (encoded as h'a0').
func (ProtectedHeader) SetAlgorithm ¶
func (h ProtectedHeader) SetAlgorithm(alg Algorithm)
SetAlgorithm sets the algorithm value to the algorithm header.
func (*ProtectedHeader) UnmarshalCBOR ¶
func (h *ProtectedHeader) UnmarshalCBOR(data []byte) error
UnmarshalCBOR decodes a CBOR bstr object into ProtectedHeader.
ProtectedHeader is an empty_or_serialized_map where
empty_or_serialized_map = bstr .cbor header_map / bstr .size 0
type Sign1Message ¶
Sign1Message represents a decoded COSE_Sign1 message.
Reference: https://tools.ietf.org/html/rfc8152#section-4.2
Example ¶
This example demonstrates signing and verifying COSE_Sign1 signatures.
// create message to be signed msgToSign := cose.NewSign1Message() msgToSign.Payload = []byte("hello world") msgToSign.Headers.Protected.SetAlgorithm(cose.AlgorithmES512) msgToSign.Headers.Unprotected[cose.HeaderLabelKeyID] = []byte("1") // create a signer privateKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) if err != nil { panic(err) } signer, err := cose.NewSigner(cose.AlgorithmES512, privateKey) if err != nil { panic(err) } // sign message err = msgToSign.Sign(rand.Reader, nil, signer) if err != nil { panic(err) } sig, err := msgToSign.MarshalCBOR() if err != nil { panic(err) } fmt.Println("message signed") // create a verifier from a trusted public key publicKey := privateKey.Public() verifier, err := cose.NewVerifier(cose.AlgorithmES512, publicKey) if err != nil { panic(err) } // verify message var msgToVerify cose.Sign1Message err = msgToVerify.UnmarshalCBOR(sig) if err != nil { panic(err) } err = msgToVerify.Verify(nil, verifier) if err != nil { panic(err) } fmt.Println("message verified") // tamper the message and verification should fail msgToVerify.Payload = []byte("foobar") err = msgToVerify.Verify(nil, verifier) if err != cose.ErrVerification { panic(err) } fmt.Println("verification error as expected")
Output: message signed message verified verification error as expected
func NewSign1Message ¶
func NewSign1Message() *Sign1Message
NewSign1Message returns a Sign1Message with header initialized.
func (*Sign1Message) MarshalCBOR ¶
func (m *Sign1Message) MarshalCBOR() ([]byte, error)
MarshalCBOR encodes Sign1Message into a COSE_Sign1_Tagged object.
func (*Sign1Message) Sign ¶
Sign signs a Sign1Message using the provided Signer. The signature is stored in m.Signature.
Note that m.Signature is only valid as long as m.Headers.Protected and m.Payload remain unchanged after calling this method. It is possible to modify m.Headers.Unprotected after signing, i.e., add counter signatures or timestamps.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
func (*Sign1Message) UnmarshalCBOR ¶
func (m *Sign1Message) UnmarshalCBOR(data []byte) error
UnmarshalCBOR decodes a COSE_Sign1_Tagged object into Sign1Message.
func (*Sign1Message) Verify ¶
func (m *Sign1Message) Verify(external []byte, verifier Verifier) error
Verify verifies the signature on the Sign1Message returning nil on success or a suitable error if verification fails.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
type SignMessage ¶
SignMessage represents a decoded COSE_Sign message.
Reference: https://tools.ietf.org/html/rfc8152#section-4.1
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
Example ¶
This example demonstrates signing and verifying COSE_Sign signatures.
The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
// create a signature holder sigHolder := cose.NewSignature() sigHolder.Headers.Protected.SetAlgorithm(cose.AlgorithmES512) sigHolder.Headers.Unprotected[cose.HeaderLabelKeyID] = []byte("1") // create message to be signed msgToSign := cose.NewSignMessage() msgToSign.Payload = []byte("hello world") msgToSign.Signatures = append(msgToSign.Signatures, sigHolder) // create a signer privateKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) if err != nil { panic(err) } signer, err := cose.NewSigner(cose.AlgorithmES512, privateKey) if err != nil { panic(err) } // sign message err = msgToSign.Sign(rand.Reader, nil, signer) if err != nil { panic(err) } sig, err := msgToSign.MarshalCBOR() if err != nil { panic(err) } fmt.Println("message signed") // create a verifier from a trusted public key publicKey := privateKey.Public() verifier, err := cose.NewVerifier(cose.AlgorithmES512, publicKey) if err != nil { panic(err) } // verify message var msgToVerify cose.SignMessage err = msgToVerify.UnmarshalCBOR(sig) if err != nil { panic(err) } err = msgToVerify.Verify(nil, verifier) if err != nil { panic(err) } fmt.Println("message verified") // tamper the message and verification should fail msgToVerify.Payload = []byte("foobar") err = msgToVerify.Verify(nil, verifier) if err != cose.ErrVerification { panic(err) } fmt.Println("verification error as expected")
Output: message signed message verified verification error as expected
func NewSignMessage ¶
func NewSignMessage() *SignMessage
NewSignMessage returns a SignMessage with header initialized.
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
func (*SignMessage) MarshalCBOR ¶
func (m *SignMessage) MarshalCBOR() ([]byte, error)
MarshalCBOR encodes SignMessage into a COSE_Sign_Tagged object.
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
func (*SignMessage) Sign ¶
Sign signs a SignMessage using the provided signers corresponding to the signatures.
See `Signature.Sign()` for advanced signing scenarios.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
func (*SignMessage) UnmarshalCBOR ¶
func (m *SignMessage) UnmarshalCBOR(data []byte) error
UnmarshalCBOR decodes a COSE_Sign_Tagged object into SignMessage.
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
func (*SignMessage) Verify ¶
func (m *SignMessage) Verify(external []byte, verifiers ...Verifier) error
Verify verifies the signatures on the SignMessage against the corresponding verifier, returning nil on success or a suitable error if verification fails.
See `Signature.Verify()` for advanced verification scenarios like threshold policies.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
type Signature ¶
Signature represents a decoded COSE_Signature.
Reference: https://tools.ietf.org/html/rfc8152#section-4.1
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
func NewSignature ¶
func NewSignature() *Signature
NewSignature returns a Signature with header initialized.
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
func (*Signature) MarshalCBOR ¶
MarshalCBOR encodes Signature into a COSE_Signature object.
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
func (*Signature) Sign ¶
func (s *Signature) Sign(rand io.Reader, signer Signer, protected cbor.RawMessage, payload, external []byte) error
Sign signs a Signature using the provided Signer. Signing a COSE_Signature requires the encoded protected header and the payload of its parent message.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
func (*Signature) UnmarshalCBOR ¶
UnmarshalCBOR decodes a COSE_Signature object into Signature.
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
func (*Signature) Verify ¶
func (s *Signature) Verify(verifier Verifier, protected cbor.RawMessage, payload, external []byte) error
Verify verifies the signature, returning nil on success or a suitable error if verification fails. Verifying a COSE_Signature requires the encoded protected header and the payload of its parent message.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
Experimental ¶
Notice: The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later release.
type Signer ¶
type Signer interface { // Algorithm returns the signing algorithm associated with the private key. Algorithm() Algorithm // Sign signs message content with the private key, possibly using entropy // from rand. // The resulting signature should follow RFC 8152 section 8. // // Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8 Sign(rand io.Reader, content []byte) ([]byte, error) }
Signer is an interface for private keys to sign COSE signatures.
func NewSigner ¶
NewSigner returns a signer with a given signing key. The signing key can be a golang built-in crypto private key, a key in HSM, or a remote KMS.
Developers are encouraged to implement the `cose.Signer` interface instead of the `crypto.Signer` interface for better performance.
All signing keys implementing `crypto.Signer` with `Public()` returning a public key of type `*rsa.PublicKey`, `*ecdsa.PublicKey`, or `ed25519.PublicKey` are accepted.
Note: `*rsa.PrivateKey`, `*ecdsa.PrivateKey`, and `ed25519.PrivateKey` implement `crypto.Signer`.
type UnprotectedHeader ¶
type UnprotectedHeader map[interface{}]interface{}
UnprotectedHeader contains parameters that are not cryptographically protected.
func (UnprotectedHeader) MarshalCBOR ¶
func (h UnprotectedHeader) MarshalCBOR() ([]byte, error)
MarshalCBOR encodes the unprotected header into a CBOR map object. A zero-length header is encoded as a zero-length map (encoded as h'a0').
func (*UnprotectedHeader) UnmarshalCBOR ¶
func (h *UnprotectedHeader) UnmarshalCBOR(data []byte) error
UnmarshalCBOR decodes a CBOR map object into UnprotectedHeader.
UnprotectedHeader is a header_map.
type UntaggedSign1Message ¶ added in v1.1.0
type UntaggedSign1Message Sign1Message
func (*UntaggedSign1Message) MarshalCBOR ¶ added in v1.1.0
func (m *UntaggedSign1Message) MarshalCBOR() ([]byte, error)
MarshalCBOR encodes UntaggedSign1Message into a COSE_Sign1 object.
func (*UntaggedSign1Message) Sign ¶ added in v1.1.0
Sign signs an UnttaggedSign1Message using the provided Signer. The signature is stored in m.Signature.
Note that m.Signature is only valid as long as m.Headers.Protected and m.Payload remain unchanged after calling this method. It is possible to modify m.Headers.Unprotected after signing, i.e., add counter signatures or timestamps.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
func (*UntaggedSign1Message) UnmarshalCBOR ¶ added in v1.1.0
func (m *UntaggedSign1Message) UnmarshalCBOR(data []byte) error
UnmarshalCBOR decodes a COSE_Sign1 object into an UnataggedSign1Message.
func (*UntaggedSign1Message) Verify ¶ added in v1.1.0
func (m *UntaggedSign1Message) Verify(external []byte, verifier Verifier) error
Verify verifies the signature on the UntaggedSign1Message returning nil on success or a suitable error if verification fails.
Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4
type Verifier ¶
type Verifier interface { // Algorithm returns the signing algorithm associated with the public key. Algorithm() Algorithm // Verify verifies message content with the public key, returning nil for // success. // Otherwise, it returns ErrVerification. // // Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-8 Verify(content, signature []byte) error }
Verifier is an interface for public keys to verify COSE signatures.