From 43a76eaad9dca8b58383c2dad29ddd7f6a3fcd1d Mon Sep 17 00:00:00 2001 From: Maksym Hrynenko Date: Mon, 6 Jan 2025 16:50:15 +0200 Subject: [PATCH] fix: handle all possible hash algorithms for verifying signature --- internal/service/api/handlers/register.go | 55 +++++++++++++++++++---- internal/types/enums.go | 6 +-- internal/types/signature_algorithm.go | 5 ++- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/internal/service/api/handlers/register.go b/internal/service/api/handlers/register.go index 129ee68..1c328ad 100644 --- a/internal/service/api/handlers/register.go +++ b/internal/service/api/handlers/register.go @@ -5,7 +5,6 @@ import ( "crypto/sha256" "encoding/asn1" "encoding/hex" - "encoding/json" "encoding/pem" errors3 "errors" "fmt" @@ -44,13 +43,11 @@ func Register(w http.ResponseWriter, r *http.Request) { return } - rawReq, _ := json.Marshal(req) - log.WithField("sod", string(rawReq)).Debug("request started") - algorithmPair := types.AlgorithmPair{ - DgHashAlgorithm: types.HashAlgorithmFromString(req.Data.Attributes.DocumentSod.HashAlgorithm), - SignedAttrHashAlg: types.HashAlgorithmFromString(req.Data.Attributes.DocumentSod.HashAlgorithm), - SignatureAlgorithm: types.SignatureAlgorithmFromString(req.Data.Attributes.DocumentSod.SignatureAlgorithm), + DgHashAlgorithm: types.HashAlgorithmFromString(req.Data.Attributes.DocumentSod.HashAlgorithm), + SignedAttrHashAlg: types.HashAlgorithmFromString(req.Data.Attributes.DocumentSod.HashAlgorithm), + SignatureDigestHashAlg: types.HashAlgorithmFromString(req.Data.Attributes.DocumentSod.HashAlgorithm), + SignatureAlgorithm: types.SignatureAlgorithmFromString(req.Data.Attributes.DocumentSod.SignatureAlgorithm), } documentSOD := data.DocumentSOD{ @@ -484,7 +481,7 @@ func verifySignature( signedAttributes []byte, algorithmPair types.AlgorithmPair, ) ([]byte, error) { - h := types.GeneralHash(algorithmPair.SignedAttrHashAlg) + h := types.GeneralHash(algorithmPair.SignatureDigestHashAlg) h.Write(signedAttributes) d := h.Sum(nil) @@ -495,6 +492,48 @@ func verifySignature( return d, nil } +func verifySignatureIterated( + signature []byte, + cert *x509.Certificate, + signedAttributes []byte, + algorithmPair types.AlgorithmPair, +) ([]byte, error) { + // Default flow to verify signature + errs := make([]error, 0, len(types.HashAlgorithmMap)) + digest, err := verifySignature(signature, cert, signedAttributes, algorithmPair) + if err == nil { + return digest, nil + } + + errs = append(errs, errors.From(err, logan.F{ + "hash_alg": algorithmPair.SignatureDigestHashAlg.String(), + "signature": algorithmPair.SignatureAlgorithm.String(), + })) + + // Workaround to handle signature digest hash algorithm different from specified in request + for name, algorithm := range types.HashAlgorithmMap { + if algorithm == algorithmPair.SignatureDigestHashAlg { + continue + } + + algo := algorithmPair + algo.SignatureDigestHashAlg = algorithm + digest, err = verifySignature(signature, cert, signedAttributes, algo) + if err == nil { + // TODO use logger + fmt.Printf("found suitable digest hash algorithm for signature %s instead %s\n", name, algorithmPair.SignatureDigestHashAlg.String()) + return digest, nil + } + + errs = append(errs, errors.From(err, logan.F{ + "hash_alg": name, + "signature": algorithmPair.SignatureAlgorithm.String(), + })) + } + + return nil, errors3.Join(errs...) +} + func validateCert(cert *x509.Certificate, masterCerts *x509.CertPool, disableTimeChecks, disableNameChecks bool) error { foundCerts, err := cert.Verify(x509.VerifyOptions{ Roots: masterCerts, diff --git a/internal/types/enums.go b/internal/types/enums.go index d1b23fb..f463e90 100644 --- a/internal/types/enums.go +++ b/internal/types/enums.go @@ -12,7 +12,7 @@ const ( SHA512 ) -var hashAlgorithmMap = map[string]HashAlgorithm{ +var HashAlgorithmMap = map[string]HashAlgorithm{ "SHA1": SHA1, "SHA224": SHA224, "SHA256": SHA256, @@ -46,7 +46,7 @@ func (h HashAlgorithm) String() string { } func HashAlgorithmFromString(alg string) HashAlgorithm { - h, ok := hashAlgorithmMap[strings.ToUpper(alg)] + h, ok := HashAlgorithmMap[strings.ToUpper(alg)] if !ok { return HashAlgorithm(0) } @@ -62,7 +62,7 @@ func HashAlgorithmFromSize(size int) HashAlgorithm { } func IsValidHashAlgorithm(alg string) (HashAlgorithm, bool) { - h, ok := hashAlgorithmMap[alg] + h, ok := HashAlgorithmMap[alg] return h, ok } diff --git a/internal/types/signature_algorithm.go b/internal/types/signature_algorithm.go index 3cd4fcd..c2af57f 100644 --- a/internal/types/signature_algorithm.go +++ b/internal/types/signature_algorithm.go @@ -21,8 +21,9 @@ func (e ErrInvalidPublicKey) Error() string { // AlgorithmPair defines a hash and signature algorithm combination. type AlgorithmPair struct { - DgHashAlgorithm HashAlgorithm - SignedAttrHashAlg HashAlgorithm + DgHashAlgorithm HashAlgorithm + SignedAttrHashAlg HashAlgorithm + SignatureDigestHashAlg HashAlgorithm SignatureAlgorithm }