cose

package
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2024 License: MIT Imports: 6 Imported by: 2

Documentation

Overview

Package cose implements CBOR Object Signing and Encryption (COSE) as defined in RFC9052. https://datatracker.ietf.org/doc/html/rfc9052.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func RemoveCBORTag added in v0.6.7

func RemoveCBORTag(data []byte) []byte

RemoveCBORTag removes the CWT_Tag / COSE_Sign_Tag / COSE_Sign1_Tag / COSE_Encrypt_Tag / COSE_Encrypt0_Tag / COSE_Mac_Tag / COSE_Mac0_Tag from the data.

Types

type Encrypt0Message

type Encrypt0Message[T any] struct {
	// protected header parameters: iana.HeaderParameterAlg, iana.HeaderParameterCrit.
	Protected Headers
	// Other header parameters.
	Unprotected Headers
	// If payload is []byte or cbor.RawMessage,
	// it will not be encoded/decoded by key.MarshalCBOR/key.UnmarshalCBOR.
	Payload T
	// contains filtered or unexported fields
}

Encrypt0Message represents a COSE_Encrypt0 object.

Reference https://datatracker.ietf.org/doc/html/rfc9052#name-single-recipient-encrypted.

Example
package main

import (
	"fmt"

	"github.com/ldclabs/cose/cose"
	"github.com/ldclabs/cose/cwt"
	"github.com/ldclabs/cose/iana"
	"github.com/ldclabs/cose/key"

	_ "github.com/ldclabs/cose/key/aesccm"
)

func main() {
	// load key
	k := key.Key{
		iana.KeyParameterKty:        iana.KeyTypeSymmetric,
		iana.KeyParameterKid:        []byte("our-secret2"),
		iana.KeyParameterAlg:        iana.AlgorithmAES_CCM_16_64_128,
		iana.SymmetricKeyParameterK: key.Base64Bytesify("hJtXhkV8FJG-Onbc6mxCcY"),
	}

	encryptor, err := k.Encryptor()
	if err != nil {
		panic(err)
	}

	// create a claim set
	claims := cwt.Claims{
		Issuer:     "ldc:ca",
		Subject:    "ldc:chain",
		Audience:   "ldc:txpool",
		Expiration: 1670123579,
		CWTID:      []byte{1, 2, 3, 4},
	}

	// create a COSE_Encrypt0 message
	obj := &cose.Encrypt0Message[cwt.Claims]{
		Payload: claims,
	}

	// encrypt and encode COSE_Encrypt0 message
	cwtData, err := obj.EncryptAndEncode(encryptor, []byte("some external data."))
	if err != nil {
		panic(err)
	}

	// will generate a random IV for each encryption when not set.
	// iv, _ := obj.Unprotected.GetBytes(iana.HeaderParameterIV)
	// fmt.Printf("IV: %x\n", iv)
	// IV: ab1ec0651cc7878ab5410eb366

	fmt.Printf("CWT(%d bytes): %x...\n", len(cwtData), cwtData[:20])
	// CWT(89 bytes): d08343a1010aa2044b6f75722d73656372657432...

	obj2, err := cose.DecryptEncrypt0Message[cwt.Claims](encryptor, cwtData, []byte("some external data."))
	if err != nil {
		panic(err)
	}
	fmt.Printf("Payload: %#v\n", obj2.Payload)
	// Payload: cwt.Claims{Issuer:"ldc:ca", Subject:"ldc:chain", Audience:"ldc:txpool", Expiration:0x638c103b, NotBefore:0x0, IssuedAt:0x0, CWTID:key.ByteStr{0x1, 0x2, 0x3, 0x4}}

}
Output:

CWT(89 bytes): d08343a1010aa2044b6f75722d73656372657432...
Payload: cwt.Claims{Issuer:"ldc:ca", Subject:"ldc:chain", Audience:"ldc:txpool", Expiration:0x638c103b, NotBefore:0x0, IssuedAt:0x0, CWTID:key.ByteStr{0x1, 0x2, 0x3, 0x4}}

func DecryptEncrypt0Message added in v0.4.0

func DecryptEncrypt0Message[T any](encryptor key.Encryptor, coseData, externalData []byte) (*Encrypt0Message[T], error)

DecryptEncrypt0Message decrypts and decodes a COSE_Encrypt0 object with a Encryptor and returns a *Encrypt0Message. `externalData` should be the same as the one used when encrypting.

func (*Encrypt0Message[T]) Bytesify

func (m *Encrypt0Message[T]) Bytesify() []byte

Bytesify returns a CBOR-encoded byte slice. It returns nil if MarshalCBOR failed.

func (*Encrypt0Message[T]) Decrypt

func (m *Encrypt0Message[T]) Decrypt(encryptor key.Encryptor, externalData []byte) error

