From fd08a5773a84d4d8463410f2a401f29dba2aeaea Mon Sep 17 00:00:00 2001 From: qmuntal Date: Mon, 16 May 2022 09:40:12 +0200 Subject: [PATCH 1/4] implement cose_sign1 oneshot Signed-off-by: qmuntal --- README.md | 19 +++++++++---------- example_test.go | 36 +++++++++++++++--------------------- fuzz_test.go | 10 +++++++--- sign1.go | 28 ++++++++-------------------- 4 files changed, 39 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 7bc087d..733d54c 100644 --- a/README.md +++ b/README.md @@ -51,16 +51,15 @@ Construct a new COSE_Sign1 message, then sign it using ECDSA w/ SHA-512 and fina privateKey, _ := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) signer, _ := cose.NewSigner(cose.AlgorithmES512, privateKey) -// create message to be signed -msgToSign := cose.NewSign1Message() -msgToSign.Payload = []byte("hello world") -msgToSign.Headers.Protected.SetAlgorithm(cose.AlgorithmES512) - -// sign message -_ = msgToSign.Sign(rand.Reader, nil, signer) - -// marshal message -data, _ := msgToSign.MarshalCBOR() +// create message header +headers := cose.Headers{ + Protected: cose.ProtectedHeader{ + cose.HeaderLabelAlgorithm: cose.AlgorithmES512, + }, +} + +// sign and marshal message +sig, _ := cose.Sign1(rand.Reader, signer, headers, []byte("hello world"), nil) ``` Verify a raw COSE_Sign1 message. For example: diff --git a/example_test.go b/example_test.go index 91efa45..1456a5a 100644 --- a/example_test.go +++ b/example_test.go @@ -153,29 +153,27 @@ func ExampleSign1() { } // sign message - protected := cose.ProtectedHeader{} - protected.SetAlgorithm(cose.AlgorithmES512) - msg, err := cose.Sign1(rand.Reader, signer, protected, []byte("hello world"), nil) - if err != nil { - panic(err) + headers := cose.Headers{ + Protected: cose.ProtectedHeader{ + cose.HeaderLabelAlgorithm: cose.AlgorithmES512, + }, + Unprotected: cose.UnprotectedHeader{ + cose.HeaderLabelKeyID: 1, + }, } - - // update unprotected headers - msg.Headers.Unprotected[cose.HeaderLabelKeyID] = 1 - - // encode message - sig, err := msg.MarshalCBOR() + sig, err := cose.Sign1(rand.Reader, signer, headers, []byte("hello world"), nil) if err != nil { panic(err) } + fmt.Println("message signed") - _ = sig // futher process on sig + _ = sig // further process on sig // Output: // message signed } // This example demonstrates verifying COSE_Sign1 signatures using Verify1(). -func ExampleVerify1() { +func ExampleSign1Message_Verify() { // get a signed message and a trusted public key sig, publicKey := getSignatureAndPublicKey() @@ -191,7 +189,7 @@ func ExampleVerify1() { if err != nil { panic(err) } - err = cose.Verify1(&msg, nil, verifier) + err = msg.Verify(nil, verifier) if err != nil { panic(err) } @@ -199,7 +197,7 @@ func ExampleVerify1() { // tamper the message and verification should fail msg.Payload = []byte("foobar") - err = cose.Verify1(&msg, nil, verifier) + err = msg.Verify(nil, verifier) if err != cose.ErrVerification { panic(err) } @@ -209,7 +207,7 @@ func ExampleVerify1() { // verification error as expected } -// getSignatureAndPublicKey is a helping function for ExampleVerify1(). +// getSignatureAndPublicKey is a helping function for ExampleSign1Message_Verify(). func getSignatureAndPublicKey() ([]byte, crypto.PublicKey) { privateKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) if err != nil { @@ -219,11 +217,7 @@ func getSignatureAndPublicKey() ([]byte, crypto.PublicKey) { if err != nil { panic(err) } - msgToSign, err := cose.Sign1(rand.Reader, signer, nil, []byte("hello world"), nil) - if err != nil { - panic(err) - } - sig, err := msgToSign.MarshalCBOR() + sig, err := cose.Sign1(rand.Reader, signer, cose.Headers{}, []byte("hello world"), nil) if err != nil { panic(err) } diff --git a/fuzz_test.go b/fuzz_test.go index 5bf9bda..e8f2b7b 100644 --- a/fuzz_test.go +++ b/fuzz_test.go @@ -129,15 +129,19 @@ func FuzzSign1(f *testing.F) { if err != nil { t.Fatal(err) } - msg, err := cose.Sign1(rand.Reader, signer, hdr, payload, external) + msg := cose.Sign1Message{ + Headers: cose.Headers{Protected: hdr}, + Payload: payload, + } + err = msg.Sign(rand.Reader, external, signer) if err != nil { t.Fatal(err) } - err = cose.Verify1(msg, external, verifier) + err = msg.Verify(external, verifier) if err != nil { t.Fatal(err) } - err = cose.Verify1(msg, append(external, []byte{0}...), verifier) + err = msg.Verify(append(external, []byte{0}...), verifier) if err == nil { t.Fatal("verification error expected") } diff --git a/sign1.go b/sign1.go index 9d8606f..1cf7338 100644 --- a/sign1.go +++ b/sign1.go @@ -227,30 +227,18 @@ func (m *Sign1Message) digestToBeSigned(alg Algorithm, external []byte) ([]byte, // This method is a wrapper of `Sign1Message.Sign()`. // // Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func Sign1(rand io.Reader, signer Signer, protected ProtectedHeader, payload, external []byte) (*Sign1Message, error) { - if protected == nil { - protected = ProtectedHeader{} - } - msg := &Sign1Message{ - Headers: Headers{ - Protected: protected, - Unprotected: UnprotectedHeader{}, - }, +func Sign1(rand io.Reader, signer Signer, header Headers, payload []byte, external []byte) ([]byte, error) { + msg := Sign1Message{ + Headers: header, Payload: payload, } err := msg.Sign(rand, external, signer) if err != nil { return nil, err } - return msg, nil -} - -// Verify1 verifies a Sign1Message returning nil on success or a suitable error -// if verification fails. -// -// This method is a wrapper of `Sign1Message.Verify()`. -// -// Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func Verify1(msg *Sign1Message, external []byte, verifier Verifier) error { - return msg.Verify(external, verifier) + sig, err := msg.MarshalCBOR() + if err != nil { + return nil, err + } + return sig, nil } From 02a1b14e5a5bf9c9025e42da8445e2488c3cfce5 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Wed, 18 May 2022 23:52:32 +0200 Subject: [PATCH 2/4] Update sign1.go Co-authored-by: Shiwei Zhang Signed-off-by: qmuntal --- sign1.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sign1.go b/sign1.go index 1cf7338..2b06e00 100644 --- a/sign1.go +++ b/sign1.go @@ -236,9 +236,5 @@ func Sign1(rand io.Reader, signer Signer, header Headers, payload []byte, extern if err != nil { return nil, err } - sig, err := msg.MarshalCBOR() - if err != nil { - return nil, err - } - return sig, nil + return msg.MarshalCBOR() } From 1f81dd4831b30c3d6f71f402a3b8e74c34d4ea7b Mon Sep 17 00:00:00 2001 From: qmuntal Date: Wed, 18 May 2022 23:54:26 +0200 Subject: [PATCH 3/4] pr feedback Signed-off-by: qmuntal --- example_test.go | 35 ----------------------------------- sign1.go | 4 ++-- 2 files changed, 2 insertions(+), 37 deletions(-) diff --git a/example_test.go b/example_test.go index 1456a5a..de8d5c5 100644 --- a/example_test.go +++ b/example_test.go @@ -172,41 +172,6 @@ func ExampleSign1() { // message signed } -// This example demonstrates verifying COSE_Sign1 signatures using Verify1(). -func ExampleSign1Message_Verify() { - // get a signed message and a trusted public key - sig, publicKey := getSignatureAndPublicKey() - - // create a verifier from a trusted public key - verifier, err := cose.NewVerifier(cose.AlgorithmES512, publicKey) - if err != nil { - panic(err) - } - - // verify message - var msg cose.Sign1Message - err = msg.UnmarshalCBOR(sig) - if err != nil { - panic(err) - } - err = msg.Verify(nil, verifier) - if err != nil { - panic(err) - } - fmt.Println("message verified") - - // tamper the message and verification should fail - msg.Payload = []byte("foobar") - err = msg.Verify(nil, verifier) - if err != cose.ErrVerification { - panic(err) - } - fmt.Println("verification error as expected") - // Output: - // message verified - // verification error as expected -} - // getSignatureAndPublicKey is a helping function for ExampleSign1Message_Verify(). func getSignatureAndPublicKey() ([]byte, crypto.PublicKey) { privateKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) diff --git a/sign1.go b/sign1.go index 2b06e00..8bac555 100644 --- a/sign1.go +++ b/sign1.go @@ -227,9 +227,9 @@ func (m *Sign1Message) digestToBeSigned(alg Algorithm, external []byte) ([]byte, // This method is a wrapper of `Sign1Message.Sign()`. // // Reference: https://datatracker.ietf.org/doc/html/rfc8152#section-4.4 -func Sign1(rand io.Reader, signer Signer, header Headers, payload []byte, external []byte) ([]byte, error) { +func Sign1(rand io.Reader, signer Signer, headers Headers, payload []byte, external []byte) ([]byte, error) { msg := Sign1Message{ - Headers: header, + Headers: headers, Payload: payload, } err := msg.Sign(rand, external, signer) From 820db4fe8bc50dd7c8ec535d343325750b4b5543 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Thu, 19 May 2022 11:24:22 +0200 Subject: [PATCH 4/4] remove unnecessary function Signed-off-by: qmuntal --- example_test.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/example_test.go b/example_test.go index de8d5c5..b007b61 100644 --- a/example_test.go +++ b/example_test.go @@ -1,7 +1,6 @@ package cose_test import ( - "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" @@ -171,20 +170,3 @@ func ExampleSign1() { // Output: // message signed } - -// getSignatureAndPublicKey is a helping function for ExampleSign1Message_Verify(). -func getSignatureAndPublicKey() ([]byte, crypto.PublicKey) { - 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) - } - sig, err := cose.Sign1(rand.Reader, signer, cose.Headers{}, []byte("hello world"), nil) - if err != nil { - panic(err) - } - return sig, privateKey.Public() -}