1 package signerverifier
2
3 import (
4 "context"
5 "crypto/ed25519"
6 "encoding/json"
7 "os"
8 "path/filepath"
9 "testing"
10
11 "github.com/secure-systems-lab/go-securesystemslib/cjson"
12 "github.com/secure-systems-lab/go-securesystemslib/dsse"
13 "github.com/stretchr/testify/assert"
14 )
15
16 func TestNewED25519SignerVerifierFromSSLibKey(t *testing.T) {
17 key, err := LoadED25519KeyFromFile(filepath.Join("test-data", "ed25519-test-key.pub"))
18 if err != nil {
19 t.Error(err)
20 }
21
22 sv, err := NewED25519SignerVerifierFromSSLibKey(key)
23 if err != nil {
24 t.Error(err)
25 }
26
27 expectedPublicString := "3f586ce67329419fb0081bd995914e866a7205da463d593b3b490eab2b27fd3f"
28 expectedPublicKey := ed25519.PublicKey(hexDecode(t, expectedPublicString))
29
30 assert.Equal(t, "52e3b8e73279d6ebdd62a5016e2725ff284f569665eb92ccb145d83817a02997", sv.keyID)
31 assert.Equal(t, expectedPublicKey, sv.public)
32 assert.Nil(t, sv.private)
33 }
34
35 func TestLoadED25519KeyFromFile(t *testing.T) {
36 t.Run("ED25519 public key", func(t *testing.T) {
37 key, err := LoadED25519KeyFromFile(filepath.Join("test-data", "ed25519-test-key.pub"))
38 assert.Nil(t, err)
39
40 assert.Equal(t, "52e3b8e73279d6ebdd62a5016e2725ff284f569665eb92ccb145d83817a02997", key.KeyID)
41 assert.Equal(t, "3f586ce67329419fb0081bd995914e866a7205da463d593b3b490eab2b27fd3f", key.KeyVal.Public)
42 assert.Equal(t, "ed25519", key.Scheme)
43 assert.Equal(t, ED25519KeyType, key.KeyType)
44 })
45
46 t.Run("ED25519 private key", func(t *testing.T) {
47 key, err := LoadED25519KeyFromFile(filepath.Join("test-data", "ed25519-test-key"))
48 assert.Nil(t, err)
49
50 assert.Equal(t, "52e3b8e73279d6ebdd62a5016e2725ff284f569665eb92ccb145d83817a02997", key.KeyID)
51 assert.Equal(t, "3f586ce67329419fb0081bd995914e866a7205da463d593b3b490eab2b27fd3f", key.KeyVal.Public)
52 assert.Equal(t, "66f6ebad4aeb949b91c84c9cfd6ee351fc4fd544744bab6e30fb400ba13c6e9a", key.KeyVal.Private)
53 assert.Equal(t, "ed25519", key.Scheme)
54 assert.Equal(t, ED25519KeyType, key.KeyType)
55 })
56
57 t.Run("invalid path", func(t *testing.T) {
58 _, err := LoadED25519KeyFromFile(filepath.Join("test-data", "invalid"))
59 assert.ErrorContains(t, err, "unable to load ED25519 key from file")
60 })
61 }
62
63 func TestED25519SignerVerifierSign(t *testing.T) {
64 key, err := LoadED25519KeyFromFile(filepath.Join("test-data", "ed25519-test-key"))
65 if err != nil {
66 t.Fatal(err)
67 }
68
69 sv, err := NewED25519SignerVerifierFromSSLibKey(key)
70 if err != nil {
71 t.Error(err)
72 }
73
74 message := []byte("test message")
75
76 signature, err := sv.Sign(context.Background(), message)
77 if err != nil {
78 t.Error(err)
79 }
80
81 expectedSignature := []byte{0x80, 0x72, 0xb4, 0x31, 0xc5, 0xa3, 0x7e, 0xc, 0xf3, 0x91, 0x22, 0x3, 0x60, 0xbf, 0x92, 0xa4, 0x46, 0x31, 0x84, 0x83, 0xf1, 0x31, 0x3, 0xdc, 0xbc, 0x5, 0x6f, 0xab, 0x84, 0xe4, 0xdc, 0xe9, 0xf5, 0x1c, 0xa9, 0xb3, 0x95, 0xa5, 0xa0, 0x16, 0xd3, 0xaa, 0x4d, 0xe7, 0xde, 0xaf, 0xc2, 0x5e, 0x1e, 0x9a, 0x9d, 0xc8, 0xb2, 0x5c, 0x1c, 0x68, 0xf7, 0x28, 0xb4, 0x1, 0x4d, 0x9f, 0xc8, 0x4}
82 assert.Equal(t, expectedSignature, signature)
83
84 key, err = LoadED25519KeyFromFile(filepath.Join("test-data", "ed25519-test-key.pub"))
85 if err != nil {
86 t.Fatal(err)
87 }
88
89 sv, err = NewED25519SignerVerifierFromSSLibKey(key)
90 if err != nil {
91 t.Error(err)
92 }
93
94 _, err = sv.Sign(context.Background(), message)
95 assert.ErrorIs(t, err, ErrNotPrivateKey)
96 }
97
98 func TestED25519SignerVerifierVerify(t *testing.T) {
99 key, err := LoadED25519KeyFromFile(filepath.Join("test-data", "ed25519-test-key.pub"))
100 if err != nil {
101 t.Fatal(err)
102 }
103
104 sv, err := NewED25519SignerVerifierFromSSLibKey(key)
105 if err != nil {
106 t.Error(err)
107 }
108
109 message := []byte("test message")
110 signature := []byte{0x80, 0x72, 0xb4, 0x31, 0xc5, 0xa3, 0x7e, 0xc, 0xf3, 0x91, 0x22, 0x3, 0x60, 0xbf, 0x92, 0xa4, 0x46, 0x31, 0x84, 0x83, 0xf1, 0x31, 0x3, 0xdc, 0xbc, 0x5, 0x6f, 0xab, 0x84, 0xe4, 0xdc, 0xe9, 0xf5, 0x1c, 0xa9, 0xb3, 0x95, 0xa5, 0xa0, 0x16, 0xd3, 0xaa, 0x4d, 0xe7, 0xde, 0xaf, 0xc2, 0x5e, 0x1e, 0x9a, 0x9d, 0xc8, 0xb2, 0x5c, 0x1c, 0x68, 0xf7, 0x28, 0xb4, 0x1, 0x4d, 0x9f, 0xc8, 0x4}
111 assert.Nil(t, sv.Verify(context.Background(), message, signature))
112
113 message = []byte("corrupted message")
114 err = sv.Verify(context.Background(), message, signature)
115 assert.ErrorIs(t, err, ErrSignatureVerificationFailed)
116 }
117
118 func TestED25519SignerVerifierWithDSSEEnvelope(t *testing.T) {
119 key, err := LoadED25519KeyFromFile(filepath.Join("test-data", "ed25519-test-key"))
120 if err != nil {
121 t.Fatal(err)
122 }
123
124 sv, err := NewED25519SignerVerifierFromSSLibKey(key)
125 if err != nil {
126 t.Fatal(err)
127 }
128
129 payloadType := "application/vnd.dsse+json"
130 payload := []byte("test message")
131
132 es, err := dsse.NewEnvelopeSigner(sv)
133 if err != nil {
134 t.Error(err)
135 }
136
137 env, err := es.SignPayload(context.Background(), payloadType, payload)
138 if err != nil {
139 t.Error(err)
140 }
141
142 assert.Equal(t, "52e3b8e73279d6ebdd62a5016e2725ff284f569665eb92ccb145d83817a02997", env.Signatures[0].KeyID)
143 envPayload, err := env.DecodeB64Payload()
144 assert.Equal(t, payload, envPayload)
145 assert.Nil(t, err)
146
147 key, err = LoadED25519KeyFromFile(filepath.Join("test-data", "ed25519-test-key.pub"))
148 if err != nil {
149 t.Fatal(err)
150 }
151
152 sv, err = NewED25519SignerVerifierFromSSLibKey(key)
153 if err != nil {
154 t.Fatal(err)
155 }
156
157 ev, err := dsse.NewEnvelopeVerifier(sv)
158 if err != nil {
159 t.Error(err)
160 }
161
162 acceptedKeys, err := ev.Verify(context.Background(), env)
163 assert.Nil(t, err)
164 assert.Equal(t, "52e3b8e73279d6ebdd62a5016e2725ff284f569665eb92ccb145d83817a02997", acceptedKeys[0].KeyID)
165 }
166
167 func TestED25519SignerVerifierWithMetablockFile(t *testing.T) {
168 key, err := LoadED25519KeyFromFile(filepath.Join("test-data", "ed25519-test-key.pub"))
169 if err != nil {
170 t.Fatal(err)
171 }
172
173 sv, err := NewED25519SignerVerifierFromSSLibKey(key)
174 if err != nil {
175 t.Fatal(err)
176 }
177
178 metadataBytes, err := os.ReadFile(filepath.Join("test-data", "test-ed25519.52e3b8e7.link"))
179 if err != nil {
180 t.Fatal(err)
181 }
182
183 mb := struct {
184 Signatures []struct {
185 KeyID string `json:"keyid"`
186 Sig string `json:"sig"`
187 } `json:"signatures"`
188 Signed any `json:"signed"`
189 }{}
190
191 if err := json.Unmarshal(metadataBytes, &mb); err != nil {
192 t.Fatal(err)
193 }
194
195 assert.Equal(t, "4c8b7605a9195d4ddba54493bbb5257a9836c1d16056a027fd77e97b95a4f3e36f8bc3c9c9960387d68187760b3072a30c44f992c5bf8f7497c303a3b0a32403", mb.Signatures[0].Sig)
196 assert.Equal(t, sv.keyID, mb.Signatures[0].KeyID)
197
198 encodedBytes, err := cjson.EncodeCanonical(mb.Signed)
199 if err != nil {
200 t.Fatal(err)
201 }
202
203 decodedSig := hexDecode(t, mb.Signatures[0].Sig)
204
205 err = sv.Verify(context.Background(), encodedBytes, decodedSig)
206 assert.Nil(t, err)
207 }
208
View as plain text