Skip to content

Commit

Permalink
Merge branch 'main' into steve/current-release-readme
Browse files Browse the repository at this point in the history
Signed-off-by: Steve Lasker <[email protected]>
  • Loading branch information
SteveLasker authored Sep 13, 2024
2 parents f730250 + 76892d1 commit 1c33f38
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 127 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ jobs:
- name: Run tests
run: go test -race -v -coverprofile=coverage.txt .
- name: Upload coverage to codecov.io
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ vendor/
.DS_Store
/cose-fuzz.zip
/workdir/

# Editor files
.vscode/
.idea/
5 changes: 0 additions & 5 deletions .vscode/settings.json

This file was deleted.

180 changes: 90 additions & 90 deletions bench_test.go
Original file line number Diff line number Diff line change
@@ -1,90 +1,90 @@
package cose_test

import (
"io"
"testing"

"github.com/veraison/go-cose"
)

func newSign1Message() *cose.Sign1Message {
return &cose.Sign1Message{
Headers: cose.Headers{
Protected: cose.ProtectedHeader{
cose.HeaderLabelAlgorithm: cose.AlgorithmES256,
},
Unprotected: cose.UnprotectedHeader{
cose.HeaderLabelKeyID: []byte{0x01},
},
},
Payload: make([]byte, 100),
Signature: make([]byte, 32),
}
}

type noSigner struct{}

func (noSigner) Algorithm() cose.Algorithm {
return cose.AlgorithmES256
}

func (noSigner) Sign(_ io.Reader, digest []byte) ([]byte, error) {
return digest, nil
}

func (noSigner) Verify(_, _ []byte) error {
return nil
}

func BenchmarkSign1Message_MarshalCBOR(b *testing.B) {
msg := newSign1Message()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := msg.MarshalCBOR()
if err != nil {
b.Fatal(err)
}
}
}

func BenchmarkSign1Message_UnmarshalCBOR(b *testing.B) {
data, err := newSign1Message().MarshalCBOR()
if err != nil {
b.Fatal(err)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
var m cose.Sign1Message
err = m.UnmarshalCBOR(data)
if err != nil {
b.Fatal(err)
}
}
}

func BenchmarkSign1Message_Sign(b *testing.B) {
msg := newSign1Message()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
msg.Signature = nil
err := msg.Sign(zeroSource{}, nil, noSigner{})
if err != nil {
b.Fatal(err)
}
}
}

func BenchmarkSign1Message_Verify(b *testing.B) {
msg := newSign1Message()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
err := msg.Verify(nil, noSigner{})
if err != nil {
b.Fatal(err)
}
}
}
package cose_test

import (
"io"
"testing"

"github.com/veraison/go-cose"
)

func newSign1Message() *cose.Sign1Message {
return &cose.Sign1Message{
Headers: cose.Headers{
Protected: cose.ProtectedHeader{
cose.HeaderLabelAlgorithm: cose.AlgorithmES256,
},
Unprotected: cose.UnprotectedHeader{
cose.HeaderLabelKeyID: []byte{0x01},
},
},
Payload: make([]byte, 100),
Signature: make([]byte, 32),
}
}

type noSigner struct{}

func (noSigner) Algorithm() cose.Algorithm {
return cose.AlgorithmES256
}

func (noSigner) Sign(_ io.Reader, digest []byte) ([]byte, error) {
return digest, nil
}

func (noSigner) Verify(_, _ []byte) error {
return nil
}

func BenchmarkSign1Message_MarshalCBOR(b *testing.B) {
msg := newSign1Message()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := msg.MarshalCBOR()
if err != nil {
b.Fatal(err)
}
}
}

func BenchmarkSign1Message_UnmarshalCBOR(b *testing.B) {
data, err := newSign1Message().MarshalCBOR()
if err != nil {
b.Fatal(err)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
var m cose.Sign1Message
err = m.UnmarshalCBOR(data)
if err != nil {
b.Fatal(err)
}
}
}

