Skip to content

Commit

Permalink
fix: handle all possible hash algorithms for signature verification (#12
Browse files Browse the repository at this point in the history
)

* debug: request data

* fix: log jsoned sod

* add: missing json import

* add: missing logan import

* fix: log data string

* debug: whole request

* fix: handle all possible hash algorithms for verifying signature

* fix: enable fix
  • Loading branch information
mhrynenko authored Jan 6, 2025
1 parent 6b015ba commit 08492d3
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
56 changes: 49 additions & 7 deletions internal/service/api/handlers/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
validation "github.com/go-ozzo/ozzo-validation/v4"
"github.com/google/jsonapi"
"github.com/iden3/go-iden3-crypto/poseidon"
"github.com/iden3/go-rapidsnark/verifier"
Expand All @@ -23,8 +24,6 @@ import (
"github.com/rarimo/passport-identity-provider/internal/utils"
"gitlab.com/distributed_lab/logan/v3"

validation "github.com/go-ozzo/ozzo-validation/v4"

"github.com/rarimo/certificate-transparency-go/x509"
"github.com/rarimo/passport-identity-provider/internal/service/api"
"github.com/rarimo/passport-identity-provider/internal/service/api/requests"
Expand All @@ -45,9 +44,10 @@ func Register(w http.ResponseWriter, r *http.Request) {
}

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{
Expand Down Expand Up @@ -350,7 +350,7 @@ func verifySod(
}
}

signedAttrHash, err := verifySignature(signature, cert, signedAttributes, *algorithmPair)
signedAttrHash, err := verifySignatureIterated(signature, cert, signedAttributes, *algorithmPair)
if err != nil {
unwrappedErr := errors2.Unwrap(err)
if errors2.Is(unwrappedErr, types.ErrInvalidPublicKey{}) {
Expand Down Expand Up @@ -481,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)

Expand All @@ -492,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,
Expand Down
6 changes: 3 additions & 3 deletions internal/types/enums.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const (
SHA512
)

var hashAlgorithmMap = map[string]HashAlgorithm{
var HashAlgorithmMap = map[string]HashAlgorithm{
"SHA1": SHA1,
"SHA224": SHA224,
"SHA256": SHA256,
Expand Down Expand Up @@ -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)
}
Expand All @@ -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
}

Expand Down
5 changes: 3 additions & 2 deletions internal/types/signature_algorithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down

0 comments on commit 08492d3

Please sign in to comment.