Decrypt decrypts a COSE_Encrypt0 object with a Encryptor. It should call `Encrypt0Message.UnmarshalCBOR` before calling this method. `externalData` should be the same as the one used when encrypting.

func (*Encrypt0Message[T]) Encrypt

func (m *Encrypt0Message[T]) Encrypt(encryptor key.Encryptor, externalData []byte) error

Encrypt encrypt a COSE_Encrypt0 object with a Encryptor. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data

func (*Encrypt0Message[T]) EncryptAndEncode added in v0.4.0

func (m *Encrypt0Message[T]) EncryptAndEncode(encryptor key.Encryptor, externalData []byte) ([]byte, error)

EncryptAndEncode encrypts and encodes a COSE_Encrypt0 object with a Encryptor. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data

func (*Encrypt0Message[T]) MarshalCBOR

func (m *Encrypt0Message[T]) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for Encrypt0Message. It should call `Encrypt0Message.Encrypt` before calling this method.

func (*Encrypt0Message[T]) UnmarshalCBOR

func (m *Encrypt0Message[T]) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for Encrypt0Message.

type EncryptMessage added in v0.5.0

type EncryptMessage[T any] struct {
	// protected header parameters: iana.HeaderParameterAlg, iana.HeaderParameterCrit.
	Protected Headers
	// Other header parameters.
	Unprotected Headers
	// If payload is []byte or cbor.RawMessage,
	// it will not be encoded/decoded by key.MarshalCBOR/key.UnmarshalCBOR.
	Payload T
	// contains filtered or unexported fields
}

EncryptMessage represents a COSE_Encrypt object.

Reference https://datatracker.ietf.org/doc/html/rfc9052#name-single-recipient-encrypted.

Example
package main

import (
	"fmt"

	"github.com/ldclabs/cose/cose"
	"github.com/ldclabs/cose/iana"
	"github.com/ldclabs/cose/key"
	"github.com/ldclabs/cose/key/aesgcm"
	"github.com/ldclabs/cose/key/ecdh"
	"github.com/ldclabs/cose/key/ecdsa"
	"github.com/ldclabs/cose/key/hkdf"
)

func main() {
	keyR := key.Key{
		iana.KeyParameterKty:    iana.KeyTypeEC2,
		iana.KeyParameterKid:    []byte("meriadoc.brandybuck@buckland.example"),
		iana.EC2KeyParameterCrv: iana.EllipticCurveP_256,
		iana.EC2KeyParameterX:   key.Base64Bytesify("Ze2loSV3wrroKUN_4zhwGhCqo3Xhu1td4QjeQ5wIVR0"),
		iana.EC2KeyParameterY:   key.Base64Bytesify("HlLtdXARY_f55A3fnzQbPcm6hgr34Mp8p-nuzQCE0Zw"),
		iana.EC2KeyParameterD:   key.Base64Bytesify("r_kHyZ-a06rmxM3yESK84r1otSg-aQcVStkRhA-iCM8"),
	}

	keyS := key.Key{
		iana.KeyParameterKty:    iana.KeyTypeEC2,
		iana.KeyParameterKid:    []byte("meriadoc.brandybuck@buckland.example"),
		iana.EC2KeyParameterCrv: iana.EllipticCurveP_256,
		iana.EC2KeyParameterX:   key.Base64Bytesify("mPUKT_bAWGHIhg0TpjjqVsP1rXWQu_vwVOHHtNkdYoA"),
		iana.EC2KeyParameterY:   key.Base64Bytesify("8BQAsImGeAS46fyWw5MhYfGTT0IjBpFw2SS34Dv4Irs"),
	}

	ecdher, err := ecdh.NewECDHer(keyR)
	if err != nil {
		panic(err)
	}

	// shared secret by ECDH-ES
	secret, err := ecdher.ECDH(keyS)
	if err != nil {
		panic(err)
	}

	// derive the key from the shared secret
	kdfContext := cose.KDFContext{
		AlgorithmID: iana.AlgorithmA128GCM,
		SuppPubInfo: cose.SuppPubInfo{
			KeyDataLength: 128,
			Protected: cose.Headers{
				iana.HeaderParameterAlg: iana.AlgorithmECDH_ES_HKDF_256,
			},
		},
	}
	ctxData, err := key.MarshalCBOR(kdfContext)
	if err != nil {
		panic(err)
	}
	cek, err := hkdf.HKDF256(secret, nil, ctxData, 128/8)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Derived key: %X\n", cek)
	// Derived key: 56074D506729CA40C4B4FE50C6439893

	gcmkey, err := aesgcm.KeyFrom(iana.AlgorithmA128GCM, cek)
	if err != nil {
		panic(err)
	}

	encryptor, err := gcmkey.Encryptor()
	if err != nil {
		panic(err)
	}

	obj := &cose.EncryptMessage[[]byte]{
		Payload: []byte("Encryption example for spec - Direct ECDH"),
	}

	err = obj.Encrypt(encryptor, nil)
	if err != nil {
		panic(err)
	}

	ck, err := ecdsa.ToCompressedKey(keyS)
	if err != nil {
		panic(err)
	}
	rp := &cose.Recipient{
		Protected: cose.Headers{iana.HeaderParameterAlg: iana.AlgorithmECDH_ES_HKDF_256},
		Unprotected: cose.Headers{
			iana.HeaderAlgorithmParameterEphemeralKey: ck,
			iana.HeaderParameterKid:                   []byte("meriadoc.brandybuck@buckland.example"),
		},
	}
	err = obj.AddRecipient(rp)
	if err != nil {
		panic(err)
	}

	output, err := key.MarshalCBOR(obj)
	if err != nil {
		panic(err)
	}
	fmt.Printf("COSE(%d bytes): %x...\n", len(output), output[:20])
	// COSE(194 bytes): d8608443a10101a20454adbfc99d99420ac0920c...

	var obj2 cose.EncryptMessage[[]byte]
	err = key.UnmarshalCBOR(output, &obj2)
	if err != nil {
		panic(err)
	}
	err = obj2.Decrypt(encryptor, nil)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Decrypt Payload: %q\n", string(obj2.Payload))
	// Decrypt Payload: "Encryption example for spec - Direct ECDH"

}
Output:

