Skip to content
This repository was archived by the owner on Feb 4, 2026. It is now read-only.

Commit a1e5a4f

Browse files
authored
signer / crypto abstractions (#39)
enveloper verifier
1 parent 4060058 commit a1e5a4f

File tree

12 files changed

+286
-185
lines changed

12 files changed

+286
-185
lines changed

.github/workflows/golangci-lint.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
uses: golangci/golangci-lint-action@v3
2121
with:
2222
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
23-
version: v1.52
23+
version: v1.59.1
2424

2525
# Optional: working directory, useful for monorepos
2626
# working-directory: somedir
@@ -29,7 +29,7 @@ jobs:
2929
args: --exclude SA1019
3030

3131
# Optional: show only new issues if it's a pull request. The default value is `false`.
32-
# only-new-issues: true
32+
only-new-issues: true
3333

3434
# Optional: if set to true then the action will use pre-installed Go
3535
# skip-go-installation: true
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package crypto
2+
3+
type (
4+
Crypto interface {
5+
Signer
6+
Hasher
7+
Verifier
8+
9+
GenerateKey() (publicKey, privateKey []byte, err error)
10+
PublicKey(privateKey []byte) ([]byte, error)
11+
}
12+
13+
Signer interface {
14+
Sign(privateKey, hash []byte) ([]byte, error)
15+
}
16+
17+
Hasher interface {
18+
Hash([]byte) []byte
19+
}
20+
21+
Verifier interface {
22+
Verify(publicKey, hash, signature []byte) error
23+
Hasher
24+
}
25+
)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package crypto_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo"
7+
. "github.com/onsi/gomega"
8+
9+
"github.com/hyperledger-labs/cckit/extensions/envelope/crypto"
10+
)
11+
12+
const (
13+
Ed25519PublicKeyLen = 32
14+
Ed25519PrivateKeyLen = 64
15+
Ed25519SignatureLen = 64
16+
)
17+
18+
func TestCrypto(t *testing.T) {
19+
RegisterFailHandler(Fail)
20+
RunSpecs(t, "Crypto suite")
21+
}
22+
23+
var _ = Describe(`Ed25519 crypto`, func() {
24+
25+
ed25519 := crypto.NewEd25519()
26+
27+
It("Allow to create keys", func() {
28+
publicKey, privateKey, err := ed25519.GenerateKey()
29+
Expect(err).NotTo(HaveOccurred())
30+
Expect(len(publicKey)).To(Equal(Ed25519PublicKeyLen))
31+
Expect(len(privateKey)).To(Equal(Ed25519PrivateKeyLen))
32+
})
33+
34+
It("Allow to create signature", func() {
35+
_, privateKey, _ := ed25519.GenerateKey()
36+
sig, err := ed25519.Sign(privateKey, []byte(`anything`))
37+
Expect(err).NotTo(HaveOccurred())
38+
Expect(len(sig)).To(Equal(Ed25519SignatureLen))
39+
})
40+
})
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package crypto
2+
3+
import (
4+
"crypto/ed25519"
5+
"crypto/rand"
6+
"crypto/sha256"
7+
"errors"
8+
"fmt"
9+
)
10+
11+
func NewEd25519() *Ed25519 {
12+
return &Ed25519{}
13+
}
14+
15+
type Ed25519 struct{}
16+
17+
func (ed *Ed25519) GenerateKey() (publicKey, privateKey []byte, err error) {
18+
publicKey, privateKey, err = ed25519.GenerateKey(rand.Reader)
19+
if err != nil {
20+
return nil, nil, err
21+
}
22+
return publicKey, privateKey, nil
23+
}
24+
25+
func (ed *Ed25519) Sign(privateKey, hash []byte) (signature []byte, err error) {
26+
defer func() {
27+
if r := recover(); r != nil {
28+
err = fmt.Errorf("sign: %v", r)
29+
}
30+
}()
31+
return ed25519.Sign(privateKey, hash), nil
32+
}
33+
34+
func (ed *Ed25519) Hash(msg []byte) []byte {
35+
h := sha256.Sum256(msg)
36+
return h[:]
37+
}
38+
39+
func (ed *Ed25519) Verify(publicKey, hash, signature []byte) error {
40+
if !ed25519.Verify(publicKey, hash, signature) {
41+
return errors.New(`invalid signature`)
42+
}
43+
return nil
44+
}
45+
46+
func (ed *Ed25519) PublicKey(privateKey []byte) ([]byte, error) {
47+
return ed25519.PrivateKey(privateKey).Public().(ed25519.PublicKey), nil
48+
}

extensions/envelope/envelope.pb.go

Lines changed: 19 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/envelope/envelope.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ message Envelope {
1818
string channel = 7;
1919
string chaincode = 8;
2020
string method = 9;
21+
string signature_alg = 10;
2122
}

extensions/envelope/testdata/cc_envelope.go renamed to extensions/envelope/envelope_cc_test.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
1-
package testdata
1+
package envelope_test
22

33
import (
44
"github.com/hyperledger-labs/cckit/extensions/envelope"
55
"github.com/hyperledger-labs/cckit/router"
66
"github.com/hyperledger-labs/cckit/router/param"
77
"github.com/hyperledger-labs/cckit/serialize"
8+
testcc "github.com/hyperledger-labs/cckit/testing"
89
)
910

1011
type EnvelopCC struct {
1112
}
1213

13-
func NewEnvelopCC(chaincodeName string) *router.Chaincode {
14-
r := router.New(chaincodeName, router.WithSerializer(serialize.PreferJSONSerializer)).Use(envelope.Verify())
14+
const (
15+
chaincode = "envelope-chaincode"
16+
channel = "envelope-channel"
17+
methodInvoke = "invokeWithEnvelope"
18+
methodQuery = "queryWithoutEnvelope"
19+
)
20+
21+
func NewNewEnvelopCCMock(verifier envelope.Verifier) *testcc.MockStub {
22+
return testcc.NewMockStub(chaincode, NewEnvelopCC(verifier, chaincode)).WithChannel(channel)
23+
}
24+
25+
func NewEnvelopCC(verifier envelope.Verifier, chaincodeName string) *router.Chaincode {
26+
r := router.New(chaincodeName, router.WithSerializer(serialize.PreferJSONSerializer)).Use(envelope.Verify(verifier))
1527

1628
r.Invoke("invokeWithEnvelope", func(c router.Context) (interface{}, error) {
1729
return nil, nil

0 commit comments

Comments
 (0)