veraison/go-cose

GitHub: veraison/go-cose

该项目是一个用 Go 语言实现的 COSE 规范库,用于在 CBOR 格式下进行消息签名与验证。

Stars: 63 | Forks: 31

# go-cose [![go.dev](https://pkg.go.dev/badge/github.com/veraison/go-cose.svg)](https://pkg.go.dev/github.com/veraison/go-cose) [![tests](https://static.pigsec.cn/wp-content/uploads/repos/cas/99/993938d8ce5e902ccfb9d6747725c320d855dea3235ed9a304cedf0d94c9321f.svg)](https://github.com/veraison/go-cose/actions?query=workflow%3Aci) [![codecov](https://codecov.io/gh/veraison/go-cose/branch/main/graph/badge.svg?token=SL18TCTC03)](https://codecov.io/gh/veraison/go-cose) 一个用于 [COSE 规范][cose-spec] 的 golang 库 ## 项目状态 verasion/go-cose 项目正在积极维护中。 参见[当前发布版本](https://github.com/veraison/go-cose/releases)。 该项目*最初*是从上游的 [mozilla-services/go-cose][mozilla-go-cose] 项目 fork 而来的,但是 Veraison 和 Mozilla 的维护者已经同意废弃 mozilla-services/go-cose 项目,并将重点放在 [veraison/go-cose][veraison-go-cose] 上作为活跃项目。 ## 行为准则 本项目采用了[贡献者公约行为准则](https://github.com/veraison/.github/blob/main/CODE_OF_CONDUCT.md)。 ## 安装 go-cose 兼容模块模式下的现代 Go 版本,在已安装 Go 的情况下: ``` go get github.com/veraison/go-cose ``` 将解析并把该包及其依赖项添加到当前的开发模块中。 或者,如果你在一个包中使用 import,也可以实现同样的效果: ``` import "github.com/veraison/go-cose" ``` 然后运行不带参数的 `go get`。 最后,要使用此仓库的最新主干版本,请使用以下命令: ``` go get github.com/veraison/go-cose@main ``` ## 用法 ### 签名与验证 ``` import "github.com/veraison/go-cose" ``` 构造一个新的 COSE_Sign1_Tagged 消息,然后使用 ECDSA w/ SHA-256 对其进行签名,最后将其 marshal。例如: ``` package main import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" _ "crypto/sha256" "github.com/veraison/go-cose" ) func SignP256(data []byte) ([]byte, error) { // create a signer privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return nil, err } signer, err := cose.NewSigner(cose.AlgorithmES256, privateKey) if err != nil { return nil, err } // create message header headers := cose.Headers{ Protected: cose.ProtectedHeader{ cose.HeaderLabelAlgorithm: cose.AlgorithmES256, }, } // sign and marshal message return cose.Sign1(rand.Reader, signer, headers, data, nil) } ``` 验证原始的 COSE_Sign1_Tagged 消息。例如: ``` package main import ( "crypto" _ "crypto/sha256" "github.com/veraison/go-cose" ) func VerifyP256(publicKey crypto.PublicKey, sig []byte) error { // create a verifier from a trusted private key verifier, err := cose.NewVerifier(cose.AlgorithmES256, publicKey) if err != nil { return err } // create a sign message from a raw COSE_Sign1 payload var msg cose.Sign1Message if err = msg.UnmarshalCBOR(sig); err != nil { return err } return msg.Verify(nil, verifier) } ``` 有关更多示例,请参见 [example_test.go](./example_test.go)。 #### 无标签的签名与验证 如上所述,可以使用 `cose.UntaggedSign1Message` 而不是 `cose.Sign1Message` 来对无标签的 COSE_Sign1 消息进行签名和验证。 #### 对 payload digest 进行签名和验证 当 `cose.NewSigner` 与 PS{256,384,512} 或 ES{256,384,512} 一起使用时,返回的 signer 可以被转换为 `cose.DigestSigner` 接口,其 `SignDigest` 方法用于对已经过 digest 处理的消息进行签名。 当 `cose.NewVerifier` 与 PS{256,384,512} 或 ES{256,384,512} 一起使用时,返回的 verifier 可以被转换为 `cose.DigestVerifier` 接口,其 `VerifyDigest` 方法用于验证已经过 digest 处理的消息。 有关 API 的用法,请参阅 [example_test.go](./example_test.go)。 ### 关于 hashing `go-cose` 本身不导入任何 hash package,以避免将不必要的算法链接到最终的二进制文件中。 `go-cose` 用户有责任在 runtime 提供必要的 hash 函数,即通过使用 blank import: ``` import ( _ "crypto/sha256" _ "crypto/sha512" ) ``` 以下是每个内置 cose.Algorithm 所需的 package: - cose.AlgorithmPS256, cose.AlgorithmES256:`crypto/sha256` - cose.AlgorithmPS384, cose.AlgorithmPS512, cose.AlgorithmES384, cose.AlgorithmES512:`crypto/sha512` - cose.AlgorithmEdDSA:无 ### Countersigning 可以对 `cose.Sign1Message`、`cose.SignMessage`、`cose.Signature` 和 `cose.Countersignature` 对象进行 countersign,并将它们添加为不受保护的 header。为此,首先使用 `cose.NewCountersignature()` 创建一个 countersignature 持有者,并调用其 `Sign` 函数,传入要进行 countersign 的父对象。然后,将该 countersignature 分配为不受保护的 header `cose.HeaderLabelCounterSignatureV2`,或者如果愿意,将其保留为分离的 countersignature。 在验证 countersignature 时,必须在 countersignature 持有者的 `Verify` 函数中传入父对象。 有关示例,请参见 [example_test.go](./example_test.go)。 ## 功能 ### 对象的签名与验证 go-cose 支持两种不同的签名结构: - [cose.Sign1Message](https://pkg.go.dev/github.com/veraison/go-cose#Sign1Message) 实现了 [COSE_Sign1](https://datatracker.ietf.org/doc/html/rfc8152#section-4.2)。 - [cose.SignMessage](https://pkg.go.dev/github.com/veraison/go-cose#SignMessage) 实现了 [COSE_Sign](https://datatracker.ietf.org/doc/html/rfc8152#section-4.1)。 ### Countersignatures go-cose 支持 [COSE_Countersignature](https://tools.ietf.org/html/rfc9338#section-3.1),请查看 [cose.Countersignature](https://pkg.go.dev/github.com/veraison/go-cose#Countersignature)。 ### 内置算法 go-cose 内置支持以下算法: - PS{256,384,512}:RFC 8230 中定义的 RSASSA-PSS w/ SHA。 - ES{256,384,512}:RFC 8152 中定义的 ECDSA w/ SHA。 - Ed25519:RFC 8152 中定义的 PureEdDSA。 ### 自定义算法 可以在此库中使用自定义算法,例如: ``` package cose_test import ( "errors" "io" "testing" "github.com/cloudflare/circl/sign" "github.com/cloudflare/circl/sign/schemes" "github.com/veraison/go-cose" ) type customKeySigner struct { alg cose.Algorithm key sign.PrivateKey } func (ks *customKeySigner) Algorithm() cose.Algorithm { return ks.alg } func (ks *customKeySigner) Sign(rand io.Reader, content []byte) ([]byte, error) { suite := schemes.ByName("ML-DSA-44") return suite.Sign(ks.key, content, nil), nil } type customKeyVerifier struct { alg cose.Algorithm key sign.PublicKey } func (ks *customKeyVerifier) Algorithm() cose.Algorithm { return ks.alg } func (ks *customKeyVerifier) Verify(content []byte, signature []byte) error { suite := schemes.ByName("ML-DSA-44") valid := suite.Verify(ks.key, content, signature, nil) if !valid { return errors.New("Signature not from public key") } return nil } func TestCustomSigner(t *testing.T) { const ( COSE_ALG_ML_DSA_44 = -48 ) suite := schemes.ByName("ML-DSA-44") var seed [32]byte // zero seed pub, priv := suite.DeriveKey(seed[:]) var ks cose.Signer = &customKeySigner{ alg: COSE_ALG_ML_DSA_44, key: priv, } var kv = customKeyVerifier{ alg: COSE_ALG_ML_DSA_44, key: pub, } headers := cose.Headers{ Protected: cose.ProtectedHeader{ cose.HeaderLabelAlgorithm: COSE_ALG_ML_DSA_44, cose.HeaderLabelKeyID: []byte("key-42"), }, } var payload = []byte("hello post quantum signatures") signature, _ := cose.Sign1(nil, ks, headers, payload, nil) var sign1 cose.Sign1Message _ = sign1.UnmarshalCBOR(signature) var verifier cose.Verifier = &kv verifyError := sign1.Verify(nil, verifier) if verifyError != nil { t.Fatalf("Verification failed") } else { // fmt.Println(cbor.Diagnose(signature)) // 18([ // <<{ // / alg / 1: -48, // / kid / 4: h'6B65792D3432'} // >>, // {}, // h'4974...722e', // h'cb5a...293b' // ]) } } ``` ### 整数范围 CBOR 支持 [-264, -1] ∪ [0, 264 - 1] 范围内的整数。 这不能映射到单一的 Go 整数类型上。 `go-cose` 使用 `int64` 来同时包含正值和负值,以保持较小的数据大小并易于使用。 主要影响在于,根据 RFC 8152 原本有效的整数标签值(即在 [-264, -263 - 1] 和 [263, 264 - 1] 范围内的值)会被 go-cose 库拒绝。 ### 一致性测试 `go-cose` 会在每次本地执行 `go test` 时运行 [GlueCOSE](https://github.com/gluecose/test-vectors) 测试套件。 这些测试也会在每个 CI 作业中执行。 ### 模糊测试 `go-cose` 使用 [Go 原生模糊测试](https://go.dev/doc/fuzz)实现了多个模糊测试。 模糊测试需要 Go 1.18 或更高版本,可以按如下方式执行: ``` go test -fuzz=FuzzSign1 ``` ### 安全审查 `go-cose` 会进行定期的安全审查。安全审查报告位于[此处](./reports)。
标签:EVTX分析, 日志审计