feat(hashes): shorten HashAlgorithm to Hash, add more of them

This commit is contained in:
Michael Muré
2025-07-22 11:27:24 +02:00
parent c7a870e9db
commit 0763d6f8b6
9 changed files with 78 additions and 45 deletions

View File

@@ -5,7 +5,7 @@ package varsig
// //
// [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
func Ed25519(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) { func Ed25519(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) {
return NewEdDSAVarsig(CurveEd25519, HashAlgorithmSHA512, payloadEncoding, opts...) return NewEdDSAVarsig(CurveEd25519, HashSha2_512, payloadEncoding, opts...)
} }
// Ed448 produces a varsig that describes the associated algorithm defined // Ed448 produces a varsig that describes the associated algorithm defined
@@ -13,7 +13,7 @@ func Ed25519(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, erro
// //
// [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
func Ed448(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) { func Ed448(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) {
return NewEdDSAVarsig(CurveEd448, HashAlgorithmShake256, payloadEncoding, opts...) return NewEdDSAVarsig(CurveEd448, HashShake_256, payloadEncoding, opts...)
} }
// RS256 produces a varsig that describes the associated algorithm defined // RS256 produces a varsig that describes the associated algorithm defined
@@ -21,7 +21,7 @@ func Ed448(payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error)
// //
// [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
func RS256(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) { func RS256(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
return NewRSAVarsig(HashAlgorithmSHA256, keyLength, payloadEncoding, opts...) return NewRSAVarsig(HashSha2_256, keyLength, payloadEncoding, opts...)
} }
// RS384 produces a varsig that describes the associated algorithm defined // RS384 produces a varsig that describes the associated algorithm defined
@@ -29,7 +29,7 @@ func RS256(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (R
// //
// [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
func RS384(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) { func RS384(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
return NewRSAVarsig(HashAlgorithmSHA384, keyLength, payloadEncoding, opts...) return NewRSAVarsig(HashSha2_384, keyLength, payloadEncoding, opts...)
} }
// RS512 produces a varsig that describes the associated algorithm defined // RS512 produces a varsig that describes the associated algorithm defined
@@ -37,5 +37,5 @@ func RS384(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (R
// //
// [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
func RS512(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) { func RS512(keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
return NewRSAVarsig(HashAlgorithmSHA512, keyLength, payloadEncoding, opts...) return NewRSAVarsig(HashSha2_512, keyLength, payloadEncoding, opts...)
} }

View File

@@ -57,12 +57,12 @@ func assertEdDSAEqual(t *testing.T, in, out varsig.EdDSAVarsig) {
t.Helper() t.Helper()
assert.Equal(t, in.Curve(), out.Curve()) assert.Equal(t, in.Curve(), out.Curve())
assert.Equal(t, in.HashAlgorithm(), out.HashAlgorithm()) assert.Equal(t, in.Hash(), out.Hash())
} }
func assertRSAEqual(t *testing.T, in, out varsig.RSAVarsig) { func assertRSAEqual(t *testing.T, in, out varsig.RSAVarsig) {
t.Helper() t.Helper()
assert.Equal(t, in.HashAlgorithm(), out.HashAlgorithm()) assert.Equal(t, in.Hash(), out.Hash())
assert.Equal(t, in.KeyLength(), out.KeyLength()) assert.Equal(t, in.KeyLength(), out.KeyLength())
} }

View File

@@ -8,38 +8,70 @@ import (
// Prefix is the value for the varsig's varuint prefix byte. // Prefix is the value for the varsig's varuint prefix byte.
const Prefix = uint64(0x34) const Prefix = uint64(0x34)
// HashAlgorithm is the value that specifies the hash algorithm // Hash is the value that specifies the hash algorithm
// that's used to reduce the signed content // that's used to reduce the signed content
type HashAlgorithm uint64 type Hash uint64
// Constant values that allow Varsig implementations to specify how // Constant values that allow Varsig implementations to specify how
// the payload content is hashed before the signature is generated. // the payload content is hashed before the signature is generated.
const ( const (
HashAlgorithmUnspecified HashAlgorithm = 0x00 HashUnspecified Hash = 0x00
HashAlgorithmSHA256 = HashAlgorithm(0x12)
HashAlgorithmSHA384 = HashAlgorithm(0x20) HashSha2_224 = Hash(0x1013)
HashAlgorithmSHA512 = HashAlgorithm(0x13) HashSha2_256 = Hash(0x12)
HashAlgorithmShake256 = HashAlgorithm(0x19) HashSha2_384 = Hash(0x20)
HashSha2_512 = Hash(0x13)
HashSha3_224 = Hash(0x17)
HashSha3_256 = Hash(0x16)
HashSha3_384 = Hash(0x15)
HashSha3_512 = Hash(0x14)
HashSha512_224 = Hash(0x1014)
HashSha512_256 = Hash(0x1015)
HashBlake2s_256 = Hash(0xb260)
HashBlake2b_256 = Hash(0xb220)
HashBlake2b_384 = Hash(0xb230)
HashBlake2b_512 = Hash(0xb240)
HashShake_256 = Hash(0x19)
HashKeccak256 = Hash(0x1b)
HashKeccak512 = Hash(0x1d)
) )
// DecodeHashAlgorithm reads and validates the expected hash algorithm // DecodeHashAlgorithm reads and validates the expected hash algorithm
// (for varsig types include a variable hash algorithm.) // (for varsig types include a variable hash algorithm.)
func DecodeHashAlgorithm(r BytesReader) (HashAlgorithm, error) { func DecodeHashAlgorithm(r BytesReader) (Hash, error) {
u, err := binary.ReadUvarint(r) u, err := binary.ReadUvarint(r)
if err != nil { if err != nil {
return HashAlgorithmUnspecified, fmt.Errorf("%w: %w", ErrUnknownHashAlgorithm, err) return HashUnspecified, fmt.Errorf("%w: %w", ErrUnknownHash, err)
} }
h := HashAlgorithm(u) h := Hash(u)
switch h { switch h {
case HashAlgorithmSHA256, case HashSha2_224,
HashAlgorithmSHA384, HashSha2_256,
HashAlgorithmSHA512, HashSha2_384,
HashAlgorithmShake256: HashSha2_512,
HashSha3_224,
HashSha3_256,
HashSha3_384,
HashSha3_512,
HashSha512_224,
HashSha512_256,
HashBlake2s_256,
HashBlake2b_256,
HashBlake2b_384,
HashBlake2b_512,
HashShake_256,
HashKeccak256,
HashKeccak512:
return h, nil return h, nil
default: default:
return HashAlgorithmUnspecified, fmt.Errorf("%w: %x", ErrUnknownHashAlgorithm, h) return HashUnspecified, fmt.Errorf("%w: %x", ErrUnknownHash, h)
} }
} }

View File

@@ -18,24 +18,24 @@ func TestDecodeHashAlgorithm(t *testing.T) {
hashAlg, err := varsig.DecodeHashAlgorithm(bytes.NewReader([]byte{0x12})) hashAlg, err := varsig.DecodeHashAlgorithm(bytes.NewReader([]byte{0x12}))
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, varsig.HashAlgorithmSHA256, hashAlg) require.Equal(t, varsig.HashSha2_256, hashAlg)
}) })
t.Run("fails - truncated varsig (no bytes)", func(t *testing.T) { t.Run("fails - truncated varsig (no bytes)", func(t *testing.T) {
t.Parallel() t.Parallel()
hashAlg, err := varsig.DecodeHashAlgorithm(bytes.NewReader([]byte{})) hashAlg, err := varsig.DecodeHashAlgorithm(bytes.NewReader([]byte{}))
require.ErrorIs(t, err, varsig.ErrUnknownHashAlgorithm) require.ErrorIs(t, err, varsig.ErrUnknownHash)
require.ErrorIs(t, err, io.EOF) require.ErrorIs(t, err, io.EOF)
require.Equal(t, varsig.HashAlgorithmUnspecified, hashAlg) require.Equal(t, varsig.HashUnspecified, hashAlg)
}) })
t.Run("fails - unknown hash algorithm", func(t *testing.T) { t.Run("fails - unknown hash algorithm", func(t *testing.T) {
t.Parallel() t.Parallel()
hashAlg, err := varsig.DecodeHashAlgorithm(bytes.NewReader([]byte{0x42})) hashAlg, err := varsig.DecodeHashAlgorithm(bytes.NewReader([]byte{0x42}))
require.ErrorIs(t, err, varsig.ErrUnknownHashAlgorithm) require.ErrorIs(t, err, varsig.ErrUnknownHash)
require.Equal(t, varsig.HashAlgorithmUnspecified, hashAlg) require.Equal(t, varsig.HashUnspecified, hashAlg)
}) })
} }

