Used to check for browser translation.
用于检测浏览器翻译。
ブラウザの翻訳を検出する
Claims Reference

Signature Claim


A Signature Claim is used to request a digital signature from the user's wallet. This is a fundamental operation for proving control over a Decentralized Identifier (DID). It can be used for various purposes, from signing a simple message to confirm an action, to authorizing a complex on-chain transaction.

DID Connect supports signing different types of data, including plain text, HTML, and pre-formatted blockchain transactions.

Request Flow#

The process of requesting and verifying a signature involves a clear sequence of interactions between your application, the DID Connect SDK, and the user's wallet.


Claim Parameters#

When defining a signature claim, you can specify several parameters to control the signing process and the user experience in the wallet.

Parameter

Type

Description

typeUrl

string

Required. Specifies the MIME type of the data to be signed. Common values include mime:text/plain, mime:text/html, and fg:t:transaction for blockchain transactions.

origin

string

The raw data to be signed, encoded in Base58. Either origin or digest must be provided.

digest

string

A pre-computed hash of the data to be signed, encoded in Base58. This is useful for large data payloads where only the hash needs to be sent to the wallet.

method

string

The hashing algorithm the wallet should apply to the origin data before signing. Defaults to sha3. Set to none to sign the origin data directly without hashing.

display

string

A JSON string containing { type, content } to provide a rich display of the signing request in the wallet.

description

string

A human-readable message explaining why the signature is being requested.

nonce

string

A unique value (e.g., a timestamp or random string) to prevent replay attacks.

requirement

object

An object specifying token or asset requirements the user must meet to be able to sign. See the Prepare Transaction Claim for details.

Requesting a Signature#

You can request various types of signatures depending on your application's needs.

Example 1: Signing a Plain Text Message#

This is the most common use case, often used to verify user identity or consent.

// From: ocap-playground/api/routes/auth/claim-signature.js

const { toBase58 } = require('@ocap/util');
const { getRandomMessage } = require('../../libs/util');

const claims = {
signature: {
typeUrl: 'mime:text/plain',
origin: toBase58(Buffer.from(getRandomMessage())), // Data must be Base58 encoded
description: 'Please sign this message to log in.',
},
};

Example 2: Signing a Transaction#

For on-chain operations, you can construct a transaction, encode it, and ask the user to sign it. The origin field should contain the Base58-encoded transaction buffer.

// From: ocap-playground/api/routes/auth/claim-signature.js

const { toBase58 } = require('@ocap/util');
const { fromPublicKey } = require('@ocap/wallet');
const { client, wallet } = require('../../libs/auth');
const env = require('../../libs/env');

// This function runs on the server to prepare the claim
const createTxSignatureClaim = async ({ userPk }) => {
const encoded = await client.encodeTransferV2Tx({
tx: {
itx: {
to: wallet.address, // The application's address
tokens: [
{
address: env.localTokenId,
value: (await client.fromTokenToUnit(1)).toString(),
},
],
},
},
wallet: fromPublicKey(userPk),
});

const origin = toBase58(encoded.buffer);

return {
typeUrl: 'fg:t:transaction',
description: 'Please sign to confirm the transfer of 1 TKN.',
origin: origin,
};
};

Example 3: Signing with a Nonce#

To prevent replay attacks, especially for authentication, include a nonce. The nonce should be unique for each session or request.

// From: ocap-playground/api/routes/auth/claim-signature.js

const { toBase58 } = require('@ocap/util');

const claims = {
signature: () => {
const date = new Date();
return {
typeUrl: 'mime:text/plain',
origin: toBase58(Buffer.from('Login request')),
nonce: [date.getFullYear(), date.getMonth() + 1, date.getDate(), date.getHours()].join('-'),
description: `Please sign in for ${date.toDateString()}`,
};
},
};

Handling the Wallet Response#

After the user signs the data, the onAuth callback on your server will receive the claim result, which now includes the signature.

Response Structure#

The claims array in the onAuth callback will contain an object for the signature claim with these additional fields:

Field

Type

Description

sig

string

The Base58-encoded signature generated by the user's wallet.

method

string

The hash method used by the wallet before signing. Matches the request.

origin / digest

string

The original data or digest that was signed.

Verifying the Signature#

It is critical to verify the signature on your backend to confirm the user's identity and the integrity of the data. Use the user's public key (userPk) provided in the onAuth callback.

// From: ocap-playground/api/routes/auth/claim-signature.js

const { toTypeInfo } = require('@arcblock/did');
const { fromPublicKey } = require('@ocap/wallet');

const onAuth = async ({ userDid, userPk, claims }) => {
const type = toTypeInfo(userDid);
const userWallet = fromPublicKey(userPk, type);
const signatureClaim = claims.find(x => x.type === 'signature');

let isValid = false;

// If you sent 'origin' data
if (signatureClaim.origin) {
// The third argument indicates whether the data was hashed before signing.
// It should match the 'method' field. 'none' means it was not hashed.
isValid = await userWallet.verify(signatureClaim.origin, signatureClaim.sig, signatureClaim.method !== 'none');
}
// If you sent a 'digest'
else if (signatureClaim.digest) {
// When verifying a digest, the data was already hashed, so the third argument must be false.
isValid = await userWallet.verify(signatureClaim.digest, signatureClaim.sig, false);
}

if (!isValid) {
throw new Error('Signature verification failed.');
}

console.log('Signature is valid!');

// If it was a transaction, you can now broadcast it
if (signatureClaim.meta && signatureClaim.meta.origin) {
const tx = client.decodeTx(signatureClaim.meta.origin);
const hash = await client.sendTransferV2Tx({
tx,
wallet: userWallet,
signature: signatureClaim.sig,
});
console.log('Transaction sent, hash:', hash);
return { hash };
}
};

This onAuth handler demonstrates the complete verification flow. It checks for either origin or digest in the response and uses the appropriate verification logic. If the signature is valid, the application can proceed with the intended action, such as logging the user in or broadcasting a transaction.


Next, learn how to request the wallet to assemble and sign a transaction when you only have partial information.

Next Step: Prepare Transaction Claim