Mozilla Public License 2.0

项目介绍

veraison/go-cose 是一个托管在 GitHub 上的开源项目,主要使用 Go 编写,采用 Mozilla Public License 2.0 许可证,目前获得 68 个 Star、31 次 Fork。

仓库全名
veraison/go-cose
开源许可证
Mozilla Public License 2.0
Star 数
68
Fork 数
31
未关闭 Issue
5

README 摘要

go-cose A golang library for the [COSE specification][cose-spec] Project Status The verasion/go-cose project is actively maintained. See current releases. The project was initially forked from the upstream [mozilla-services/go-cose][mozilla-go-cose] project, however the Veraison and Mozilla maintainers have agreed to retire the mozilla-services/go-cose project and focus on [veraison/go-cose][veraison-go-cose] as the…

完整内容见 GitHub 原始 README 或本页 。

常见问题

go-cose 用什么语言开发?

主要使用 Go 编写,采用 Mozilla Public License 2.0 许可证,目前有 68 个 Star。

go-cose 可以免费商用吗?

仓库标注的许可证为 Mozilla Public License 2.0,商用前请先阅读仓库 LICENSE 文件确认授权范围。

如何获取 go-cose 的源码?

可以直接克隆仓库:git clone https://github.com/veraison/go-cose.git,默认分支为 main;安装与运行步骤见仓库 README。

go-cose 最近还在维护吗?

仓库最近一次更新为 10月3日,当前有 5 个未关闭 Issue;Star 数为 68,可作为社区活跃度的参考。

关于

GitHub 原始描述(英文)

go library for CBOR Object Signing and Encryption (COSE)

描述取自 GitHub 官方 API,保持仓库作者书写的原文。

简要分析

热度分
138
价值分
50
活跃状态
活跃

README

go-cose

go.dev tests codecov

A golang library for the COSE specification

Project Status

The verasion/go-cose project is actively maintained. See current releases.

The project was initially forked from the upstream mozilla-services/go-cose project, however the Veraison and Mozilla maintainers have agreed to retire the mozilla-services/go-cose project and focus on veraison/go-cose as the active project.

We thank the Mozilla maintainers and contributors for their great work that formed the base of the veraison/go-cose project.

Community

The veraison/go-cose project is an open source community effort.

You can reach the go-cose community via::

Participation in the go-cose community is governed by the Veraison CODE_OF_CONDUCT.md and GOVERNANCE.md

Code of Conduct

This project has adopted the Contributor Covenant Code of Conduct.

Installation

go-cose is compatible with modern Go releases in module mode, with Go installed:

go get github.com/veraison/go-cose

will resolve and add the package to the current development module, along with its dependencies.

Alternatively the same can be achieved if you use import in a package:

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

and run go get without parameters.

Finally, to use the top-of-trunk version of this repo, use the following command:

go get github.com/veraison/go-cose@main

Usage

Signing and Verification

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

Construct a new COSE_Sign1_Tagged message, then sign it using ECDSA w/ SHA-256 and finally marshal it. For example:

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)
}

Verify a raw COSE_Sign1_Tagged message. For example:

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)
}

See example_test.go for more examples.

Verify with a protected X.509 certificate chain

Use SetX5Chain to add an ordered certificate chain to the protected header. VerifyWithX5Chain does not support an unprotected-only x5chain. Omitted issuers may be supplied through AdditionalIntermediates, which never become trust anchors.

var msg cose.Sign1Message
if err := msg.UnmarshalCBOR(encoded); err != nil {
    return err
}

anchors, err := cose.LoadTrustAnchors(
    os.ReadFile,
    []string{"root.pem"},
    []string{"intermediate.crl.pem", "root.crl.pem"},
)
if err != nil {
    return err
}

verifiedChain, err := msg.VerifyWithX5Chain(nil, anchors, nil)
if err != nil {
    return err
}
// Apply application-specific Subject, SAN, or EKU authorization here.
_ = verifiedChain
return nil

System roots require explicit opt-in. Full-chain CRL checking is enabled by default, so provide an applicable CRL for every non-root certificate issuer. Set anchors.RevocationMode to cose.RevocationDisabled to skip CRL checks, or use RevocationLeafOnly to check only the signing certificate. Certificate identity authorization remains the caller’s responsibility. See the TrustAnchors and X5ChainVerifyOptions GoDoc for configuration details.