Derived key: 56074D506729CA40C4B4FE50C6439893
COSE(194 bytes): d8608443a10101a20454adbfc99d99420ac0920c...
Decrypt Payload: "Encryption example for spec - Direct ECDH"

func DecryptEncryptMessage added in v0.5.0

func DecryptEncryptMessage[T any](encryptor key.Encryptor, coseData, externalData []byte) (*EncryptMessage[T], error)

DecryptEncryptMessage decrypts and decodes a COSE_Encrypt object with a Encryptor and returns a *EncryptMessage. `externalData` should be the same as the one used when encrypting.

func (*EncryptMessage[T]) AddRecipient added in v0.5.0

func (m *EncryptMessage[T]) AddRecipient(recipient *Recipient) error

AddRecipient add a COSE Recipient to the COSE_Encrypt object.

func (*EncryptMessage[T]) Bytesify added in v0.5.0

func (m *EncryptMessage[T]) Bytesify() []byte

Bytesify returns a CBOR-encoded byte slice. It returns nil if MarshalCBOR failed.

func (*EncryptMessage[T]) Decrypt added in v0.5.0

func (m *EncryptMessage[T]) Decrypt(encryptor key.Encryptor, externalData []byte) error

Decrypt decrypts a COSE_Encrypt object with a Encryptor. It should call `EncryptMessage.UnmarshalCBOR` before calling this method. `externalData` should be the same as the one used when encrypting.

func (*EncryptMessage[T]) Encrypt added in v0.5.0

func (m *EncryptMessage[T]) Encrypt(encryptor key.Encryptor, externalData []byte) error

Encrypt encrypt a COSE_Encrypt object with a Encryptor. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data.

func (*EncryptMessage[T]) EncryptAndEncode added in v0.5.0

func (m *EncryptMessage[T]) EncryptAndEncode(encryptor key.Encryptor, externalData []byte) ([]byte, error)

EncryptAndEncode encrypts and encodes a COSE_Encrypt object with a Encryptor. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data.

func (*EncryptMessage[T]) MarshalCBOR added in v0.5.0

func (m *EncryptMessage[T]) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for EncryptMessage. It should call `EncryptMessage.Encrypt` before calling this method.

func (*EncryptMessage[T]) Recipients added in v0.5.0

func (m *EncryptMessage[T]) Recipients() []*Recipient

Recipients returns recipients in the COSE_Encrypt object

func (*EncryptMessage[T]) UnmarshalCBOR added in v0.5.0

func (m *EncryptMessage[T]) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for EncryptMessage.

type Headers

type Headers key.CoseMap

Headers represents a COSE Generic_Headers structure.

func HeadersFromBytes added in v0.6.10

func HeadersFromBytes(data []byte) (Headers, error)

HeadersFromBytes decode bytes into a Headers. It returns (Headers{}, nil) if data is nil or empty.

func (Headers) Bytes added in v0.6.10

func (h Headers) Bytes() ([]byte, error)

Bytesify returns a CBOR-encoded byte slice. It returns ([]byte{}, nil) if Headers is nil or empty.

func (Headers) Bytesify

func (h Headers) Bytesify() []byte

Bytesify returns a CBOR-encoded byte slice. It returns nil if MarshalCBOR failed.

func (Headers) Get added in v1.3.0