View File

@@ -46,12 +46,12 @@ type EdDSAVarsig struct {
varsig varsig
curve EdDSACurve curve EdDSACurve
hashAlg HashAlgorithm hashAlg Hash
} }
// NewEdDSAVarsig creates and validates an EdDSA varsig with the provided // NewEdDSAVarsig creates and validates an EdDSA varsig with the provided
// curve, hash algorithm and payload encoding. // curve, hash algorithm and payload encoding.
func NewEdDSAVarsig(curve EdDSACurve, hashAlgorithm HashAlgorithm, payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) { func NewEdDSAVarsig(curve EdDSACurve, hashAlgorithm Hash, payloadEncoding PayloadEncoding, opts ...Option) (EdDSAVarsig, error) {
options := newOptions(opts...) options := newOptions(opts...)
var ( var (
@@ -85,9 +85,9 @@ func (v EdDSAVarsig) Curve() EdDSACurve {
return v.curve return v.curve
} }
// HashAlgorithm returns the value describing the hash algorithm used to hash // Hash returns the value describing the hash algorithm used to hash
// the payload content before the signature is generated. // the payload content before the signature is generated.
func (v EdDSAVarsig) HashAlgorithm() HashAlgorithm { func (v EdDSAVarsig) Hash() Hash {
return v.hashAlg return v.hashAlg
} }

View File

@@ -39,7 +39,7 @@ func TestDecodeEd25519(t *testing.T) {
impl, ok := v.(varsig.EdDSAVarsig) impl, ok := v.(varsig.EdDSAVarsig)
require.True(t, ok) require.True(t, ok)
assert.Equal(t, varsig.CurveEd25519, impl.Curve()) assert.Equal(t, varsig.CurveEd25519, impl.Curve())
assert.Equal(t, varsig.HashAlgorithmSHA512, impl.HashAlgorithm()) assert.Equal(t, varsig.HashSha2_512, impl.Hash())
}) })
t.Run("Encode", func(t *testing.T) { t.Run("Encode", func(t *testing.T) {
@@ -47,7 +47,7 @@ func TestDecodeEd25519(t *testing.T) {
v, err := varsig.NewEdDSAVarsig( v, err := varsig.NewEdDSAVarsig(
varsig.CurveEd25519, varsig.CurveEd25519,
varsig.HashAlgorithmSHA512, varsig.HashSha2_512,
varsig.PayloadEncodingDAGCBOR, varsig.PayloadEncodingDAGCBOR,
varsig.WithForceVersion0(sig), varsig.WithForceVersion0(sig),
) )
@@ -79,7 +79,7 @@ func TestUCANExampleV1(t *testing.T) {
assert.Equal(t, varsig.Version1, ed25519V.Version()) assert.Equal(t, varsig.Version1, ed25519V.Version())
assert.Equal(t, varsig.DiscriminatorEdDSA, ed25519V.Discriminator()) assert.Equal(t, varsig.DiscriminatorEdDSA, ed25519V.Discriminator())
assert.Equal(t, varsig.CurveEd25519, ed25519V.Curve()) assert.Equal(t, varsig.CurveEd25519, ed25519V.Curve())
assert.Equal(t, varsig.HashAlgorithmSHA512, ed25519V.HashAlgorithm()) assert.Equal(t, varsig.HashSha2_512, ed25519V.Hash())
assert.Equal(t, varsig.PayloadEncodingDAGCBOR, ed25519V.PayloadEncoding()) assert.Equal(t, varsig.PayloadEncodingDAGCBOR, ed25519V.PayloadEncoding())
assert.Len(t, ed25519V.Signature(), 0) assert.Len(t, ed25519V.Signature(), 0)
}) })
@@ -89,7 +89,7 @@ func TestUCANExampleV1(t *testing.T) {
edDSAVarsig, err := varsig.NewEdDSAVarsig( edDSAVarsig, err := varsig.NewEdDSAVarsig(
varsig.CurveEd25519, varsig.CurveEd25519,
varsig.HashAlgorithmSHA512, varsig.HashSha2_512,
varsig.PayloadEncodingDAGCBOR, varsig.PayloadEncodingDAGCBOR,
) )
require.NoError(t, err) require.NoError(t, err)

View File

@@ -21,9 +21,9 @@ var ErrUnexpectedSignaturePresent = errors.New("unexpected signature present in
// signing algorithm or sent via a Varsig field. // signing algorithm or sent via a Varsig field.
var ErrUnexpectedSignatureSize = errors.New("unexpected signature size in varsig v0") var ErrUnexpectedSignatureSize = errors.New("unexpected signature size in varsig v0")
// ErrUnknownHashAlgorithm is returned when an unexpected value is provided // ErrUnknownHash is returned when an unexpected value is provided
// while decoding the hashing algorithm. // while decoding the hashing algorithm.
var ErrUnknownHashAlgorithm = errors.New("unknown hash algorithm") var ErrUnknownHash = errors.New("unknown hash algorithm")
// ErrUnsupportedPayloadEncoding is returned when an unexpected value is // ErrUnsupportedPayloadEncoding is returned when an unexpected value is
// provided while decoding the payload encoding field. The allowed values // provided while decoding the payload encoding field. The allowed values

9
rsa.go
View File

@@ -13,13 +13,13 @@ var _ Varsig = RSAVarsig{}
// an RSA signature. // an RSA signature.
type RSAVarsig struct { type RSAVarsig struct {
varsig varsig
hashAlg HashAlgorithm hashAlg Hash
sigLen uint64 sigLen uint64
} }
// NewRSAVarsig creates and validates an RSA varsig with the provided // NewRSAVarsig creates and validates an RSA varsig with the provided
// hash algorithm, key length and payload encoding. // hash algorithm, key length and payload encoding.
func NewRSAVarsig(hashAlgorithm HashAlgorithm, keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) { func NewRSAVarsig(hashAlgorithm Hash, keyLength uint64, payloadEncoding PayloadEncoding, opts ...Option) (RSAVarsig, error) {
options := newOptions(opts...) options := newOptions(opts...)
var ( var (
@@ -57,8 +57,9 @@ func (v RSAVarsig) Encode() []byte {
return buf return buf
} }
// HashAlgorithm returns the hash algorithm used to has the payload content. // Hash returns the value describing the hash algorithm used to hash
func (v RSAVarsig) HashAlgorithm() HashAlgorithm { // the payload content before the signature is generated.
func (v RSAVarsig) Hash() Hash {
return v.hashAlg return v.hashAlg
} }

View File

@@ -31,7 +31,7 @@ func TestRSAVarsig(t *testing.T) {
assert.Equal(t, varsig.Version1, rsaVs.Version()) assert.Equal(t, varsig.Version1, rsaVs.Version())
assert.Equal(t, varsig.DiscriminatorRSA, rsaVs.Discriminator()) assert.Equal(t, varsig.DiscriminatorRSA, rsaVs.Discriminator())
assert.Equal(t, varsig.HashAlgorithmSHA256, rsaVs.HashAlgorithm()) assert.Equal(t, varsig.HashSha2_256, rsaVs.Hash())
assert.Equal(t, varsig.PayloadEncodingDAGCBOR, rsaVs.PayloadEncoding()) assert.Equal(t, varsig.PayloadEncodingDAGCBOR, rsaVs.PayloadEncoding())
assert.Equal(t, uint64(keyLen), rsaVs.KeyLength()) assert.Equal(t, uint64(keyLen), rsaVs.KeyLength())
assert.Len(t, rsaVs.Signature(), 0) assert.Len(t, rsaVs.Signature(), 0)
@@ -41,7 +41,7 @@ func TestRSAVarsig(t *testing.T) {
t.Parallel() t.Parallel()
rsaVarsig, err := varsig.NewRSAVarsig( rsaVarsig, err := varsig.NewRSAVarsig(
varsig.HashAlgorithmSHA256, varsig.HashSha2_256,
keyLen, keyLen,
varsig.PayloadEncodingDAGCBOR, varsig.PayloadEncodingDAGCBOR,
) )
@@ -74,7 +74,7 @@ func TestUCANExampleV0(t *testing.T) {
assert.Equal(t, varsig.Version0, rsaVs.Version()) assert.Equal(t, varsig.Version0, rsaVs.Version())
assert.Equal(t, varsig.DiscriminatorRSA, rsaVs.Discriminator()) assert.Equal(t, varsig.DiscriminatorRSA, rsaVs.Discriminator())
assert.Equal(t, varsig.HashAlgorithmSHA256, rsaVs.HashAlgorithm()) assert.Equal(t, varsig.HashSha2_256, rsaVs.Hash())
assert.Equal(t, varsig.PayloadEncodingDAGCBOR, rsaVs.PayloadEncoding()) assert.Equal(t, varsig.PayloadEncodingDAGCBOR, rsaVs.PayloadEncoding())
assert.Equal(t, uint64(keyLen), rsaVs.KeyLength()) assert.Equal(t, uint64(keyLen), rsaVs.KeyLength())
assert.Len(t, rsaVs.Signature(), 0) assert.Len(t, rsaVs.Signature(), 0)
@@ -84,7 +84,7 @@ func TestUCANExampleV0(t *testing.T) {
t.Parallel() t.Parallel()
rsaVarsig, err := varsig.NewRSAVarsig( rsaVarsig, err := varsig.NewRSAVarsig(
varsig.HashAlgorithmSHA256, varsig.HashSha2_256,
keyLen, keyLen,
varsig.PayloadEncodingDAGCBOR, varsig.PayloadEncodingDAGCBOR,
varsig.WithForceVersion0([]byte{}), varsig.WithForceVersion0([]byte{}),