func BenchmarkSign1Message_Sign(b *testing.B) {
msg := newSign1Message()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
msg.Signature = nil
err := msg.Sign(zeroSource{}, nil, noSigner{})
if err != nil {
b.Fatal(err)
}
}
}

func BenchmarkSign1Message_Verify(b *testing.B) {
msg := newSign1Message()
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
err := msg.Verify(nil, noSigner{})
if err != nil {
b.Fatal(err)
}
}
}
135 changes: 135 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,77 @@ func ExampleSignMessage() {
// verification error as expected
}

// This example demonstrates signing and verifying COSE_Sign signatures with
// detached payload.
//
// The COSE Sign API is EXPERIMENTAL and may be changed or removed in a later
// release.
func ExampleSignMessage_detachedPayload() {
// 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)
}
msgToSign.Payload = nil // detach payload
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)
}
msgToVerify.Payload = []byte("hello world") // reattach payload
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
}

// This example demonstrates signing and verifying COSE_Sign1 signatures.
func ExampleSign1Message() {
// create message to be signed
Expand Down Expand Up @@ -139,6 +210,70 @@ func ExampleSign1Message() {
// verification error as expected
}

// This example demonstrates signing and verifying COSE_Sign1 signatures with
// detached payload.
func ExampleSign1Message_detachedPayload() {
// 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)
}
msgToSign.Payload = nil // detach payload
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)
}
msgToVerify.Payload = []byte("hello world") // reattach payload
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
}

// This example demonstrates signing COSE_Sign1_Tagged signatures using Sign1().
func ExampleSign1() {
// create a signer
Expand Down
24 changes: 11 additions & 13 deletions release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@ This document describes the checklist to publish a release via GitHub workflow.

The maintainers may periodically update this checklist based on feedback.

NOTE: Make sure the dependencies in `go.mod` file are expected by the release.
For example, if there are dependencies on certain version of notation library (notation-go or notation-core-go) or ORAS library (oras-go), make sure that version of library is released first, and the version number is updated accordingly in `go.mod` file.
After updating go.mod file, run `go mod tidy` to ensure the go.sum file is also updated with any potential changes.
> [!NOTE]
> Make sure the dependencies in `go.mod` file are expected by the release.
> After updating `go.mod` file, run `go mod tidy` to ensure the `go.sum` file is also updated with any potential changes.
## Release Process

1. Determine a [SemVer2](https://semver.org/)-valid version prefixed with the letter `v` for release.
For example, `version="v1.0.0-alpha.1"`.
1. Bump up the `Version` in [internal/version/version.go](internal/version/version.go#L5) and open a PR for the changes.
1. Wait for the PR merge.
1. Be on the main branch connected to the actual repository (not a fork) and `git pull`.
Ensure `git log -1` shows the latest commit on the main branch.
1. Create a tag `git tag -am $version $version`
1. `git tag` and ensure the name in the list added looks correct, then push the tag directly to the repository by `git push --follow-tags`.
1. Wait for the completion of the GitHub action [release-github](https://github.com/veraison/go-cose/blob/main/.github/workflows/ci.yml).
1. Check the new draft release, revise the release description, and publish the release.
1. Determine a [SemVer2](https://semver.org/)-valid version prefixed with the letter `v` for release. For example, `v1.0.0-alpha.1`.
1. Determine the commit to be tagged and released.
1. Create an issue for voting with title similar to `vote: tag v1.0.0-alpha.1` with the proposed commit.
1. Wait for the vote pass.
1. Cut a release branch `release-X.Y` (e.g. `release-1.0`) if it does not exist. The voted commit MUST be the head of the release branch.
- To cut a release branch directly on GitHub, navigate to `https://github.com/veraison/go-cose/tree/{commit}` and then follow the [creating a branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository#creating-a-branch-using-the-branch-dropdown) doc.
1. Draft a new release from the release branch by following the [creating a release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release) doc. Set release title to the voted version and create a tag in the **Choose a tag** dropdown menu with the voted version as the tag name.
1. Proofread the draft release, and publish the release.
1. Announce the release in the community.
Loading

0 comments on commit 1c33f38

Please sign in to comment.