func (h Headers) Get(p any) any

Get returns the value of the given parameter.

func (Headers) GetBool added in v0.6.0

func (h Headers) GetBool(p any) (bool, error)

GetBool returns the value of the given parameter as a bool, or a error.

func (Headers) GetBytes

func (h Headers) GetBytes(p any) ([]byte, error)

GetBytes returns the value of the given parameter as a slice of bytes, or a error.

func (Headers) GetInt

func (h Headers) GetInt(p any) (int, error)

GetInt returns the value of the given parameter as a int, or a error.

func (Headers) GetInt64 added in v0.6.0

func (h Headers) GetInt64(p any) (int64, error)

GetInt64 returns the value of the given parameter as a int64, or a error.

func (Headers) GetMap added in v1.3.0

func (h Headers) GetMap(p any) (key.CoseMap, error)

GetMap returns the value of the given parameter as a key.CoseMap, or a error.

func (Headers) GetString

func (h Headers) GetString(p any) (string, error)

GetString returns the value of the given parameter as a string, or a error.

func (Headers) GetUint64 added in v0.6.0

func (h Headers) GetUint64(p any) (uint64, error)

GetUint64 returns the value of the given parameter as a uint64, or a error.

func (Headers) Has added in v0.6.0

func (h Headers) Has(p any) bool

Has returns true if the Headers has the given parameter.

func (Headers) MarshalCBOR

func (h Headers) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for Headers.

func (Headers) Set added in v1.3.0

func (h Headers) Set(p, value any) error

Set sets the parameter. parameter key should be int or string.

func (*Headers) UnmarshalCBOR added in v0.6.6

func (h *Headers) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for Headers.

type KDFContext added in v0.6.1

type KDFContext struct {
	AlgorithmID  int
	PartyUInfo   PartyInfo
	PartyVInfo   PartyInfo
	SuppPubInfo  SuppPubInfo
	SuppPrivInfo []byte
}

KDFContext represents a COSE_KDF_Context object.

Reference https://datatracker.ietf.org/doc/html/rfc9053#name-context-information-structu

func (KDFContext) MarshalCBOR added in v0.6.1

func (m KDFContext) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for KDFContext.

func (*KDFContext) UnmarshalCBOR added in v0.6.1

func (m *KDFContext) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for KDFContext.

type Mac0Message

type Mac0Message[T any] struct {
	// protected header parameters: iana.HeaderParameterAlg, iana.HeaderParameterCrit.
	Protected Headers
	// Other header parameters.
	Unprotected Headers
	// If payload is []byte or cbor.RawMessage,
	// it will not be encoded/decoded by key.MarshalCBOR/key.UnmarshalCBOR.
	Payload T
	// contains filtered or unexported fields
}

Mac0Message represents a COSE_Mac0 object.

Reference https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-signer.

Example
// load key
k := key.Key{
	iana.KeyParameterKty:        iana.KeyTypeSymmetric,
	iana.KeyParameterKid:        []byte("our-secret"),
	iana.KeyParameterAlg:        iana.AlgorithmAES_MAC_256_64,
	iana.SymmetricKeyParameterK: key.Base64Bytesify("hJtXIZ2uSN5kbQfbtTNWbpdmhkV8FJG-Onbc6mxCcYg"),
}

macer, err := k.MACer()
if err != nil {
	panic(err)
}

// create a COSE_Mac0 message
obj := &cose.Mac0Message[[]byte]{
	Unprotected: cose.Headers{},
	Payload:     []byte("This is the content."),
}

// compute MAC
err = obj.Compute(macer, nil)
if err != nil {
	panic(err)
}
fmt.Printf("Tag: %x\n", obj.Tag())
// Tag: 726043745027214f

// encode COSE_Mac0 message
coseData, err := cbor.Marshal(obj)
if err != nil {
	panic(err)
}

// decode a COSE_Mac0 message
var obj3 cose.Mac0Message[[]byte]
cbor.Unmarshal(coseData, &obj3)
if err != nil {
	panic(err)
}

// verify MAC
err = obj3.Verify(macer, nil)
if err != nil {
	panic(err)
}
fmt.Printf("Payload: %s\n", string(obj3.Payload))
// Payload: This is the content.
fmt.Printf("Tag: %x\n", obj3.Tag())
// Tag: 726043745027214f

// or verify and decode a COSE_Mac0 message
obj2, err := cose.VerifyMac0Message[[]byte](macer, coseData, nil)
if err != nil {
	panic(err)
}
fmt.Printf("Payload: %s\n", string(obj2.Payload))
// Payload: This is the content.
fmt.Printf("Tag: %x\n", obj2.Tag())
// Tag: 726043745027214f
Output:

Tag: 726043745027214f
Payload: This is the content.
Tag: 726043745027214f
Payload: This is the content.
Tag: 726043745027214f

