Sign Message

To let the user sign an arbitrary message with any of their addresses, you can call signMessage() with the following request object. If you do not include a signer property, the user will be prompted to select an address from their available accounts. The message can be either a string or a Uint8Array byte array.

Table of Contents

  1. Request
  2. Options
  3. Result
  4. Prefixing and Hashing
  5. Verification

Request

Result: -

const options = {
  appName: 'Hub API Docs',
  message: 'I like the Nimiq Hub API!',
  // See more options in the table below
};

// All client requests are async and return a promise
const signedMessage = await hubApi.signMessage(options);

Options

(On mobile, scroll right to see the whole table.)

Option Type Required? Description
appName string yes The name of your app, should be as short as possible.
message string or Uint8Array yes The message to sign. Can either be string of valid UTF-8 characters or a byte array to sign arbitrary data.
signer string no The human-readable address with which to sign. When not passed, an address selector will be displayed to the user.

Result

The method returns a SignedMessage object containing the following properties:

interface SignedMessage {
    signer: string;               // Userfriendly address
    signerPublicKey: Uint8Array;  // The public key of the signer
    signature: Uint8Array;        // Signature for the message
}

Prefixing and Hashing

To prevent users from signing valid transactions or other blockchain-related proofs which could be used to impersonate them, the Nimiq Keyguard prefixes additional data to the message before signing. This prefix consists of

This data is then hashed with SHA256 before being signed. Together, this leads to the following data structure:

sign( sha256( '\x16Nimiq Signed Message:\n' + message.length + message ) );

Verification

Verifying a signed message with the Nimiq Core library could go like this:

const signature = new Nimiq.Signature(signedMessage.signature);
const publicKey = new Nimiq.PublicKey(signedMessage.signerPublicKey);

// For string messages:
const data = HubApi.MSG_PREFIX
           + message.length
           + message;
const dataBytes = Nimiq.BufferUtils.fromUtf8(data);
const hash = Nimiq.Hash.computeSha256(dataBytes);

// Check signature against the hashed message
const isValid = signature.verify(publicKey, hash);