Skip to content

Commit 26ce440

Browse files
committed
feat(test): add more tests for the presets, and compat with iso-ucan
1 parent a43c3af commit 26ce440

File tree

3 files changed

+179
-101
lines changed

3 files changed

+179
-101
lines changed

common.go

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,64 @@
11
package varsig
22

3-
// Ed25519 produces a varsig that describes the associated algorithm defined
4-
// by the [IANA JOSE specification].
5-
//
63
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
4+
5+
// Ed25519 produces a varsig for EdDSA using Ed25519 curve.
6+
// This algorithm is defined in [IANA JOSE specification].
77
func Ed25519(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) {
88
return NewEdDSAVarsig(CurveEd25519, HashSha2_512, payloadEncoding, opts...)
99
}
1010

11-
// Ed448 produces a varsig that describes the associated algorithm defined
12-
// by the [IANA JOSE specification].
13-
//
14-
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
11+
// Ed448 produces a varsig for EdDSA using Ed448 curve.
12+
// This algorithm is defined in [IANA JOSE specification].
1513
func Ed448(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) {
1614
return NewEdDSAVarsig(CurveEd448, HashShake_256, payloadEncoding, opts...)
1715
}
1816

19-
// RS256 produces a varsig that describes the associated algorithm defined
20-
// by the [IANA JOSE specification].
21-
//
22-
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
17+
// RS256 produces a varsig for RSASSA-PKCS1-v1_5 using SHA-256.
18+
// This algorithm is defined in [IANA JOSE specification].
2319
func RS256(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
2420
return NewRSAVarsig(HashSha2_256, keyLength, payloadEncoding, opts...)
2521
}
2622

27-
// RS384 produces a varsig that describes the associated algorithm defined
28-
// by the [IANA JOSE specification].
29-
//
30-
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
23+
// RS384 produces a varsig for RSASSA-PKCS1-v1_5 using SHA-384.
24+
// This algorithm is defined in [IANA JOSE specification].
3125
func RS384(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
3226
return NewRSAVarsig(HashSha2_384, keyLength, payloadEncoding, opts...)
3327
}
3428

35-
// RS512 produces a varsig that describes the associated algorithm defined
36-
// by the [IANA JOSE specification].
37-
//
38-
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
29+
// RS512 produces a varsig for RSASSA-PKCS1-v1_5 using SHA-512.
30+
// This algorithm is defined in [IANA JOSE specification].
3931
func RS512(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
4032
return NewRSAVarsig(HashSha2_512, keyLength, payloadEncoding, opts...)
4133
}
34+
35+
// ES256 produces a varsig for ECDSA using P-256 and SHA-256.
36+
// This algorithm is defined in [IANA JOSE specification].
37+
func ES256(payloadEncoding PayloadEncoding, opts ...Option) (ECDSAVarsig, error) {
38+
return NewECDSAVarsig(CurveP256, HashSha2_256, payloadEncoding, opts...)
39+
}
40+
41+
// ES256K produces a varsig for ECDSA using secp256k1 curve and SHA-256.
42+
// This algorithm is defined in [IANA JOSE specification].
43+
func ES256K(payloadEncoding PayloadEncoding, opts ...Option) (ECDSAVarsig, error) {
44+
return NewECDSAVarsig(CurveSecp256k1, HashSha2_256, payloadEncoding, opts...)
45+
}
46+
47+
// ES384 produces a varsig for ECDSA using P-384 and SHA-384.
48+
// This algorithm is defined in [IANA JOSE specification].
49+
func ES384(payloadEncoding PayloadEncoding, opts ...Option) (ECDSAVarsig, error) {
50+
return NewECDSAVarsig(CurveP384, HashSha2_384, payloadEncoding, opts...)
51+
}
52+
53+
// ES512 produces a varsig for ECDSA using P-521 and SHA-512.
54+
// This algorithm is defined in [IANA JOSE specification].
55+
func ES512(payloadEncoding PayloadEncoding, opts ...Option) (ECDSAVarsig, error) {
56+
return NewECDSAVarsig(CurveP521, HashSha2_512, payloadEncoding, opts...)
57+
}
58+
59+
// EIP191 produces a varsig for ECDSA using the Secp256k1 curve, Keccak256 and encoded
60+
// with the "personal_sign" format defined by [EIP191].
61+
// [EIP191]: https://eips.ethereum.org/EIPS/eip-191
62+
func EIP191(opts ...Option) (ECDSAVarsig, error) {
63+
return NewECDSAVarsig(CurveSecp256k1, HashKeccak256, PayloadEncodingEIP191, opts...)
64+
}

common_test.go

Lines changed: 137 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,149 @@
11
package varsig_test
22

33
import (
4+
"encoding/hex"
45
"testing"
56

6-
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
78

89
"github.com/ucan-wg/go-varsig"
910
)
1011

