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
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
@@ -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
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
@@ -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
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
@@ -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
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
@@ -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
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()
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) {
t.Helper()
assert.Equal(t, in.HashAlgorithm(), out.HashAlgorithm())
assert.Equal(t, in.Hash(), out.Hash())
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.
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
type HashAlgorithm uint64
type Hash uint64
// Constant values that allow Varsig implementations to specify how
// the payload content is hashed before the signature is generated.
const (
HashAlgorithmUnspecified HashAlgorithm = 0x00
HashAlgorithmSHA256 = HashAlgorithm(0x12)
HashAlgorithmSHA384 = HashAlgorithm(0x20)
HashAlgorithmSHA512 = HashAlgorithm(0x13)
HashAlgorithmShake256 = HashAlgorithm(0x19)
HashUnspecified Hash = 0x00
HashSha2_224 = Hash(0x1013)
HashSha2_256 = Hash(0x12)
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
// (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)
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 {
case HashAlgorithmSHA256,
HashAlgorithmSHA384,
HashAlgorithmSHA512,
HashAlgorithmShake256:
case HashSha2_224,
HashSha2_256,
HashSha2_384,
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
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}))
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.Parallel()
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.Equal(t, varsig.HashAlgorithmUnspecified, hashAlg)
require.Equal(t, varsig.HashUnspecified, hashAlg)
})
t.Run("fails - unknown hash algorithm", func(t *testing.T) {
t.Parallel()
hashAlg, err := varsig.DecodeHashAlgorithm(bytes.NewReader([]byte{0x42}))
require.ErrorIs(t, err, varsig.ErrUnknownHashAlgorithm)
require.Equal(t, varsig.HashAlgorithmUnspecified, hashAlg)
require.ErrorIs(t, err, varsig.ErrUnknownHash)
require.Equal(t, varsig.HashUnspecified, hashAlg)
})
}

View File

@@ -46,12 +46,12 @@ type EdDSAVarsig struct {
varsig
curve EdDSACurve
hashAlg HashAlgorithm
hashAlg Hash
}
// NewEdDSAVarsig creates and validates an EdDSA varsig with the provided
// 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...)
var (
@@ -85,9 +85,9 @@ func (v EdDSAVarsig) Curve() EdDSACurve {
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.
func (v EdDSAVarsig) HashAlgorithm() HashAlgorithm {
func (v EdDSAVarsig) Hash() Hash {
return v.hashAlg
}

View File

@@ -39,7 +39,7 @@ func TestDecodeEd25519(t *testing.T) {
impl, ok := v.(varsig.EdDSAVarsig)
require.True(t, ok)
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) {
@@ -47,7 +47,7 @@ func TestDecodeEd25519(t *testing.T) {
v, err := varsig.NewEdDSAVarsig(
varsig.CurveEd25519,
varsig.HashAlgorithmSHA512,
varsig.HashSha2_512,
varsig.PayloadEncodingDAGCBOR,
varsig.WithForceVersion0(sig),
)
@@ -79,7 +79,7 @@ func TestUCANExampleV1(t *testing.T) {
assert.Equal(t, varsig.Version1, ed25519V.Version())
assert.Equal(t, varsig.DiscriminatorEdDSA, ed25519V.Discriminator())
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.Len(t, ed25519V.Signature(), 0)
})
@@ -89,7 +89,7 @@ func TestUCANExampleV1(t *testing.T) {
edDSAVarsig, err := varsig.NewEdDSAVarsig(
varsig.CurveEd25519,
varsig.HashAlgorithmSHA512,
varsig.HashSha2_512,
varsig.PayloadEncodingDAGCBOR,
)
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.
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.
var ErrUnknownHashAlgorithm = errors.New("unknown hash algorithm")
var ErrUnknownHash = errors.New("unknown hash algorithm")
// ErrUnsupportedPayloadEncoding is returned when an unexpected value is
// 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.
type RSAVarsig struct {
varsig
hashAlg HashAlgorithm
hashAlg Hash
sigLen uint64
}
// NewRSAVarsig creates and validates an RSA varsig with the provided
// 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...)
var (
@@ -57,8 +57,9 @@ func (v RSAVarsig) Encode() []byte {
return buf
}
// HashAlgorithm returns the hash algorithm used to has the payload content.
func (v RSAVarsig) HashAlgorithm() HashAlgorithm {
// Hash returns the value describing the hash algorithm used to hash
// the payload content before the signature is generated.
func (v RSAVarsig) Hash() Hash {
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.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, uint64(keyLen), rsaVs.KeyLength())
assert.Len(t, rsaVs.Signature(), 0)
@@ -41,7 +41,7 @@ func TestRSAVarsig(t *testing.T) {
t.Parallel()
rsaVarsig, err := varsig.NewRSAVarsig(
varsig.HashAlgorithmSHA256,
varsig.HashSha2_256,
keyLen,
varsig.PayloadEncodingDAGCBOR,
)
@@ -74,7 +74,7 @@ func TestUCANExampleV0(t *testing.T) {
assert.Equal(t, varsig.Version0, rsaVs.Version())
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, uint64(keyLen), rsaVs.KeyLength())
assert.Len(t, rsaVs.Signature(), 0)
@@ -84,7 +84,7 @@ func TestUCANExampleV0(t *testing.T) {
t.Parallel()
rsaVarsig, err := varsig.NewRSAVarsig(
varsig.HashAlgorithmSHA256,
varsig.HashSha2_256,
keyLen,
varsig.PayloadEncodingDAGCBOR,
varsig.WithForceVersion0([]byte{}),