From 709a2a74e31eb79c208a12fabee2a253e3e0db0c Mon Sep 17 00:00:00 2001 From: Matee Ullah Malik Date: Wed, 29 Oct 2025 18:17:23 +0500 Subject: [PATCH] Use ADR36 signautres --- sdk/action/client.go | 6 ++++-- sdk/task/helpers.go | 35 ++++++++++++++++++++--------------- supernode/cascade/download.go | 19 ++++++++++++++++--- supernode/cascade/helper.go | 34 ++++++++++++++++++++++++++++++---- 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/sdk/action/client.go b/sdk/action/client.go index d5fdf410..81aa806b 100644 --- a/sdk/action/client.go +++ b/sdk/action/client.go @@ -318,13 +318,15 @@ func (c *ClientImpl) BuildCascadeMetadataFromFile(ctx context.Context, filePath // GenerateStartCascadeSignatureFromFile computes blake3(file) and signs it with the configured key. // Returns base64-encoded signature suitable for StartCascade. func (c *ClientImpl) GenerateStartCascadeSignatureFromFile(ctx context.Context, filePath string) (string, error) { + // Compute blake3(file), encode as base64 string, and sign the string bytes h, err := utils.Blake3HashFile(filePath) if err != nil { return "", fmt.Errorf("blake3: %w", err) } - sig, err := keyringpkg.SignBytes(c.keyring, c.config.Account.KeyName, h) + dataHashB64 := base64.StdEncoding.EncodeToString(h) + sig, err := keyringpkg.SignBytes(c.keyring, c.config.Account.KeyName, []byte(dataHashB64)) if err != nil { - return "", fmt.Errorf("sign hash: %w", err) + return "", fmt.Errorf("sign hash string: %w", err) } return base64.StdEncoding.EncodeToString(sig), nil } diff --git a/sdk/task/helpers.go b/sdk/task/helpers.go index 2e9ee4c3..c1a059d2 100644 --- a/sdk/task/helpers.go +++ b/sdk/task/helpers.go @@ -8,6 +8,7 @@ import ( "os" "sort" + actionkeeper "github.com/LumeraProtocol/lumera/x/action/v1/keeper" "github.com/LumeraProtocol/supernode/v2/pkg/utils" "github.com/LumeraProtocol/supernode/v2/sdk/adapters/lumera" ) @@ -74,28 +75,32 @@ func (m *ManagerImpl) validateSignature(ctx context.Context, action lumera.Actio return fmt.Errorf("failed to decode cascade metadata: %w", err) } - // Extract the base64-encoded data hash from the metadata - base64EnTcketDataHash := cascadeMetaData.DataHash + // Extract the base64-encoded data hash string from the metadata + dataHashB64 := cascadeMetaData.DataHash - // Decode the data hash from base64 to raw bytes - dataHashBytes, err := base64.StdEncoding.DecodeString(base64EnTcketDataHash) + // Decode the provided signature from base64 to raw bytes and coerce to r||s + signatureRaw, err := base64.StdEncoding.DecodeString(signature) if err != nil { - return fmt.Errorf("failed to decode data hash: %w", err) + return fmt.Errorf("failed to decode signature: %w", err) } - - // Decode the provided signature from base64 to raw bytes - signatureBytes, err := base64.StdEncoding.DecodeString(signature) + sigRS, err := actionkeeper.CoerceToRS64(signatureRaw) if err != nil { - return fmt.Errorf("failed to decode signature: %w", err) + return fmt.Errorf("coerce signature: %w", err) } - // Verify the signature using the Lumera client - // This checks if the signature was produced by the action creator - // for the given data hash - err = m.lumeraClient.VerifySignature(ctx, action.Creator, dataHashBytes, signatureBytes) + // Try raw verification over []byte(dataHashB64). If it fails, try ADR-36 bytes. + err = m.lumeraClient.VerifySignature(ctx, action.Creator, []byte(dataHashB64), sigRS) if err != nil { - m.logger.Error(ctx, "Signature validation failed", "actionID", action.ID, "error", err) - return fmt.Errorf("signature validation failed: %w", err) + // ADR-36 fallback: sign doc with data = base64(dataHashB64) + doc, derr := actionkeeper.MakeADR36AminoSignBytes(action.Creator, base64.StdEncoding.EncodeToString([]byte(dataHashB64))) + if derr != nil { + m.logger.Error(ctx, "ADR36 doc build failed", "actionID", action.ID, "error", derr) + return fmt.Errorf("signature validation failed: %w", err) + } + if err2 := m.lumeraClient.VerifySignature(ctx, action.Creator, doc, sigRS); err2 != nil { + m.logger.Error(ctx, "Signature validation failed", "actionID", action.ID, "error", err) + return fmt.Errorf("signature validation failed: %w", err) + } } return nil diff --git a/supernode/cascade/download.go b/supernode/cascade/download.go index 944e7d84..bed86d14 100644 --- a/supernode/cascade/download.go +++ b/supernode/cascade/download.go @@ -9,6 +9,7 @@ import ( "sort" "time" + actionkeeper "github.com/LumeraProtocol/lumera/x/action/v1/keeper" actiontypes "github.com/LumeraProtocol/lumera/x/action/v1/types" "github.com/LumeraProtocol/supernode/v2/pkg/cascadekit" "github.com/LumeraProtocol/supernode/v2/pkg/codec" @@ -117,12 +118,24 @@ func (task *CascadeRegistrationTask) VerifyDownloadSignature(ctx context.Context return fmt.Errorf("get action for signature verification: %w", err) } creator := act.GetAction().Creator - sigBytes, err := base64.StdEncoding.DecodeString(signature) + sigRaw, err := base64.StdEncoding.DecodeString(signature) if err != nil { return fmt.Errorf("invalid base64 signature: %w", err) } - if err := task.LumeraClient.Verify(ctx, creator, []byte(actionID), sigBytes); err != nil { - return err + sigRS, err := actionkeeper.CoerceToRS64(sigRaw) + if err != nil { + return fmt.Errorf("coerce signature: %w", err) + } + if err := task.LumeraClient.Verify(ctx, creator, []byte(actionID), sigRS); err != nil { + // Fallback to ADR-36 sign-bytes verification over base64(actionID) + dataB64 := base64.StdEncoding.EncodeToString([]byte(actionID)) + doc, derr := actionkeeper.MakeADR36AminoSignBytes(creator, dataB64) + if derr != nil { + return fmt.Errorf("build adr36 doc: %w", derr) + } + if err2 := task.LumeraClient.Verify(ctx, creator, doc, sigRS); err2 != nil { + return err + } } return nil } diff --git a/supernode/cascade/helper.go b/supernode/cascade/helper.go index 2d204c52..07e825fe 100644 --- a/supernode/cascade/helper.go +++ b/supernode/cascade/helper.go @@ -6,6 +6,7 @@ import ( "strconv" "cosmossdk.io/math" + actionkeeper "github.com/LumeraProtocol/lumera/x/action/v1/keeper" actiontypes "github.com/LumeraProtocol/lumera/x/action/v1/types" "github.com/LumeraProtocol/supernode/v2/pkg/cascadekit" "github.com/LumeraProtocol/supernode/v2/pkg/codec" @@ -87,13 +88,26 @@ func (task *CascadeRegistrationTask) validateIndexAndLayout(ctx context.Context, if err != nil { return cascadekit.IndexFile{}, nil, err } - creatorSig, err := base64.StdEncoding.DecodeString(creatorSigB64) + creatorSigRaw, err := base64.StdEncoding.DecodeString(creatorSigB64) if err != nil { return cascadekit.IndexFile{}, nil, err } - if err := task.LumeraClient.Verify(ctx, creator, []byte(indexB64), creatorSig); err != nil { + // Coerce signature to r||s then try raw -> ADR36 + sigRS, err := actionkeeper.CoerceToRS64(creatorSigRaw) + if err != nil { return cascadekit.IndexFile{}, nil, err } + if err := task.LumeraClient.Verify(ctx, creator, []byte(indexB64), sigRS); err != nil { + // Fallback to ADR-36 verification + dataB64 := base64.StdEncoding.EncodeToString([]byte(indexB64)) + signDoc, derr := actionkeeper.MakeADR36AminoSignBytes(creator, dataB64) + if derr != nil { + return cascadekit.IndexFile{}, nil, derr + } + if err2 := task.LumeraClient.Verify(ctx, creator, signDoc, sigRS); err2 != nil { + return cascadekit.IndexFile{}, nil, err + } + } // Decode index indexFile, err := cascadekit.DecodeIndexB64(indexB64) if err != nil { @@ -107,13 +121,25 @@ func (task *CascadeRegistrationTask) validateIndexAndLayout(ctx context.Context, if err := cascadekit.VerifySingleBlock(layout); err != nil { return cascadekit.IndexFile{}, nil, err } - layoutSig, err := base64.StdEncoding.DecodeString(indexFile.LayoutSignature) + layoutSigRaw, err := base64.StdEncoding.DecodeString(indexFile.LayoutSignature) if err != nil { return cascadekit.IndexFile{}, nil, err } - if err := task.LumeraClient.Verify(ctx, creator, layoutB64, layoutSig); err != nil { + layoutSigRS, err := actionkeeper.CoerceToRS64(layoutSigRaw) + if err != nil { return cascadekit.IndexFile{}, nil, err } + if err := task.LumeraClient.Verify(ctx, creator, layoutB64, layoutSigRS); err != nil { + // Fallback to ADR-36 verification over string(layoutB64) + dataB64 := base64.StdEncoding.EncodeToString([]byte(string(layoutB64))) + signDoc, derr := actionkeeper.MakeADR36AminoSignBytes(creator, dataB64) + if derr != nil { + return cascadekit.IndexFile{}, nil, derr + } + if err2 := task.LumeraClient.Verify(ctx, creator, signDoc, layoutSigRS); err2 != nil { + return cascadekit.IndexFile{}, nil, err + } + } return indexFile, layoutB64, nil }