Trust sources can be combined: enable UseSystemRoots for the OS defaults, add custom trust anchors in TrustAnchors.Anchors, and verify once against the combined store. If the OS trust store cannot be loaded, verification can still succeed when the explicitly configured anchors establish a valid path.

CRL selection honors CurrentTime and does not fall back from an expired newer CRL to an older CRL. Permissive CRL policy tolerates missing CRLs, but a path with missing CRLs cannot bypass an explicit revocation on another path. A path with complete CRL coverage is preferred when available.

See ExampleSign1Message_VerifyWithX5Chain for a runnable end-to-end example, including CBOR decoding and a simple signer identity check. See ExampleSign1Message_VerifyWithX5Chain_fromFiles for loading the root via LoadTrustAnchors and an omitted intermediate from files on disk.

Untagged Signing and Verification

Untagged COSE_Sign1 messages can be signed and verified as above, using cose.UntaggedSign1Message instead of cose.Sign1Message.

Signing and Verification of payload digest

When cose.NewSigner is used with PS{256,384,512} or ES{256,384,512}, the returned signer can be casted to the cose.DigestSigner interface, whose SignDigest method signs an already digested message.

When cose.NewVerifier is used with PS{256,384,512} or ES{256,384,512}, the returned verifier can be casted to the cose.DigestVerifier interface, whose VerifyDigest method verifies an already digested message.

Please refer to example_test.go for the API usage.

About hashing

go-cose does not import any hash package by its own to avoid linking unnecessary algorithms to the final binary. It is the the responsibility of the go-cose user to make the necessary hash functions available at runtime, i.e., by using a blank import:

import (
    _ "crypto/sha256"
    _ "crypto/sha512"
)

These are the required packages for each built-in cose.Algorithm:

  • cose.AlgorithmPS256, cose.AlgorithmES256: crypto/sha256
  • cose.AlgorithmPS384, cose.AlgorithmPS512, cose.AlgorithmES384, cose.AlgorithmES512: crypto/sha512
  • cose.AlgorithmEdDSA: none

Countersigning

It is possible to countersign cose.Sign1Message, cose.SignMessage, cose.Signature and cose.Countersignature objects and add them as unprotected headers. In order to do so, first create a countersignature holder with cose.NewCountersignature() and call its Sign function passing the parent object which is going to be countersigned. Then assign the countersignature as an unprotected header cose.HeaderLabelCounterSignatureV2 or, if preferred, maintain it as a detached countersignature.

When verifying countersignatures, it is necessary to pass the parent object in the Verify function of the countersignature holder.

See example_test.go for examples.

Features

Signing and Verifying Objects

go-cose supports two different signature structures:

:warning: The COSE_Sign API is currently EXPERIMENTAL and may be changed or removed in a later release. In addition, the amount of functional and security testing it has received so far is significantly lower than the COSE_Sign1 API.

Countersignatures

go-cose supports COSE_Countersignature, check cose.Countersignature.

:warning: The COSE_Countersignature API is currently EXPERIMENTAL and may be changed or removed in a later release.

Built-in Algorithms

go-cose has built-in supports the following algorithms:

  • PS{256,384,512}: RSASSA-PSS w/ SHA as defined in RFC 8230.
  • ES{256,384,512}: ECDSA w/ SHA as defined in RFC 8152.
  • Ed25519: PureEdDSA as defined in RFC 8152.

Custom Algorithms

It is possible to use custom algorithms with this library, for example:

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'
		// ])
	}
}

Integer Ranges

CBOR supports integers in the range [-264, -1] ∪ [0, 264 - 1].

This does not map onto a single Go integer type.

go-cose uses int64 to encompass both positive and negative values to keep data sizes smaller and easy to use.

The main effect is that integer label values in the [-264, -263 - 1] and the [263, 264 - 1] ranges, which are nominally valid per RFC 8152, are rejected by the go-cose library.

Conformance Tests

go-cose runs the GlueCOSE test suite on every local go test execution. These are also executed on every CI job.

Fuzz Tests

go-cose implements several fuzz tests using Go’s native fuzzing.

Fuzzing requires Go 1.18 or higher, and can be executed as follows:

go test -fuzz=FuzzSign1

Security Reviews

go-cose undergoes periodic security review. The security review reports are located here

评论

暂无评论