func VerifyMac0Message

func VerifyMac0Message[T any](macer key.MACer, coseData, externalData []byte) (*Mac0Message[T], error)

VerifyMac0Message verifies and decodes a COSE_Mac0 object with a MACer and returns a *Mac0Message. `externalData` should be the same as the one used when computing.

func (*Mac0Message[T]) Bytesify

func (m *Mac0Message[T]) Bytesify() []byte

Bytesify returns a CBOR-encoded byte slice. It returns nil if MarshalCBOR failed.

func (*Mac0Message[T]) Compute

func (m *Mac0Message[T]) Compute(macer key.MACer, externalData []byte) error

Compute computes a COSE_Mac0 object' MAC with a MACer. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data.

func (*Mac0Message[T]) ComputeAndEncode

func (m *Mac0Message[T]) ComputeAndEncode(macer key.MACer, externalData []byte) ([]byte, error)

ComputeAndEncode computes and encodes a COSE_Mac0 object with a MACer. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data.

func (*Mac0Message[T]) MarshalCBOR

func (m *Mac0Message[T]) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for Mac0Message. It should call `Mac0Message.WithSign` before calling this method.

func (*Mac0Message[T]) Tag

func (m *Mac0Message[T]) Tag() []byte

Tag returns the MAC tag of the Mac0Message. If the MAC is not computed, it returns nil.

func (*Mac0Message[T]) UnmarshalCBOR

func (m *Mac0Message[T]) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for Mac0Message.

func (*Mac0Message[T]) Verify

func (m *Mac0Message[T]) Verify(macer key.MACer, externalData []byte) error

Verify verifies a COSE_Mac0 object' MAC with a MACer. It should call `Mac0Message.UnmarshalCBOR` before calling this method. `externalData` should be the same as the one used when computing.

type MacMessage added in v0.5.0

type MacMessage[T any] struct {
	// protected header parameters: iana.HeaderParameterAlg, iana.HeaderParameterCrit.
	Protected Headers
	// Other header parameters.
	Unprotected Headers
	// If payload is []byte or cbor.RawMessage,
	// it will not be encoded/decoded by key.MarshalCBOR/key.UnmarshalCBOR.
	Payload T
	// contains filtered or unexported fields
}

MacMessage represents a COSE_Mac object.

Reference https://datatracker.ietf.org/doc/html/rfc9052#name-maced-message-with-recipien.

func VerifyMacMessage added in v0.5.0

func VerifyMacMessage[T any](macer key.MACer, coseData, externalData []byte) (*MacMessage[T], error)

VerifyMacMessage verifies and decodes a COSE_Mac object with a MACer and returns a *MacMessage. `externalData` should be the same as the one used when computing.

func (*MacMessage[T]) AddRecipient added in v0.5.0

func (m *MacMessage[T]) AddRecipient(recipient *Recipient) error

AddRecipient add a Recipient to the COSE_Mac object.

func (*MacMessage[T]) Bytesify added in v0.5.0

func (m *MacMessage[T]) Bytesify() []byte

Bytesify returns a CBOR-encoded byte slice. It returns nil if MarshalCBOR failed.

func (*MacMessage[T]) Compute added in v0.5.0

func (m *MacMessage[T]) Compute(macer key.MACer, externalData []byte) error

Compute computes a COSE_Mac object' MAC with a MACer. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data.

func (*MacMessage[T]) ComputeAndEncode added in v0.5.0

func (m *MacMessage[T]) ComputeAndEncode(macer key.MACer, externalData []byte) ([]byte, error)

ComputeAndEncode computes and encodes a COSE_Mac object with a MACer. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data.

func (*MacMessage[T]) MarshalCBOR added in v0.5.0

func (m *MacMessage[T]) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for MacMessage. It should call `MacMessage.WithSign` before calling this method.

func (*MacMessage[T]) Recipients added in v0.5.0

func (m *MacMessage[T]) Recipients() []*Recipient

Recipients returns recipients in the COSE_Mac message

func (*MacMessage[T]) Tag added in v0.5.0

func (m *MacMessage[T]) Tag() []byte

Tag returns the MAC tag of the MacMessage. If the MAC is not computed, it returns nil.

func (*MacMessage[T]) UnmarshalCBOR added in v0.5.0

func (m *MacMessage[T]) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for MacMessage.

func (*MacMessage[T]) Verify added in v0.5.0

func (m *MacMessage[T]) Verify(macer key.MACer, externalData []byte) error

Verify verifies a COSE_Mac object' MAC with a MACer. It should call `MacMessage.UnmarshalCBOR` before calling this method. `externalData` should be the same as the one used when computing.

type PartyInfo added in v0.6.1

type PartyInfo struct {
	Identity []byte
	Nonce    []byte
	Other    []byte
	// contains filtered or unexported fields
}