11-
func TestEd25519(t *testing.T) {
12-
t.Parallel()
13-
14-
in, err := varsig.Ed25519(varsig.PayloadEncodingDAGCBOR)
15-
mustVarsig(t, in, err)
16-
out := roundTrip(t, in, "3401ed01ed011371")
17-
assertEdDSAEqual(t, in, out)
12+
func TestRoundTrip(t *testing.T) {
13+
for _, tc := range []struct {
14+
name string
15+
varsig varsig.Varsig
16+
dataHex string
17+
dataBytes []byte
18+
}{
19+
// Arbitrary use of presets
20+
{
21+
name: "Ed25519",
22+
varsig: must(varsig.Ed25519(varsig.PayloadEncodingDAGCBOR)),
23+
dataHex: "3401ed01ed011371",
24+
},
25+
{
26+
name: "Ed448",
27+
varsig: must(varsig.Ed448(varsig.PayloadEncodingDAGCBOR)),
28+
dataHex: "3401ed0183241971",
29+
},
30+
{
31+
name: "RS256",
32+
varsig: must(varsig.RS256(0x100, varsig.PayloadEncodingDAGCBOR)),
33+
dataHex: "3401852412800271",
34+
},
35+
{
36+
name: "RS384",
37+
varsig: must(varsig.RS384(0x100, varsig.PayloadEncodingDAGCBOR)),
38+
dataHex: "3401852420800271",
39+
},
40+
{
41+
name: "RS512",
42+
varsig: must(varsig.RS512(0x100, varsig.PayloadEncodingDAGCBOR)),
43+
dataHex: "3401852413800271",
44+
},
45+
{
46+
name: "ES256",
47+
varsig: must(varsig.ES256(varsig.PayloadEncodingDAGCBOR)),
48+
dataHex: "3401ec0180241271",
49+
},
50+
{
51+
name: "ES256K",
52+
varsig: must(varsig.ES256K(varsig.PayloadEncodingDAGCBOR)),
53+
dataHex: "3401ec01e7011271",
54+
},
55+
{
56+
name: "ES384",
57+
varsig: must(varsig.ES384(varsig.PayloadEncodingDAGCBOR)),
58+
dataHex: "3401ec0181242071",
59+
},
60+
{
61+
name: "ES512",
62+
varsig: must(varsig.ES512(varsig.PayloadEncodingDAGCBOR)),
63+
dataHex: "3401ec0182241371",
64+
},
65+
{
66+
name: "EIP191",
67+
varsig: must(varsig.EIP191()),
68+
dataHex: "3401ec01e7011b91a303",
69+
},
70+
71+
// from https://github.com/hugomrdias/iso-repo/blob/main/packages/iso-ucan/test/varsig.test.js
72+
{
73+
name: "RS256+RAW",
74+
varsig: must(varsig.RS256(256, varsig.PayloadEncodingVerbatim)),
75+
dataBytes: []byte{52, 1, 133, 36, 18, 128, 2, 95},
76+
},
77+
{
78+
name: "ES256+RAW",
79+
varsig: must(varsig.ES256(varsig.PayloadEncodingVerbatim)),
80+
dataBytes: []byte{52, 1, 236, 1, 128, 36, 18, 95},
81+
},
82+
{
83+
name: "ES512+RAW",
84+
varsig: must(varsig.ES512(varsig.PayloadEncodingVerbatim)),
85+
dataBytes: []byte{52, 1, 236, 1, 130, 36, 19, 95},
86+
},
87+
{
88+
name: "ES256K+RAW",
89+
varsig: must(varsig.ES256K(varsig.PayloadEncodingVerbatim)),
90+
dataBytes: []byte{52, 1, 236, 1, 231, 1, 18, 95},
91+
},
92+
// the two cases below in iso-ucan are actually EIP191 preset where the encoding is overridden
93+
// therefore, we build them manually.
94+
{
95+
name: "EIP191+RAW",
96+
varsig: must(varsig.NewECDSAVarsig(varsig.CurveSecp256k1, varsig.HashKeccak256, varsig.PayloadEncodingVerbatim)),
97+
dataBytes: []byte{52, 1, 236, 1, 231, 1, 27, 145, 195, 3, 95},
98+
},
99+
{
100+
name: "EIP191+DAG-CBOR",
101+
varsig: must(varsig.NewECDSAVarsig(varsig.CurveSecp256k1, varsig.HashKeccak256, varsig.PayloadEncodingDAGCBOR)),
102+
dataBytes: []byte{52, 1, 236, 1, 231, 1, 27, 145, 195, 3, 113},
103+
},
104+
} {
105+
t.Run(tc.name, func(t *testing.T) {
106+
// round-trip encode and back
107+
data := tc.varsig.Encode()
108+
109+
if tc.dataBytes != nil {
110+
require.Equal(t, tc.dataBytes, data)
111+
}
112+
if tc.dataHex != "" {
113+
require.Equal(t, tc.dataHex, hex.EncodeToString(data))
114+
}
115+
116+
rt, err := varsig.Decode(data)
117+
require.NoError(t, err)
118+
119+
require.Equal(t, tc.varsig.Version(), rt.Version())
120+
require.Equal(t, tc.varsig.Discriminator(), rt.Discriminator())
121+
require.Equal(t, tc.varsig.PayloadEncoding(), rt.PayloadEncoding())
122+
require.Equal(t, tc.varsig.Signature(), rt.Signature())
123+
124+
switch vs := tc.varsig.(type) {
125+
case varsig.EdDSAVarsig:
126+
rt := rt.(varsig.EdDSAVarsig)
127+
require.Equal(t, vs.Curve(), rt.Curve())
128+
require.Equal(t, vs.Hash(), rt.Hash())
129+
case varsig.ECDSAVarsig:
130+
rt := rt.(varsig.ECDSAVarsig)
131+
require.Equal(t, vs.Curve(), rt.Curve())
132+
require.Equal(t, vs.Hash(), rt.Hash())
133+
case varsig.RSAVarsig:
134+
rt := rt.(varsig.RSAVarsig)
135+
require.Equal(t, vs.Hash(), rt.Hash())
136+
require.Equal(t, vs.KeyLength(), rt.KeyLength())
137+
default:
138+
t.Fatalf("unexpected varsig type: %T", vs)
139+
}
140+
})
141+
}
18142
}
19143

20-
func TestEd448(t *testing.T) {
21-
t.Parallel()
22-
23-
in, err := varsig.Ed448(varsig.PayloadEncodingDAGCBOR)
24-
mustVarsig(t, in, err)
25-
out := roundTrip(t, in, "3401ed0183241971")
26-
assertEdDSAEqual(t, in, out)
27-
}
28-
29-
func TestRS256(t *testing.T) {
30-
t.Parallel()
31-
32-
in, err := varsig.RS256(0x100, varsig.PayloadEncodingDAGCBOR)
33-
mustVarsig(t, in, err)
34-
out := roundTrip(t, in, "3401852412800271")
35-
assertRSAEqual(t, in, out)
36-
}
37-
38-
func TestRS384(t *testing.T) {
39-
t.Parallel()
40-
41-
in, err := varsig.RS384(0x100, varsig.PayloadEncodingDAGCBOR)
42-
mustVarsig(t, in, err)
43-
out := roundTrip(t, in, "3401852420800271")
44-
assertRSAEqual(t, in, out)
45-
}
46-
47-
func TestRS512(t *testing.T) {
48-
t.Parallel()
49-
50-
in, err := varsig.RS512(0x100, varsig.PayloadEncodingDAGCBOR)
51-
mustVarsig(t, in, err)
52-
out := roundTrip(t, in, "3401852413800271")
53-
assertRSAEqual(t, in, out)
54-
}
55-
56-
func assertEdDSAEqual(t *testing.T, in, out varsig.EdDSAVarsig) {
57-
t.Helper()
58-
59-
assert.Equal(t, in.Curve(), out.Curve())
60-
assert.Equal(t, in.Hash(), out.Hash())
61-
}
62-
63-
func assertRSAEqual(t *testing.T, in, out varsig.RSAVarsig) {
64-
t.Helper()
65-
66-
assert.Equal(t, in.Hash(), out.Hash())
67-
assert.Equal(t, in.KeyLength(), out.KeyLength())
144+
func must[T any](v T, err error) T {
145+
if err != nil {
146+
panic(err)
147+
}
148+
return v
68149
}

varsig_test.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package varsig_test
22

33
import (
44
"encoding/hex"
5-
"errors"
65
"io"
76
"testing"
87

@@ -157,28 +156,3 @@ func TestDecode(t *testing.T) {
157156
assert.NotNil(t, vs) // varsig is still returned with just "header"
158157
})
159158
}
160-
161-
func mustVarsig[T varsig.Varsig](t *testing.T, v T, err error) {
162-
t.Helper()
163-
164-
if err != nil && (v.Version() != varsig.Version0 || !errors.Is(err, varsig.ErrMissingSignature)) {
165-
t.Error(err)
166-
}
167-
}
168-
169-
func roundTrip[T varsig.Varsig](t *testing.T, in T, expEncHex string) T {
170-
data := in.Encode()
171-
assert.Equal(t, expEncHex, hex.EncodeToString(data))
172-
173-
out, err := varsig.Decode(in.Encode())
174-
if err != nil && (out.Version() != varsig.Version0 || !errors.Is(err, varsig.ErrMissingSignature)) {
175-
t.Fail()
176-
}
177-
178-
assert.Equal(t, in.Version(), out.Version())
179-
assert.Equal(t, in.Discriminator(), out.Discriminator())
180-
assert.Equal(t, in.PayloadEncoding(), out.PayloadEncoding())
181-
assert.Equal(t, in.Signature(), out.Signature())
182-
183-
return out.(T)
184-
}

0 commit comments

Comments
 (0)