Skip to content

feat(identity): add secp256k1 identity type and EIP-712 endorsement envelope - #1685

Closed
Rama542 wants to merge 2 commits into
LFDT-Panurus:mainfrom
Rama542:feat/secp256k1-eip712-identity
Closed

feat(identity): add secp256k1 identity type and EIP-712 endorsement envelope#1685
Rama542 wants to merge 2 commits into
LFDT-Panurus:mainfrom
Rama542:feat/secp256k1-eip712-identity

Conversation

@Rama542

@Rama542 Rama542 commented May 7, 2026

Copy link
Copy Markdown
Contributor

Closes #1667

This PR adds the secp256k1 identity primitives needed by the Ethereum/EVM driver. Ethereum accounts are 20-byte addresses derived from secp256k1 public keys, and co-signers approve token operations off-chain by signing EIP-712 typed-data digests before the transaction is submitted to the ledger.

What changed:

A new package token/services/identity/eth is introduced with three source files:

signer.go wraps a secp256k1 private key. Sign keccak256-hashes the caller-supplied message and returns a DER-encoded ECDSA signature, which matches the Ethereum signing convention used by eth_sign and EIP-712.

verifier.go wraps a secp256k1 public key. Verify parses the DER signature, keccak256-hashes the message, and checks the result against the stored key. AddressFromPublicKey derives the standard 20-byte Ethereum address from any secp256k1 public key (keccak256 of the uncompressed key X||Y bytes, taking the last 20 bytes of the hash).

eip712.go defines the Domain and EndorsementRequest typed-data structs and HashEndorsementRequest, which builds the full EIP-712 digest: keccak256(0x1901 || domainSeparator || structHash). The domain separator and struct hash follow the EIP-712 spec exactly, with string fields hashed via keccak256 and uint64 fields ABI-encoded as 32-byte big-endian values.

Two existing files are also updated:

token/driver/wallet.go registers Secp256k1IdentityType (= 7) and Secp256k1IdentityTypeString ("secp256k1") alongside the existing identity type constants.

token/services/identity/typed.go extends TypeToString to return the correct label for the new type.

No new module dependencies are introduced. Keccak-256 is provided by golang.org/x/crypto/sha3 (already a direct dependency) and secp256k1 signing by github.com/decred/dcrd/dcrec/secp256k1/v4 (already an indirect dependency).

Testing:

eth_test.go contains 14 unit tests:

  • Sign/verify round-trip with a fresh key pair
  • Wrong message and wrong key rejection
  • Nil key error paths for both signer and verifier
  • Malformed (non-DER) signature rejection
  • Address derivation: determinism, uniqueness across keys, 20-byte length
  • EIP-712 hash determinism and sensitivity to TxID, domain ChainID, and Deadline fields
  • End-to-end endorse-and-verify flow using HashEndorsementRequest plus Signer and Verifier

All 14 tests pass.

Rama542 added 2 commits May 7, 2026 21:00
…nvelope

Adds the foundational secp256k1 identity primitives needed by the
Ethereum/EVM driver.  Ethereum accounts are identified by a 20-byte
address derived from a secp256k1 public key, and off-chain co-signers
approve token operations by signing an EIP-712 typed-data digest.

Changes:

- token/driver/wallet.go: register Secp256k1IdentityType (= 7) and
  Secp256k1IdentityTypeString ("secp256k1") alongside the existing
  identity type constants so the rest of the SDK can reference the
  new type without importing the eth package.

- token/services/identity/typed.go: extend TypeToString to return
  the correct label for Secp256k1IdentityType.

- token/services/identity/eth/signer.go: Signer wraps a secp256k1
  private key.  Sign keccak256-hashes the message then returns a
  DER-encoded ECDSA signature, matching the Ethereum eth_sign and
  EIP-712 conventions.

- token/services/identity/eth/verifier.go: Verifier wraps a
  secp256k1 public key.  Verify parses the DER signature,
  keccak256-hashes the message, and checks the result.
  AddressFromPublicKey derives the standard 20-byte Ethereum address
  from the public key (keccak256 of X||Y bytes, last 20 bytes).

- token/services/identity/eth/eip712.go: Domain and
  EndorsementRequest typed-data structs plus HashEndorsementRequest,
  which computes the full EIP-712 digest
  keccak256(0x1901 || domainSeparator || structHash).  Uses the
  pre-standardisation Keccak-256 variant that Ethereum adopted, via
  golang.org/x/crypto/sha3.NewLegacyKeccak256 (already a direct
  dependency).  secp256k1 signing is provided by
  github.com/decred/dcrd/dcrec/secp256k1/v4 (already an indirect
  dependency), so no new modules are introduced.

- token/services/identity/eth/eth_test.go: 14 unit tests covering
  sign/verify round-trip, wrong-message and wrong-key rejection, nil
  key error paths, malformed signature rejection, address derivation
  properties, EIP-712 hash determinism and field sensitivity, and a
  full end-to-end endorse-and-verify flow.

Closes LFDT-Panurus#1667

Signed-off-by: Rama542 <ramasasankgudipati@gmail.com>
Signed-off-by: Rama542 <Rama542@users.noreply.github.com>
Signed-off-by: Rama542 <ramasasankgudipati@gmail.com>
Signed-off-by: Rama542 <Rama542@users.noreply.github.com>
@Rama542 Rama542 closed this May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ethereum driver: secp256k1 identities and EIP-712 endorsement envelope

2 participants