Skip to content

Commit f62dffc

Browse files
authored
Feature: Signature verification (#1)
* Added working signatures * Added some signature tests
1 parent caaf5db commit f62dffc

File tree

8 files changed

+366
-178
lines changed

8 files changed

+366
-178
lines changed

builder.go

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,20 @@
11
package ocmf_go
22

33
import (
4-
"crypto"
4+
"crypto/ecdsa"
55
"encoding/json"
66
"fmt"
77

88
"github.com/samber/lo"
99
)
1010

11-
type BuilderOption func(*Builder)
12-
13-
func WithSignatureAlgorithm(algorithm SignatureAlgorithm) BuilderOption {
14-
return func(b *Builder) {
15-
if isValidSignatureAlgorithm(algorithm) {
16-
b.signature.Algorithm = algorithm
17-
}
18-
}
19-
}
20-
21-
func WithSignatureEncoding(encoding SignatureEncoding) BuilderOption {
22-
return func(b *Builder) {
23-
if isValidSignatureEncoding(encoding) {
24-
b.signature.Encoding = encoding
25-
}
26-
}
27-
}
28-
2911
type Builder struct {
3012
payload PayloadSection
3113
signature Signature
32-
privateKey crypto.PrivateKey
14+
privateKey *ecdsa.PrivateKey
3315
}
3416

35-
func NewBuilder(privateKey crypto.PrivateKey, opts ...BuilderOption) *Builder {
17+
func NewBuilder(privateKey *ecdsa.PrivateKey, opts ...BuilderOption) *Builder {
3618
builder := &Builder{
3719
payload: PayloadSection{
3820
FormatVersion: OcmfVersion,
@@ -130,11 +112,10 @@ func (b *Builder) AddLossCompensation(lossCompensation LossCompensation) *Builde
130112
return b
131113
}
132114

133-
func (b *Builder) ClearPayloadSection() *Builder {
115+
func (b *Builder) ClearPayloadSection() {
134116
b.payload = PayloadSection{
135117
FormatVersion: OcmfVersion,
136118
}
137-
return b
138119
}
139120

140121
func (b *Builder) Build() (*string, error) {
@@ -145,7 +126,7 @@ func (b *Builder) Build() (*string, error) {
145126
}
146127

147128
// Sign payload with private key
148-
err = b.signature.Sign(b.privateKey)
129+
err = b.signature.Sign(b.payload, b.privateKey)
149130
if err != nil {
150131
return nil, err
151132
}

builder_opts.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package ocmf_go
2+
3+
type BuilderOption func(*Builder)
4+
5+
func WithSignatureAlgorithm(algorithm SignatureAlgorithm) BuilderOption {
6+
return func(b *Builder) {
7+
if isValidSignatureAlgorithm(algorithm) {
8+
b.signature.Algorithm = algorithm
9+
}
10+
}
11+
}
12+
13+
func WithSignatureEncoding(encoding SignatureEncoding) BuilderOption {
14+
return func(b *Builder) {
15+
if isValidSignatureEncoding(encoding) {
16+
b.signature.Encoding = encoding
17+
}
18+
}
19+
}
20+
21+
func WithSignature(signature Signature) BuilderOption {
22+
return func(b *Builder) {
23+
err := signature.Validate()
24+
if err != nil {
25+
return
26+
}
27+
28+
b.signature = signature
29+
}
30+
}

builder_opts_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package ocmf_go
2+
3+
import (
4+
"crypto/ecdsa"
5+
"crypto/elliptic"
6+
"crypto/rand"
7+
"testing"
8+
9+
"github.com/stretchr/testify/suite"
10+
)
11+
12+
type builderOptsTestSuite struct {
13+
suite.Suite
14+
}
15+
16+
func (s *builderOptsTestSuite) TestWithSignatureAlgorithm() {
17+
tests := []struct {
18+
name string
19+
algorithm SignatureAlgorithm
20+
want bool
21+
}{
22+
{
23+
name: "ECDSA-secp192k1-SHA256",
24+
algorithm: SignatureAlgorithmECDSAsecp192k1SHA256,
25+
want: true,
26+
},
27+
{
28+
name: "ECDSA-secp256k1-SHA256",
29+
algorithm: SignatureAlgorithmECDSAsecp256k1SHA256,
30+
want: true,
31+
},
32+
{
33+
name: "ECDSA-secp384r1-SHA256",
34+
algorithm: SignatureAlgorithmECDSAsecp384r1SHA256,
35+
want: true,
36+
},
37+
{
38+
name: "ECDSA-brainpool256r1-SHA256",
39+
algorithm: SignatureAlgorithmECDSAbrainpool256r11SHA256,
40+
want: true,
41+
},
42+
{
43+
name: "ECDSA-secp256r1-SHA256",
44+
algorithm: SignatureAlgorithmECDSAsecp256r1SHA256,
45+
want: true,
46+
},
47+
{
48+
name: "ECDSA-secp192r1-SHA256",
49+
algorithm: SignatureAlgorithmECDSAsecp192r1SHA256,
50+
want: true,
51+
},
52+
{
53+
name: "Unknown algorithm",
54+
algorithm: SignatureAlgorithm("ABCD"),
55+
want: false,
56+
},
57+
{
58+
name: "Empty algorithm",
59+
algorithm: SignatureAlgorithm(""),
60+
want: false,
61+
},
62+
}
63+
64+
for _, tt := range tests {
65+
s.T().Run(tt.name, func(t *testing.T) {
66+
curve := elliptic.P256()
67+
privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
68+
s.Require().NoError(err)
69+
70+
builder := NewBuilder(privateKey, WithSignatureAlgorithm(tt.algorithm))
71+
72+
if tt.name == "Unknown algorithm" || tt.name == "Empty algorithm" {
73+
s.NotEqual(tt.algorithm, builder.signature.Algorithm)
74+
} else {
75+
s.Equal(tt.algorithm, builder.signature.Algorithm)
76+
}
77+
})
78+
}
79+
}
80+
81+
func (s *builderOptsTestSuite) TestWithWithSignatureEncoding() {
82+
tests := []struct {
83+
name string
84+
encoding SignatureEncoding
85+
}{
86+
{
87+
name: "Base64 encoding",
88+
encoding: SignatureEncodingBase64,
89+
},
90+
{
91+
name: "Hex encoding",
92+
encoding: SignatureEncodingHex,
93+
},
94+
{
95+
name: "Empty encoding",
96+
encoding: SignatureEncoding(""),
97+
},
98+
{
99+
name: "Unknown encoding",
100+
encoding: SignatureEncoding("ABDD"),
101+
},
102+
}
103+
104+
for _, tt := range tests {
105+
s.T().Run(tt.name, func(t *testing.T) {
106+
builder := NewBuilder(nil, WithSignatureEncoding(tt.encoding))
107+
108+
if tt.encoding == SignatureEncodingBase64 || tt.encoding == SignatureEncodingHex {
109+
s.Equal(tt.encoding, builder.signature.Encoding)
110+
} else {
111+
s.NotEqual(tt.encoding, builder.signature.Encoding)
112+
}
113+
})
114+
}
115+
}
116+
func TestBuilderOpts(t *testing.T) {
117+
suite.Run(t, new(builderOptsTestSuite))
118+
}

builder_test.go

Lines changed: 9 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package ocmf_go
22

33
import (
4+
"crypto/ecdsa"
5+
"crypto/elliptic"
6+
"crypto/rand"
47
"testing"
58

69
"github.com/stretchr/testify/suite"
@@ -32,7 +35,10 @@ func (s *builderTestSuite) TestNewBuilder() {
3235
}
3336

3437
func (s *builderTestSuite) TestBuilder_Valid() {
35-
privateKey := "" // todo
38+
curve := elliptic.P256()
39+
privateKey, err := ecdsa.GenerateKey(curve, rand.Reader)
40+
s.Require().NoError(err)
41+
3642
builder := NewBuilder(privateKey).
3743
WithPagination("1").
3844
WithMeterSerial("exampleSerial123").
@@ -61,7 +67,7 @@ func (s *builderTestSuite) TestBuilder_Valid() {
6167
}
6268

6369
func (s *builderTestSuite) TestBuilder_MissingAttributes() {
64-
builder := NewBuilder("privateKey").
70+
builder := NewBuilder(nil).
6571
// WithPagination("1").
6672
WithMeterSerial("exampleSerial123").
6773
WithIdentificationStatus(true).
@@ -79,7 +85,7 @@ func (s *builderTestSuite) TestBuilder_MissingAttributes() {
7985
}
8086

8187
func (s *builderTestSuite) TestBuilder_CantSign() {
82-
builder := NewBuilder("privateKey").
88+
builder := NewBuilder(nil).
8389
WithPagination("1").
8490
WithMeterSerial("exampleSerial123").
8591
WithIdentificationStatus(true).
@@ -91,110 +97,11 @@ func (s *builderTestSuite) TestBuilder_CantSign() {
9197
Status: string(MeterOk),
9298
})
9399

94-
builder.privateKey = ""
95-
96100
payload, err := builder.Build()
97101
s.Error(err)
98102
s.Nil(payload)
99103
}
100104

101-
func (s *builderTestSuite) TestWithSignatureAlgorithm() {
102-
tests := []struct {
103-
name string
104-
algorithm SignatureAlgorithm
105-
want bool
106-
}{
107-
{
108-
name: "ECDSA-secp192k1-SHA256",
109-
algorithm: SignatureAlgorithmECDSAsecp192k1SHA256,
110-
want: true,
111-
},
112-
{
113-
name: "ECDSA-secp256k1-SHA256",
114-
algorithm: SignatureAlgorithmECDSAsecp256k1SHA256,
115-
want: true,
116-
},
117-
{
118-
name: "ECDSA-secp384r1-SHA256",
119-
algorithm: SignatureAlgorithmECDSAsecp384r1SHA256,
120-
want: true,
121-
},
122-
{
123-
name: "ECDSA-brainpool256r1-SHA256",
124-
algorithm: SignatureAlgorithmECDSAbrainpool256r11SHA256,
125-
want: true,
126-
},
127-
{
128-
name: "ECDSA-secp256r1-SHA256",
129-
algorithm: SignatureAlgorithmECDSAsecp256r1SHA256,
130-
want: true,
131-
},
132-
{
133-
name: "ECDSA-secp192r1-SHA256",
134-
algorithm: SignatureAlgorithmECDSAsecp192r1SHA256,
135-
want: true,
136-
},
137-
{
138-
name: "Unknown algorithm",
139-
algorithm: SignatureAlgorithm("ABCD"),
140-
want: false,
141-
},
142-
{
143-
name: "Empty algorithm",
144-
algorithm: SignatureAlgorithm(""),
145-
want: false,
146-
},
147-
}
148-
149-
for _, tt := range tests {
150-
s.T().Run(tt.name, func(t *testing.T) {
151-
builder := NewBuilder("privateKey", WithSignatureAlgorithm(tt.algorithm))
152-
153-
if tt.name == "Unknown algorithm" || tt.name == "Empty algorithm" {
154-
s.NotEqual(tt.algorithm, builder.signature.Algorithm)
155-
} else {
156-
s.Equal(tt.algorithm, builder.signature.Algorithm)
157-
}
158-
})
159-
}
160-
}
161-
162-
func (s *builderTestSuite) TestWithWithSignatureEncoding() {
163-
tests := []struct {
164-
name string
165-
encoding SignatureEncoding
166-
}{
167-
{
168-
name: "Base64 encoding",
169-
encoding: SignatureEncodingBase64,
170-
},
171-
{
172-
name: "Hex encoding",
173-
encoding: SignatureEncodingHex,
174-
},
175-
{
176-
name: "Empty encoding",
177-
encoding: SignatureEncoding(""),
178-
},
179-
{
180-
name: "Unknown encoding",
181-
encoding: SignatureEncoding("ABDD"),
182-
},
183-
}
184-
185-
for _, tt := range tests {
186-
s.T().Run(tt.name, func(t *testing.T) {
187-
builder := NewBuilder("privateKey", WithSignatureEncoding(tt.encoding))
188-
189-
if tt.encoding == SignatureEncodingBase64 || tt.encoding == SignatureEncodingHex {
190-
s.Equal(tt.encoding, builder.signature.Encoding)
191-
} else {
192-
s.NotEqual(tt.encoding, builder.signature.Encoding)
193-
}
194-
})
195-
}
196-
}
197-
198105
func TestBuilder(t *testing.T) {
199106
suite.Run(t, new(builderTestSuite))
200107
}

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.22
44

55
require (
66
github.com/go-playground/validator/v10 v10.22.1
7+
github.com/pkg/errors v0.9.1
78
github.com/samber/lo v1.47.0
89
github.com/stretchr/testify v1.9.0
910
)
@@ -13,11 +14,13 @@ require (
1314
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
1415
github.com/go-playground/locales v0.14.1 // indirect
1516
github.com/go-playground/universal-translator v0.18.1 // indirect
17+
github.com/kr/pretty v0.3.1 // indirect
1618
github.com/leodido/go-urn v1.4.0 // indirect
1719
github.com/pmezard/go-difflib v1.0.0 // indirect
1820
golang.org/x/crypto v0.23.0 // indirect
1921
golang.org/x/net v0.25.0 // indirect
20-
golang.org/x/sys v0.20.0 // indirect
22+
golang.org/x/sys v0.22.0 // indirect
2123
golang.org/x/text v0.16.0 // indirect
24+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
2225
gopkg.in/yaml.v3 v3.0.1 // indirect
2326
)

0 commit comments

Comments
 (0)