PartyInfo represents a PartyInfo object.

type Recipient added in v0.5.0

type Recipient struct {
	Protected   Headers
	Unprotected Headers
	Ciphertext  []byte
	// contains filtered or unexported fields
}

Recipient represents a COSE_recipient object.

Reference https://datatracker.ietf.org/doc/html/rfc9052#name-enveloped-cose-structure.

func (*Recipient) AddRecipient added in v0.5.0

func (m *Recipient) AddRecipient(recipient *Recipient) error

AddRecipient add a Recipient to the COSE_Recipient object.

Reference https://datatracker.ietf.org/doc/html/rfc9052#name-two-layers-of-recipient-inf.

func (*Recipient) Bytesify added in v0.6.8

func (m *Recipient) Bytesify() []byte

Bytesify returns a CBOR-encoded byte slice. It returns nil if MarshalCBOR failed.

func (*Recipient) MarshalCBOR added in v0.5.0

func (m *Recipient) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for Recipient.

func (*Recipient) Recipients added in v0.5.0

func (m *Recipient) Recipients() []*Recipient

func (*Recipient) UnmarshalCBOR added in v0.5.0

func (m *Recipient) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for Recipient.

type Sign1Message

type Sign1Message[T any] struct {
	// protected header parameters: iana.HeaderParameterAlg, iana.HeaderParameterCrit.
	Protected Headers
	// Other header parameters.
	Unprotected Headers
	// If payload is []byte or cbor.RawMessage,
	// it will not be encoded/decoded by key.MarshalCBOR/key.UnmarshalCBOR.
	Payload T
	// contains filtered or unexported fields
}

Sign1Message represents a COSE_Sign1 object.

Reference https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-signer

Example
package main

import (
	"fmt"

	"github.com/ldclabs/cose/cose"
	"github.com/ldclabs/cose/iana"
	"github.com/ldclabs/cose/key"

	_ "github.com/ldclabs/cose/key/ecdsa"
)

func main() {
	// load Key
	var k key.Key
	err := key.UnmarshalCBOR(key.HexBytesify("A60102024231312001215820BAC5B11CAD8F99F9C72B05CF4B9E26D244DC189F745228255A219A86D6A09EFF22582020138BF82DC1B6D562BE0FA54AB7804A3A64B6D72CCFED6B6FB6ED28BBFC117E23582057C92077664146E876760C9520D054AA93C3AFB04E306705DB6090308507B4D3"), &k)
	if err != nil {
		panic(err)
	}

	// k is:
	// key.Key{
	// 	iana.KeyParameterKty:    iana.KeyTypeEC2,
	// 	iana.KeyParameterKid:    []byte("11"),
	// 	iana.EC2KeyParameterCrv: iana.EllipticCurveP_256,
	// 	iana.EC2KeyParameterX:   key.Base64Bytesify("usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8"),
	// 	iana.EC2KeyParameterY:   key.Base64Bytesify("IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4"),
	// 	iana.EC2KeyParameterD:   key.Base64Bytesify("V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM"),
	// }

	// create a Sign1Message object.
	obj := &cose.Sign1Message[[]byte]{
		Protected: cose.Headers{
			iana.HeaderParameterAlg: iana.AlgorithmES256,
		},
		Unprotected: cose.Headers{
			iana.HeaderParameterKid: k.Kid(),
		},
		Payload: []byte("This is the content."),
	}

	signer, err := k.Signer()
	if err != nil {
		panic(err)
	}

	externalData := key.HexBytesify("11aa22bb33cc44dd55006699")
	// sign the message
	coseData, err := obj.SignAndEncode(signer, externalData)
	if err != nil {
		panic(err)
	}

	fmt.Printf("COSE(%d bytes): %x...\n", len(coseData), coseData[:32])
	// COSE(98 bytes): d28443a10126a10442313154546869732069732074686520636f6e74656e742e...

	verifier, err := k.Verifier()
	if err != nil {
		panic(err)
	}

	obj2, err := cose.VerifySign1Message[[]byte](verifier, coseData, externalData)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Payload: %s\n", string(obj2.Payload))
	// Payload: This is the content.

	// verify with a different external data should fail
	obj3, err := cose.VerifySign1Message[[]byte](verifier, coseData, []byte("some other external data."))
	if obj3 != nil {
		panic("should be nil")
	}
	fmt.Println(err)
	// cose/key/ecdsa: Verifier.Verify: invalid signature

}
Output:

COSE(98 bytes): d28443a10126a10442313154546869732069732074686520636f6e74656e742e...
Payload: This is the content.
cose/key/ecdsa: Verifier.Verify: invalid signature

func VerifySign1Message

func VerifySign1Message[T any](verifier key.Verifier, coseData, externalData []byte) (*Sign1Message[T], error)

