feat(test): add more tests for the presets, and compat with iso-ucan
This commit is contained in:
61
common.go
61
common.go
@@ -1,41 +1,64 @@
|
|||||||
package varsig
|
package varsig
|
||||||
|
|
||||||
// Ed25519 produces a varsig that describes the associated algorithm defined
|
|
||||||
// by the [IANA JOSE specification].
|
|
||||||
//
|
|
||||||
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
|
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
|
||||||
|
|
||||||
|
// Ed25519 produces a varsig for EdDSA using Ed25519 curve.
|
||||||
|
// This algorithm is defined in [IANA JOSE specification].
|
||||||
func Ed25519(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) {
|
func Ed25519(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) {
|
||||||
return NewEdDSAVarsig(CurveEd25519, HashSha2_512, payloadEncoding, opts...)
|
return NewEdDSAVarsig(CurveEd25519, HashSha2_512, payloadEncoding, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ed448 produces a varsig that describes the associated algorithm defined
|
// Ed448 produces a varsig for EdDSA using Ed448 curve.
|
||||||
// by the [IANA JOSE specification].
|
// This algorithm is defined in [IANA JOSE specification].
|
||||||
//
|
|
||||||
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
|
|
||||||
func Ed448(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) {
|
func Ed448(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) {
|
||||||
return NewEdDSAVarsig(CurveEd448, HashShake_256, payloadEncoding, opts...)
|
return NewEdDSAVarsig(CurveEd448, HashShake_256, payloadEncoding, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RS256 produces a varsig that describes the associated algorithm defined
|
// RS256 produces a varsig for RSASSA-PKCS1-v1_5 using SHA-256.
|
||||||
// by the [IANA JOSE specification].
|
// This algorithm is defined in [IANA JOSE specification].
|
||||||
//
|
|
||||||
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
|
|
||||||
func RS256(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
|
func RS256(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
|
||||||
return NewRSAVarsig(HashSha2_256, keyLength, payloadEncoding, opts...)
|
return NewRSAVarsig(HashSha2_256, keyLength, payloadEncoding, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RS384 produces a varsig that describes the associated algorithm defined
|
// RS384 produces a varsig for RSASSA-PKCS1-v1_5 using SHA-384.
|
||||||
// by the [IANA JOSE specification].
|
// This algorithm is defined in [IANA JOSE specification].
|
||||||
//
|
|
||||||
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
|
|
||||||
func RS384(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
|
func RS384(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
|
||||||
return NewRSAVarsig(HashSha2_384, keyLength, payloadEncoding, opts...)
|
return NewRSAVarsig(HashSha2_384, keyLength, payloadEncoding, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RS512 produces a varsig that describes the associated algorithm defined
|
// RS512 produces a varsig for RSASSA-PKCS1-v1_5 using SHA-512.
|
||||||
// by the [IANA JOSE specification].
|
// This algorithm is defined in [IANA JOSE specification].
|
||||||
//
|
|
||||||
// [IANA JOSE specification]: https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
|
|
||||||
func RS512(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
|
func RS512(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
|
||||||
return NewRSAVarsig(HashSha2_512, keyLength, payloadEncoding, opts...)
|
return NewRSAVarsig(HashSha2_512, keyLength, payloadEncoding, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ES256 produces a varsig for ECDSA using P-256 and SHA-256.
|
||||||
|
// This algorithm is defined in [IANA JOSE specification].
|
||||||
|
func ES256(payloadEncoding PayloadEncoding, opts ...Option) (ECDSAVarsig, error) {
|
||||||
|
return NewECDSAVarsig(CurveP256, HashSha2_256, payloadEncoding, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES256K produces a varsig for ECDSA using secp256k1 curve and SHA-256.
|
||||||
|
// This algorithm is defined in [IANA JOSE specification].
|
||||||
|
func ES256K(payloadEncoding PayloadEncoding, opts ...Option) (ECDSAVarsig, error) {
|
||||||
|
return NewECDSAVarsig(CurveSecp256k1, HashSha2_256, payloadEncoding, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES384 produces a varsig for ECDSA using P-384 and SHA-384.
|
||||||
|
// This algorithm is defined in [IANA JOSE specification].
|
||||||
|
func ES384(payloadEncoding PayloadEncoding, opts ...Option) (ECDSAVarsig, error) {
|
||||||
|
return NewECDSAVarsig(CurveP384, HashSha2_384, payloadEncoding, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES512 produces a varsig for ECDSA using P-521 and SHA-512.
|
||||||
|
// This algorithm is defined in [IANA JOSE specification].
|
||||||
|
func ES512(payloadEncoding PayloadEncoding, opts ...Option) (ECDSAVarsig, error) {
|
||||||
|
return NewECDSAVarsig(CurveP521, HashSha2_512, payloadEncoding, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EIP191 produces a varsig for ECDSA using the Secp256k1 curve, Keccak256 and encoded
|
||||||
|
// with the "personal_sign" format defined by [EIP191].
|
||||||
|
// [EIP191]: https://eips.ethereum.org/EIPS/eip-191
|
||||||
|
func EIP191(opts ...Option) (ECDSAVarsig, error) {
|
||||||
|
return NewECDSAVarsig(CurveSecp256k1, HashKeccak256, PayloadEncodingEIP191, opts...)
|
||||||
|
}
|
||||||
|
|||||||
191
common_test.go
191
common_test.go
@@ -1,68 +1,149 @@
|
|||||||
package varsig_test
|
package varsig_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/ucan-wg/go-varsig"
|
"github.com/ucan-wg/go-varsig"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEd25519(t *testing.T) {
|
func TestRoundTrip(t *testing.T) {
|
||||||
t.Parallel()
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
varsig varsig.Varsig
|
||||||
|
dataHex string
|
||||||
|
dataBytes []byte
|
||||||
|
}{
|
||||||
|
// Arbitrary use of presets
|
||||||
|
{
|
||||||
|
name: "Ed25519",
|
||||||
|
varsig: must(varsig.Ed25519(varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataHex: "3401ed01ed011371",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ed448",
|
||||||
|
varsig: must(varsig.Ed448(varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataHex: "3401ed0183241971",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "RS256",
|
||||||
|
varsig: must(varsig.RS256(0x100, varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataHex: "3401852412800271",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "RS384",
|
||||||
|
varsig: must(varsig.RS384(0x100, varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataHex: "3401852420800271",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "RS512",
|
||||||
|
varsig: must(varsig.RS512(0x100, varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataHex: "3401852413800271",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ES256",
|
||||||
|
varsig: must(varsig.ES256(varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataHex: "3401ec0180241271",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ES256K",
|
||||||
|
varsig: must(varsig.ES256K(varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataHex: "3401ec01e7011271",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ES384",
|
||||||
|
varsig: must(varsig.ES384(varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataHex: "3401ec0181242071",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ES512",
|
||||||
|
varsig: must(varsig.ES512(varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataHex: "3401ec0182241371",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "EIP191",
|
||||||
|
varsig: must(varsig.EIP191()),
|
||||||
|
dataHex: "3401ec01e7011b91a303",
|
||||||
|
},
|
||||||
|
|
||||||
in, err := varsig.Ed25519(varsig.PayloadEncodingDAGCBOR)
|
// from https://github.com/hugomrdias/iso-repo/blob/main/packages/iso-ucan/test/varsig.test.js
|
||||||
mustVarsig(t, in, err)
|
{
|
||||||
out := roundTrip(t, in, "3401ed01ed011371")
|
name: "RS256+RAW",
|
||||||
assertEdDSAEqual(t, in, out)
|
varsig: must(varsig.RS256(256, varsig.PayloadEncodingVerbatim)),
|
||||||
|
dataBytes: []byte{52, 1, 133, 36, 18, 128, 2, 95},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ES256+RAW",
|
||||||
|
varsig: must(varsig.ES256(varsig.PayloadEncodingVerbatim)),
|
||||||
|
dataBytes: []byte{52, 1, 236, 1, 128, 36, 18, 95},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ES512+RAW",
|
||||||
|
varsig: must(varsig.ES512(varsig.PayloadEncodingVerbatim)),
|
||||||
|
dataBytes: []byte{52, 1, 236, 1, 130, 36, 19, 95},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ES256K+RAW",
|
||||||
|
varsig: must(varsig.ES256K(varsig.PayloadEncodingVerbatim)),
|
||||||
|
dataBytes: []byte{52, 1, 236, 1, 231, 1, 18, 95},
|
||||||
|
},
|
||||||
|
// the two cases below in iso-ucan are actually EIP191 preset where the encoding is overridden
|
||||||
|
// therefore, we build them manually.
|
||||||
|
{
|
||||||
|
name: "EIP191+RAW",
|
||||||
|
varsig: must(varsig.NewECDSAVarsig(varsig.CurveSecp256k1, varsig.HashKeccak256, varsig.PayloadEncodingVerbatim)),
|
||||||
|
dataBytes: []byte{52, 1, 236, 1, 231, 1, 27, 145, 195, 3, 95},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "EIP191+DAG-CBOR",
|
||||||
|
varsig: must(varsig.NewECDSAVarsig(varsig.CurveSecp256k1, varsig.HashKeccak256, varsig.PayloadEncodingDAGCBOR)),
|
||||||
|
dataBytes: []byte{52, 1, 236, 1, 231, 1, 27, 145, 195, 3, 113},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
// round-trip encode and back
|
||||||
|
data := tc.varsig.Encode()
|
||||||
|
|
||||||
|
if tc.dataBytes != nil {
|
||||||
|
require.Equal(t, tc.dataBytes, data)
|
||||||
|
}
|
||||||
|
if tc.dataHex != "" {
|
||||||
|
require.Equal(t, tc.dataHex, hex.EncodeToString(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
rt, err := varsig.Decode(data)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, tc.varsig.Version(), rt.Version())
|
||||||
|
require.Equal(t, tc.varsig.Discriminator(), rt.Discriminator())
|
||||||
|
require.Equal(t, tc.varsig.PayloadEncoding(), rt.PayloadEncoding())
|
||||||
|
require.Equal(t, tc.varsig.Signature(), rt.Signature())
|
||||||
|
|
||||||
|
switch vs := tc.varsig.(type) {
|
||||||
|
case varsig.EdDSAVarsig:
|
||||||
|
rt := rt.(varsig.EdDSAVarsig)
|
||||||
|
require.Equal(t, vs.Curve(), rt.Curve())
|
||||||
|
require.Equal(t, vs.Hash(), rt.Hash())
|
||||||
|
case varsig.ECDSAVarsig:
|
||||||
|
rt := rt.(varsig.ECDSAVarsig)
|
||||||
|
require.Equal(t, vs.Curve(), rt.Curve())
|
||||||
|
require.Equal(t, vs.Hash(), rt.Hash())
|
||||||
|
case varsig.RSAVarsig:
|
||||||
|
rt := rt.(varsig.RSAVarsig)
|
||||||
|
require.Equal(t, vs.Hash(), rt.Hash())
|
||||||
|
require.Equal(t, vs.KeyLength(), rt.KeyLength())
|
||||||
|
default:
|
||||||
|
t.Fatalf("unexpected varsig type: %T", vs)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEd448(t *testing.T) {
|
func must[T any](v T, err error) T {
|
||||||
t.Parallel()
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
in, err := varsig.Ed448(varsig.PayloadEncodingDAGCBOR)
|
}
|
||||||
mustVarsig(t, in, err)
|
return v
|
||||||
out := roundTrip(t, in, "3401ed0183241971")
|
|
||||||
assertEdDSAEqual(t, in, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRS256(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
in, err := varsig.RS256(0x100, varsig.PayloadEncodingDAGCBOR)
|
|
||||||
mustVarsig(t, in, err)
|
|
||||||
out := roundTrip(t, in, "3401852412800271")
|
|
||||||
assertRSAEqual(t, in, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRS384(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
in, err := varsig.RS384(0x100, varsig.PayloadEncodingDAGCBOR)
|
|
||||||
mustVarsig(t, in, err)
|
|
||||||
out := roundTrip(t, in, "3401852420800271")
|
|
||||||
assertRSAEqual(t, in, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRS512(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
in, err := varsig.RS512(0x100, varsig.PayloadEncodingDAGCBOR)
|
|
||||||
mustVarsig(t, in, err)
|
|
||||||
out := roundTrip(t, in, "3401852413800271")
|
|
||||||
assertRSAEqual(t, in, out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertEdDSAEqual(t *testing.T, in, out varsig.EdDSAVarsig) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
assert.Equal(t, in.Curve(), out.Curve())
|
|
||||||
assert.Equal(t, in.Hash(), out.Hash())
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertRSAEqual(t *testing.T, in, out varsig.RSAVarsig) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
assert.Equal(t, in.Hash(), out.Hash())
|
|
||||||
assert.Equal(t, in.KeyLength(), out.KeyLength())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package varsig_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -157,28 +156,3 @@ func TestDecode(t *testing.T) {
|
|||||||
assert.NotNil(t, vs) // varsig is still returned with just "header"
|
assert.NotNil(t, vs) // varsig is still returned with just "header"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustVarsig[T varsig.Varsig](t *testing.T, v T, err error) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
if err != nil && (v.Version() != varsig.Version0 || !errors.Is(err, varsig.ErrMissingSignature)) {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func roundTrip[T varsig.Varsig](t *testing.T, in T, expEncHex string) T {
|
|
||||||
data := in.Encode()
|
|
||||||
assert.Equal(t, expEncHex, hex.EncodeToString(data))
|
|
||||||
|
|
||||||
out, err := varsig.Decode(in.Encode())
|
|
||||||
if err != nil && (out.Version() != varsig.Version0 || !errors.Is(err, varsig.ErrMissingSignature)) {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, in.Version(), out.Version())
|
|
||||||
assert.Equal(t, in.Discriminator(), out.Discriminator())
|
|
||||||
assert.Equal(t, in.PayloadEncoding(), out.PayloadEncoding())
|
|
||||||
assert.Equal(t, in.Signature(), out.Signature())
|
|
||||||
|
|
||||||
return out.(T)
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user