Skip to main content

SignedData

EIP-191 signed data primitive implementing the Ethereum Signed Message standard. Provides type-safe message signing and verification following the EIP-191 specification.

Overview

EIP-191 defines a standard format for signed data with three versions:
  • 0x00: Data with validator (contract address)
  • 0x01: Structured data (EIP-712)
  • 0x45: Personal message (most common)

Installation

npm install @tevm/primitives

Basic Usage

Personal Message Signing

import * as SignedData from '@tevm/primitives/SignedData';
import { hash as keccak256 } from '@tevm/crypto/keccak256';
import { recoverPublicKey } from '@tevm/crypto/Secp256k1';
import { fromPublicKey } from '@tevm/primitives/Address';

// Create hash factory
const hash = SignedData.Hash({ keccak256 });

// Hash a personal message
const message = "Hello, Ethereum!";
const messageHash = hash(message);

// Verify signature
const verify = SignedData.Verify({
  keccak256,
  recoverPublicKey,
  addressFromPublicKey: fromPublicKey
});

const isValid = verify(message, signature, signerAddress);

Create Signed Data

import * as SignedData from '@tevm/primitives/SignedData';

// Personal message (0x45)
const signedData = SignedData.from(
  SignedData.VERSION_PERSONAL_MESSAGE,
  new Uint8Array(0),
  new TextEncoder().encode("Hello, Ethereum!")
);

// Data with validator (0x00)
const validatorAddress = new Uint8Array(20).fill(0x42);
const signedDataWithValidator = SignedData.from(
  SignedData.VERSION_DATA_WITH_VALIDATOR,
  validatorAddress,
  messageData
);

API Reference

Types

SignedDataType

Branded Uint8Array representing EIP-191 signed data.
type SignedDataType = Uint8Array & {
  readonly __tag: "SignedData";
};

SignedDataVersion

EIP-191 version bytes:
type SignedDataVersion =
  | 0x00  // Data with validator
  | 0x01  // Structured data (EIP-712)
  | 0x45; // Personal message

Functions

from(version, versionData, data)

Create EIP-191 signed data from components. Parameters:
  • version: Version byte (0x00, 0x01, or 0x45)
  • versionData: Version-specific data (validator address or domain separator)
  • data: Message data
Returns: SignedDataType Example:
const signedData = SignedData.from(
  SignedData.VERSION_PERSONAL_MESSAGE,
  new Uint8Array(0),
  new TextEncoder().encode("message")
);

Hash({ keccak256 })

Factory function that creates a personal message hash function. Parameters:
  • keccak256: Keccak256 hash function
Returns: Function that hashes messages with EIP-191 format Example:
const hash = SignedData.Hash({ keccak256 });
const messageHash = hash("Hello, Ethereum!");

Verify({ keccak256, recoverPublicKey, addressFromPublicKey })

Factory function that creates a signature verification function. Parameters:
  • keccak256: Keccak256 hash function
  • recoverPublicKey: secp256k1 public key recovery function
  • addressFromPublicKey: Address derivation function
Returns: Function that verifies signatures Example:
const verify = SignedData.Verify({
  keccak256,
  recoverPublicKey,
  addressFromPublicKey: fromPublicKey
});

const isValid = verify(message, signature, expectedAddress);

Constants

VERSION_DATA_WITH_VALIDATOR = 0x00;
VERSION_STRUCTURED_DATA = 0x01;
VERSION_PERSONAL_MESSAGE = 0x45;
EIP191_PREFIX = 0x19;
PERSONAL_MESSAGE_PREFIX = "\x19Ethereum Signed Message:\n";

EIP-191 Format

Personal Message (0x45)

The most common format used by wallets:
"\x19Ethereum Signed Message:\n" + len(message) + message
Hashed with keccak256 before signing.

Data with Validator (0x00)

For contract-validated signatures:
0x19 0x00 <validator address (20 bytes)> <data>

Structured Data (0x01)

For EIP-712 typed data:
0x19 0x01 <domainSeparator (32 bytes)> <hashStruct(message)>

Error Handling

import {
  InvalidSignedDataVersionError,
  InvalidSignedDataFormatError,
  SignatureVerificationError
} from '@tevm/primitives/SignedData';

try {
  const signedData = SignedData.from(0x99, data, message);
} catch (error) {
  if (error instanceof InvalidSignedDataVersionError) {
    console.error("Invalid version byte");
  }
}

See Also

  • Address - Ethereum address handling
  • Hash - Keccak256 hashing