VerifySign1Message verifies and decodes a COSE_Sign1 message with a Verifier and returns a *Sign1Message. `externalData` should be the same as the one used when signing.

func (*Sign1Message[T]) Bytesify

func (m *Sign1Message[T]) Bytesify() []byte

Bytesify returns a CBOR-encoded byte slice. It returns nil if MarshalCBOR failed.

func (*Sign1Message[T]) MarshalCBOR

func (m *Sign1Message[T]) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for Sign1Message. It should call `Sign1Message.WithSign` before calling this method.

func (*Sign1Message[T]) SignAndEncode

func (m *Sign1Message[T]) SignAndEncode(signer key.Signer, externalData []byte) ([]byte, error)

SignAndEncode signs and encodes a COSE_Sign1 message with a Signer. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data

func (*Sign1Message[T]) Signature

func (m *Sign1Message[T]) Signature() []byte

Signature returns the signature of the Sign1Message. If the Sign1Message is not signed, it returns nil.

func (*Sign1Message[T]) UnmarshalCBOR

func (m *Sign1Message[T]) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for Sign1Message.

func (*Sign1Message[T]) Verify

func (m *Sign1Message[T]) Verify(verifier key.Verifier, externalData []byte) error

Verify verifies a COSE_Sign1 message with a Verifier. It should call `Sign1Message.UnmarshalCBOR` before calling this method. `externalData` should be the same as the one used when signing.

func (*Sign1Message[T]) WithSign

func (m *Sign1Message[T]) WithSign(signer key.Signer, externalData []byte) error

WithSign signs a COSE_Sign1 message with a Signer. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data

type SignMessage

type SignMessage[T any] struct {
	// protected header parameters: iana.HeaderParameterCrit.
	Protected Headers
	// Other header parameters.
	Unprotected Headers
	// If payload is []byte or cbor.RawMessage,
	// it will not be encoded/decoded by key.MarshalCBOR/key.UnmarshalCBOR.
	Payload T
	// contains filtered or unexported fields
}

SignMessage represents a COSE_Sign object.

Reference https://datatracker.ietf.org/doc/html/rfc9052#name-signing-with-one-or-more-si

Example
// load KeySet
ks := key.KeySet{}
err := key.UnmarshalCBOR(key.HexBytesify("82a60102024231312001215820bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a09eff22582020138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbfc117e23582057c92077664146e876760c9520d054aa93c3afb04e306705db6090308507b4d3a6010202581e62696c626f2e62616767696e7340686f626269746f6e2e6578616d706c65200321584172992cb3ac08ecf3e5c63dedec0d51a8c1f79ef2f82f94f3c737bf5de7986671eac625fe8257bbd0394644caaa3aaf8f27a4585fbbcad0f2457620085e5c8f42ad22584201dca6947bce88bc5790485ac97427342bc35f887d86d65a089377e247e60baa55e4e8501e2ada5724ac51d6909008033ebc10ac999b9d7f5cc2519f3fe1ea1d947523584200085138ddabf5ca975f5860f91a08e91d6d5f9a76ad4018766a476680b55cd339e8ab6c72b5facdb2a2a50ac25bd086647dd3e2e6e99e84ca2c3609fdf177feb26d"), &ks)
if err != nil {
	panic(err)
}

// ks is:
// key.KeySet{
// 	key.Key{
// 		iana.KeyParameterKty:    iana.KeyTypeEC2,
// 		iana.KeyParameterKid:    []byte("11"),
// 		iana.EC2KeyParameterCrv: iana.EllipticCurveP_256,
// 		iana.EC2KeyParameterX:   key.Base64Bytesify("usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8"),
// 		iana.EC2KeyParameterY:   key.Base64Bytesify("IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4"),
// 		iana.EC2KeyParameterD:   key.Base64Bytesify("V8kgd2ZBRuh2dgyVINBUqpPDr7BOMGcF22CQMIUHtNM"),
// 	},
// 	key.Key{
// 		iana.KeyParameterKty:    iana.KeyTypeEC2,
// 		iana.KeyParameterKid:    []byte("bilbo.baggins@hobbiton.example"),
// 		iana.EC2KeyParameterCrv: iana.EllipticCurveP_521,
// 		iana.EC2KeyParameterX:   key.Base64Bytesify("cpkss6wI7PPlxj3t7A1RqMH3nvL4L5Tzxze_XeeYZnHqxiX-gle70DlGRMqqOq-PJ6RYX7vK0PJFdiAIXlyPQq0"),
// 		iana.EC2KeyParameterY:   key.Base64Bytesify("AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVySsUdaQkAgDPrwQrJmbnX9cwlGfP-HqHZR1"),
// 		iana.EC2KeyParameterD:   key.Base64Bytesify("AAhRON2r9cqXX1hg-RoI6R1tX5p2rUAYdmpHZoC1XNM56KtscrX6zbKipQrCW9CGZH3T4ubpnoTKLDYJ_fF3_rJt"),
// 	},
// }

