Skip to content

Commit 83ae237

Browse files
authored
Merge pull request #42 from adityasaky/code-cleanup
Reorganize DSSE library
2 parents 6476f36 + 7a2c08e commit 83ae237

File tree

7 files changed

+474
-468
lines changed

7 files changed

+474
-468
lines changed

cjson/canonicaljson_test.go

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,29 @@ import (
55
"fmt"
66
"strings"
77
"testing"
8+
9+
"github.com/stretchr/testify/assert"
810
)
911

10-
type KeyVal struct {
12+
type keyVal struct {
1113
Private string `json:"private"`
1214
Public string `json:"public"`
1315
Certificate string `json:"certificate,omitempty"`
1416
}
1517

16-
type Key struct {
18+
type key struct {
1719
KeyID string `json:"keyid"`
1820
KeyIDHashAlgorithms []string `json:"keyid_hash_algorithms"`
1921
KeyType string `json:"keytype"`
20-
KeyVal KeyVal `json:"keyval"`
22+
KeyVal keyVal `json:"keyval"`
2123
Scheme string `json:"scheme"`
2224
}
2325

2426
func TestEncodeCanonical(t *testing.T) {
2527
objects := []interface{}{
26-
Key{},
27-
Key{
28-
KeyVal: KeyVal{
28+
key{},
29+
key{
30+
KeyVal: keyVal{
2931
Private: "priv",
3032
Public: "pub",
3133
},
@@ -42,8 +44,8 @@ func TestEncodeCanonical(t *testing.T) {
4244
"int2": float64(42),
4345
"string": `\"`,
4446
},
45-
Key{
46-
KeyVal: KeyVal{
47+
key{
48+
KeyVal: keyVal{
4749
Certificate: "cert",
4850
Private: "priv",
4951
Public: "pub",
@@ -91,21 +93,22 @@ func TestEncodeCanonicalErr(t *testing.T) {
9193
}
9294
}
9395

94-
func TestencodeCanonical(t *testing.T) {
95-
expectedError := "Can't canonicalize"
96+
func TestEncodeCanonicalHelper(t *testing.T) {
97+
defer func() {
98+
if r := recover(); r == nil {
99+
t.Error("encodeCanonical did not panic as expected")
100+
}
101+
}()
96102

97103
objects := []interface{}{
98-
TestencodeCanonical,
99-
[]interface{}{TestencodeCanonical},
104+
TestEncodeCanonicalHelper,
105+
[]interface{}{TestEncodeCanonicalHelper},
100106
}
101107

102108
for i := 0; i < len(objects); i++ {
103109
var result strings.Builder
104110
err := encodeCanonical(objects[i], &result)
105-
if err == nil || !strings.Contains(err.Error(), expectedError) {
106-
t.Errorf("EncodeCanonical returned '%s', expected '%s' error",
107-
err, expectedError)
108-
}
111+
assert.Nil(t, err)
109112
}
110113
}
111114

dsse/envelope.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package dsse
2+
3+
import (
4+
"encoding/base64"
5+
"fmt"
6+
)
7+
8+
/*
9+
Envelope captures an envelope as described by the DSSE specification. See here:
10+
https://github.com/secure-systems-lab/dsse/blob/master/envelope.md
11+
*/
12+
type Envelope struct {
13+
PayloadType string `json:"payloadType"`
14+
Payload string `json:"payload"`
15+
Signatures []Signature `json:"signatures"`
16+
}
17+
18+
/*
19+
DecodeB64Payload returns the serialized body, decoded from the envelope's
20+
payload field. A flexible decoder is used, first trying standard base64, then
21+
URL-encoded base64.
22+
*/
23+
func (e *Envelope) DecodeB64Payload() ([]byte, error) {
24+
return b64Decode(e.Payload)
25+
}
26+
27+
/*
28+
Signature represents a generic in-toto signature that contains the identifier
29+
of the key which was used to create the signature.
30+
The used signature scheme has to be agreed upon by the signer and verifer
31+
out of band.
32+
The signature is a base64 encoding of the raw bytes from the signature
33+
algorithm.
34+
*/
35+
type Signature struct {
36+
KeyID string `json:"keyid"`
37+
Sig string `json:"sig"`
38+
}
39+
40+
/*
41+
PAE implementes the DSSE Pre-Authentic Encoding
42+
https://github.com/secure-systems-lab/dsse/blob/master/protocol.md#signature-definition
43+
*/
44+
func PAE(payloadType string, payload []byte) []byte {
45+
return []byte(fmt.Sprintf("DSSEv1 %d %s %d %s",
46+
len(payloadType), payloadType,
47+
len(payload), payload))
48+
}
49+
50+
/*
51+
Both standard and url encoding are allowed:
52+
https://github.com/secure-systems-lab/dsse/blob/master/envelope.md
53+
*/
54+
func b64Decode(s string) ([]byte, error) {
55+
b, err := base64.StdEncoding.DecodeString(s)
56+
if err != nil {
57+
b, err = base64.URLEncoding.DecodeString(s)
58+
if err != nil {
59+
return nil, fmt.Errorf("unable to base64 decode payload (is payload in the right format?)")
60+
}
61+
}
62+
63+
return b, nil
64+
}

dsse/sign.go

Lines changed: 9 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -8,109 +8,32 @@ import (
88
"context"
99
"encoding/base64"
1010
"errors"
11-
"fmt"
1211
)
1312

14-
// ErrUnknownKey indicates that the implementation does not recognize the
15-
// key.
16-
var ErrUnknownKey = errors.New("unknown key")
17-
18-
// ErrNoSignature indicates that an envelope did not contain any signatures.
19-
var ErrNoSignature = errors.New("no signature found")
20-
2113
// ErrNoSigners indicates that no signer was provided.
2214
var ErrNoSigners = errors.New("no signers provided")
2315

24-
/*
25-
Envelope captures an envelope as described by the Secure Systems Lab
26-
Signing Specification. See here:
27-
https://github.com/secure-systems-lab/signing-spec/blob/master/envelope.md
28-
*/
29-
type Envelope struct {
30-
PayloadType string `json:"payloadType"`
31-
Payload string `json:"payload"`
32-
Signatures []Signature `json:"signatures"`
33-
}
34-
35-
/*
36-
DecodeB64Payload returns the serialized body, decoded
37-
from the envelope's payload field. A flexible
38-
decoder is used, first trying standard base64, then
39-
URL-encoded base64.
40-
*/
41-
func (e *Envelope) DecodeB64Payload() ([]byte, error) {
42-
return b64Decode(e.Payload)
43-
}
44-
45-
/*
46-
Signature represents a generic in-toto signature that contains the identifier
47-
of the key which was used to create the signature.
48-
The used signature scheme has to be agreed upon by the signer and verifer
49-
out of band.
50-
The signature is a base64 encoding of the raw bytes from the signature
51-
algorithm.
52-
*/
53-
type Signature struct {
54-
KeyID string `json:"keyid"`
55-
Sig string `json:"sig"`
56-
}
57-
58-
/*
59-
PAE implementes the DSSE Pre-Authentic Encoding
60-
https://github.com/secure-systems-lab/dsse/blob/master/protocol.md#signature-definition
61-
*/
62-
func PAE(payloadType string, payload []byte) []byte {
63-
return []byte(fmt.Sprintf("DSSEv1 %d %s %d %s",
64-
len(payloadType), payloadType,
65-
len(payload), payload))
66-
}
67-
68-
/*
69-
Signer defines the interface for an abstract signing algorithm.
70-
The Signer interface is used to inject signature algorithm implementations
71-
into the EnevelopeSigner. This decoupling allows for any signing algorithm
72-
and key management system can be used.
73-
The full message is provided as the parameter. If the signature algorithm
74-
depends on hashing of the message prior to signature calculation, the
75-
implementor of this interface must perform such hashing.
76-
The function must return raw bytes representing the calculated signature
77-
using the current algorithm, and the key used (if applicable).
78-
For an example see EcdsaSigner in sign_test.go.
79-
*/
80-
type Signer interface {
81-
Sign(ctx context.Context, data []byte) ([]byte, error)
82-
KeyID() (string, error)
83-
}
84-
85-
// SignVerifer provides both the signing and verification interface.
86-
type SignVerifier interface {
87-
Signer
88-
Verifier
89-
}
90-
9116
// EnvelopeSigner creates signed Envelopes.
9217
type EnvelopeSigner struct {
93-
providers []SignVerifier
94-
ev *EnvelopeVerifier
18+
providers []SignerVerifier
9519
}
9620

9721
/*
98-
NewEnvelopeSigner creates an EnvelopeSigner that uses 1+ Signer
99-
algorithms to sign the data.
100-
Creates a verifier with threshold=1, at least one of the providers must validate signitures successfully.
22+
NewEnvelopeSigner creates an EnvelopeSigner that uses 1+ Signer algorithms to
23+
sign the data. Creates a verifier with threshold=1, at least one of the
24+
providers must validate signatures successfully.
10125
*/
102-
func NewEnvelopeSigner(p ...SignVerifier) (*EnvelopeSigner, error) {
26+
func NewEnvelopeSigner(p ...SignerVerifier) (*EnvelopeSigner, error) {
10327
return NewMultiEnvelopeSigner(1, p...)
10428
}
10529

10630
/*
10731
NewMultiEnvelopeSigner creates an EnvelopeSigner that uses 1+ Signer
108-
algorithms to sign the data.
109-
Creates a verifier with threshold.
110-
threashold indicates the amount of providers that must validate the envelope.
32+
algorithms to sign the data. Creates a verifier with threshold. Threshold
33+
indicates the amount of providers that must validate the envelope.
11134
*/
112-
func NewMultiEnvelopeSigner(threshold int, p ...SignVerifier) (*EnvelopeSigner, error) {
113-
var providers []SignVerifier
35+
func NewMultiEnvelopeSigner(threshold int, p ...SignerVerifier) (*EnvelopeSigner, error) {
36+
var providers []SignerVerifier
11437

11538
for _, sv := range p {
11639
if sv != nil {
@@ -122,19 +45,8 @@ func NewMultiEnvelopeSigner(threshold int, p ...SignVerifier) (*EnvelopeSigner,
12245
return nil, ErrNoSigners
12346
}
12447

125-
evps := []Verifier{}
126-
for _, p := range providers {
127-
evps = append(evps, p.(Verifier))
128-
}
129-
130-
ev, err := NewMultiEnvelopeVerifier(threshold, evps...)
131-
if err != nil {
132-
return nil, err
133-
}
134-
13548
return &EnvelopeSigner{
13649
providers: providers,
137-
ev: ev,
13850
}, nil
13951
}
14052

@@ -170,29 +82,3 @@ func (es *EnvelopeSigner) SignPayload(ctx context.Context, payloadType string, b
17082

17183
return &e, nil
17284
}
173-
174-
/*
175-
Verify decodes the payload and verifies the signature.
176-
Any domain specific validation such as parsing the decoded body and
177-
validating the payload type is left out to the caller.
178-
Verify returns a list of accepted keys each including a keyid, public and signiture of the accepted provider keys.
179-
*/
180-
func (es *EnvelopeSigner) Verify(ctx context.Context, e *Envelope) ([]AcceptedKey, error) {
181-
return es.ev.Verify(ctx, e)
182-
}
183-
184-
/*
185-
Both standard and url encoding are allowed:
186-
https://github.com/secure-systems-lab/dsse/blob/master/envelope.md
187-
*/
188-
func b64Decode(s string) ([]byte, error) {
189-
b, err := base64.StdEncoding.DecodeString(s)
190-
if err != nil {
191-
b, err = base64.URLEncoding.DecodeString(s)
192-
if err != nil {
193-
return nil, err
194-
}
195-
}
196-
197-
return b, nil
198-
}

0 commit comments

Comments
 (0)