// create a SignMessage object.
obj := &cose.SignMessage[[]byte]{
	Payload: []byte("This is the content."),
}

// get the signers from the KeySet
signers, err := ks.Signers()
if err != nil {
	panic(err)
}

// sign the message
err = obj.WithSign(signers, []byte("some external data."))
if err != nil {
	panic(err)
}

coseData, err := cbor.Marshal(obj)
if err != nil {
	panic(err)
}

fmt.Printf("COSE(%d bytes): %x...\n", len(coseData), coseData[:32])
// COSE(277 bytes): d8628440a054546869732069732074686520636f6e74656e742e828343a10126...

verifiers, err := ks.Verifiers()
if err != nil {
	panic(err)
}
obj2, err := cose.VerifySignMessage[[]byte](verifiers, coseData, []byte("some external data."))
if err != nil {
	panic(err)
}
fmt.Printf("Payload: %s\n", string(obj2.Payload))
// Payload: This is the content.

// verify with a different external data should fail
obj3, err := cose.VerifySignMessage[[]byte](verifiers, coseData, []byte("some other external data."))
if obj3 != nil {
	panic("should be nil")
}
fmt.Println(err)
// cose/key/ecdsa: Verifier.Verify: invalid signature
Output:

COSE(277 bytes): d8628440a054546869732069732074686520636f6e74656e742e828343a10126...
Payload: This is the content.
cose/key/ecdsa: Verifier.Verify: invalid signature

func VerifySignMessage

func VerifySignMessage[T any](verifiers key.Verifiers, coseData, externalData []byte) (*SignMessage[T], error)

VerifySignMessage verifies and decodes a COSE_Sign format with some Verifiers and returns a *SignMessage. `externalData` should be the same as the one used when signing.

func (*SignMessage[T]) Bytesify

func (m *SignMessage[T]) Bytesify() []byte

Bytesify returns a CBOR-encoded byte slice. It returns nil if MarshalCBOR failed.

func (*SignMessage[T]) MarshalCBOR

func (m *SignMessage[T]) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for SignMessage. It should call `SignMessage.WithSign` before calling this method.

func (*SignMessage[T]) SignAndEncode

func (m *SignMessage[T]) SignAndEncode(signers key.Signers, externalData []byte) ([]byte, error)

SignAndEncode signs and encodes a COSE_Sign message with some Signers. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data

func (*SignMessage[t]) Signatures

func (m *SignMessage[t]) Signatures() []*Signature

Signatures returns the signatures of the SignMessage. If the SignMessage is not signed, it returns nil.

func (*SignMessage[T]) UnmarshalCBOR

func (m *SignMessage[T]) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for SignMessage.

func (*SignMessage[T]) Verify

func (m *SignMessage[T]) Verify(verifiers key.Verifiers, externalData []byte) error

Verify verifies a COSE_Sign message with some Verifiers. It should call `SignMessage.UnmarshalCBOR` before calling this method. `externalData` should be the same as the one used when signing.

func (*SignMessage[T]) WithSign

func (m *SignMessage[T]) WithSign(signers key.Signers, externalData []byte) error

WithSign signs a COSE_Sign message with some Signers. `externalData` can be nil. https://datatracker.ietf.org/doc/html/rfc9052#name-externally-supplied-data

type Signature

type Signature struct {
	Protected   Headers
	Unprotected Headers
	Signature   []byte
	// contains filtered or unexported fields
}

Signature represents a COSE_Signature object.

func (*Signature) Kid

func (s *Signature) Kid() key.ByteStr

Kid returns the kid of the Signature which key signed. If the SignMessage is not signed, it returns nil.

func (*Signature) MarshalCBOR

func (s *Signature) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for Signature.

func (*Signature) UnmarshalCBOR

func (s *Signature) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for Signature.

type SuppPubInfo added in v0.6.1

type SuppPubInfo struct {
	KeyDataLength uint // bits of the desired output value
	Protected     Headers
	Other         []byte
}

SuppPubInfo represents a SuppPubInfo object.

func (SuppPubInfo) MarshalCBOR added in v0.6.1

func (m SuppPubInfo) MarshalCBOR() ([]byte, error)

MarshalCBOR implements the CBOR Marshaler interface for SuppPubInfo.

func (*SuppPubInfo) UnmarshalCBOR added in v0.6.1

func (m *SuppPubInfo) UnmarshalCBOR(data []byte) error

UnmarshalCBOR implements the CBOR Unmarshaler interface for SuppPubInfo.

Jump to

Keyboard shortcuts

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