Allekirjoita viestejä ja todenna käyttäjiä

Viestin allekirjoittaminen todistaa, että käyttäjä hallitsee lompakkoa – ilman transaktiota, maksua tai verkkokutsua. Sovellukset käyttävät allekirjoitettuja viestejä käyttäjien kirjaamiseen sisään, käyttäjän hyväksymien ehtojen tallentamiseen, lompakon yhdistämiseen olemassa olevaan tiliin tai off-chain-toiminnon, kuten tilauksen tekemisen, valtuuttamiseen.

Solana-lompakot allekirjoittavat viestejä kahdella tavalla:

  • Off-chain-viestit (solana:signOffchainMessage) paketoivat tekstisi vakiomuotoon, jonka määrittelee off-chain-viestien allekirjoitusta (OCMS) koskeva spesifikaatio. Muotoa ei voi koskaan sekoittaa transaktioon, se nimeää tilit, joiden on allekirjoitettava viesti, ja laitelompakot allekirjoittavat nimenomaan tämän muodon.
  • Raakaviestit (solana:signMessage) allekirjoittavat täsmälleen ne tavut, jotka sovelluksesi välittää, ilman etuliitettä ja ilman ilmoitettuja allekirjoittajia. Useimmat ohjelmistolompakot tukevat niitä, mutta tavuista ei voi päätellä, että kyseessä on viesti eikä transaktio.

Käytä off-chain-viestejä, kun lompakko tukee niitä, ja palaa raakaviesteihin, kun se ei tue. Tämä opas käyttää esimerkkinä sisäänkirjautumista, mutta samat allekirjoitus- ja varmennusvaiheet pätevät mihin tahansa viestiin.

Valitse viestin muoto

Off-chain-viestiRaakaviestiTransaktio
Lompakon ominaisuussignOffchainMessagesignMessagesignTransaction
Laitelompakon tukiRiippuu laitteestaEiKyllä
Käyttäjän luettavissaKylläVain ohjelmistolompakoissaRiippuu laitteesta
Ilmoittaa vaadittavat allekirjoittajatKylläEiKyllä
RPC-kutsut ja maksutEi mitäänEi mitäänBlockhash, lähetys, maksu, vahvistus

Miksei transaktiota?

Laitelompakoilla ei aiemmin voinut allekirjoittaa luettavaa viestiä. Monet sovellukset turvautuivat pyytämään näitä käyttäjiä allekirjoittamaan tyhjän transaktion. Se toimii, mutta lisää viivettä, kustannuksia ja riskejä:

  • Verkkomaksut. Transaktiosta maksetaan maksu, vaikka se ei tekisi mitään.
  • Useita RPC-kutsuja. Sovelluksesi hakee blockhashin, simuloi, lähettää ja kyselee sen jälkeen vahvistusta.
  • Lisäviivettä. Jokainen näistä kutsuista on edestakainen kierros, ennen kuin käyttäjä on kirjautunut sisään.
  • Mitään ei voi lukea. Käyttäjä hyväksyy transaktion tavut, ei selkeää kuvausta siitä, mihin hän suostuu.
  • Käyttäytymiseen liittyvä riski. Kun käyttäjiä pyydetään allekirjoittamaan transaktio pelkästään kirjautumista varten, heidät on helpompi huijata allekirjoittamaan haitallinen.

Off-chain-viesti ohittaa kaiken tämän. Ainoa edestakainen kierros tapahtuu omalle palvelimellesi.

A sign-in transaction fetches a blockhash, signs, simulates, sends, and polls for confirmation before the server can verify it. An off-chain message goes from a server challenge to a wallet signature to a server-side check, with no RPC calls and no fee.

Mitä lompakko allekirjoittaa

Off-chain-viesti alkaa kiinteällä allekirjoitusdomainilla \xffsolana offchain. Mikään kelvollinen transaktio eiala näillä tavuilla, joten allekirjoitettua viestiä ei voi koskaan käyttää transaktiona. Muodon versio 1 luettelee sen jälkeen vaadittavat allekirjoittajat ja sisältää viestin UTF-8-tekstinä ilman pituusrajaa.

Lompakko muodostaa nämä tavut, allekirjoittaa ne ja palauttaa ne allekirjoituksen mukana. Spesifikaatio kattaa koko muodon, mukaan lukien vanhan version 0.

A version 1 off-chain message is a 16-byte signing domain, a version byte, a signer count, each signer's 32-byte public key in sorted order, and the UTF-8 content. The envelope prefixes it with a signature count and one 64-byte signature per signer.

Valitse kirjautumistapa

Kaikki lompakot eivät vielä tue off-chain-viestejä. Tarkista yhdistetyn tilin ominaisuudet ennen allekirjoituspyyntöä ja käytä varamenetelmää, jos ominaisuus puuttuu:

  1. Jos tili tukee solana:signOffchainMessage-ominaisuutta viestiversiolla 1, allekirjoita off-chain-viesti.
  2. Muussa tapauksessa allekirjoita sama haaste solana:signMessage-ominaisuudella. Useimmat ohjelmistolompakot tukevat sitä.
  3. Tarjoa laitelompakon käyttäjille, joiden lompakko ei tue viestejä, nimenomainen valinta, kuten "Käytän laitelompakkoa" -kytkin, joka allekirjoittaa sen sijaan kirjautumistransaktion. Älä ohjaa heitä tälle polulle oletuksena.
When a wallet connects, check whether its account supports solana:signOffchainMessage version 1. If it does, sign an off-chain message. If not, sign a raw message with solana:signMessage, and let hardware wallet users opt into signing a sign-in transaction.

Allekirjoita viesti selaimessa

Asenna Wallet Standard -paketit Kitin rinnalle:

Terminal
$
npm install @solana/kit @solana/wallet-standard-features @wallet-standard/ui @wallet-standard/ui-features @wallet-standard/ui-registry

Nämä apufunktiot ottavat parametrina UiWalletAccount-olion, kuten account, jonka useConnectedWallet palauttaa React-oppaassa:

offchain-message.ts
import {
SolanaSignOffchainMessage,
type SolanaSignOffchainMessageFeature
} from "@solana/wallet-standard-features";
import type { UiWalletAccount } from "@wallet-standard/ui";
import { getWalletAccountFeature } from "@wallet-standard/ui-features";
import { getWalletAccountForUiWalletAccount } from "@wallet-standard/ui-registry";
type OffchainMessageFeature =
SolanaSignOffchainMessageFeature[typeof SolanaSignOffchainMessage];
export function supportsOffchainMessages(account: UiWalletAccount) {
if (!account.features.includes(SolanaSignOffchainMessage)) return false;
const feature = getWalletAccountFeature(
account,
SolanaSignOffchainMessage
) as OffchainMessageFeature;
return feature.supportedMessageVersions.includes(1);
}
export async function signOffchainMessage(
account: UiWalletAccount,
message: string
) {
const feature = getWalletAccountFeature(
account,
SolanaSignOffchainMessage
) as OffchainMessageFeature;
const [output] = await feature.signOffchainMessage({
messageVersion: 1,
account: getWalletAccountForUiWalletAccount(account),
message,
requiredSigners: [account.publicKey]
});
return output;
}

signOffchainMessage palauttaa signedOffchainMessage-arvon, eli täydelliset tavut, jotka lompakko allekirjoitti, sekä signature-arvon. Koodaa molemmat Base64-muotoon ja lähetä ne palvelimellesi lompakon osoitteen kanssa.

Kirjoita haaste niin, että se on helppolukuinen pienellä näytöllä. Nimeä sovelluksesi ja domain, kerro, mitä allekirjoittaminen tekee, ja lisää kertakäyttöinen nonce sekä palvelimesi antama myöntöaika:

swap.app wants you to sign in with your Solana account.
Signing in costs nothing and does not submit a transaction.
Nonce: 8f3a1c9e
Issued at: 2026-09-29T17:04:00Z

Varmenna allekirjoitus palvelimellasi

Varmennus on paikallinen allekirjoituksen tarkistus, eikä se vaadi RPC-yhteyttä. Pura lompakon allekirjoittamat tavut, varmista, että ne vastaavat antamaasi haastetta, ja tarkista sitten allekirjoitus:

verify-sign-in.ts
import {
address,
assertOffchainMessageV1Equal,
getBase64Encoder,
getOffchainMessageDecoder,
verifyOffchainMessageEnvelope,
type OffchainMessageBytes,
type SignatureBytes
} from "@solana/kit";
export async function verifySignIn(input: {
walletAddress: string;
expectedMessage: string;
signedOffchainMessage: string;
signature: string;
}) {
const signer = address(input.walletAddress);
const base64 = getBase64Encoder();
const content = base64.encode(
input.signedOffchainMessage
) as OffchainMessageBytes;
const signature = base64.encode(input.signature) as SignatureBytes;
const received = getOffchainMessageDecoder().decode(content);
if (received.version !== 1) {
throw new Error(`Expected a v1 message, got v${received.version}`);
}
assertOffchainMessageV1Equal(received, {
version: 1,
requiredSignatories: [{ address: signer }],
content: input.expectedMessage
});
await verifyOffchainMessageEnvelope({
content,
signatures: { [signer]: signature }
});
}

assertOffchainMessageV1Equal heittää virheen, jos sisältö tai allekirjoittajat poikkeavat odotetusta. verifyOffchainMessageEnvelope heittää virheen, jos allekirjoitus puuttuu tai on virheellinen. Hae expectedMessage noncen perusteella palvelimeltasi sen sijaan, että luottaisit asiakkaan palauttamaan kopioon. Kuluta nonce heti, kun allekirjoitus varmistuu, jotta samalla allekirjoituksella ei voi kirjautua sisään kahdesti.

Varmenna raakaviesti

signMessage-allekirjoitus kattaa haastetavut suoraan, joten asiakkaan tarvitsee lähettää vain allekirjoitus ja lompakon osoite. Tarkista se antamaasi haastetta vasten:

verify-raw-sign-in.ts
import {
address,
getBase64Encoder,
getPublicKeyFromAddress,
getUtf8Encoder,
signatureBytes,
verifySignature
} from "@solana/kit";
export async function verifyRawSignIn(input: {
walletAddress: string;
expectedMessage: string;
signature: string;
}) {
const publicKey = await getPublicKeyFromAddress(address(input.walletAddress));
const signature = signatureBytes(getBase64Encoder().encode(input.signature));
const message = getUtf8Encoder().encode(input.expectedMessage);
if (!(await verifySignature(publicKey, signature, message))) {
throw new Error("Invalid signature");
}
}

Samat nonce-säännöt pätevät: hae expectedMessage noncen perusteella ja kuluta se, kun varmennus onnistuu.

@solana/kit re-eksporttaa nämä apufunktiot paketista @solana/offchain-messages. Käytä erillistä pakettia, jos palvelimesi ei riipu Kitistä.

Sign In With Solana

Sign In With Solana (SIWS) standardoi itse haasteen. Sovelluksesi välittää rakenteiset kentät, kuten domain, statement, nonce ja issuedAt, lompakon solana:signIn- ominaisuudelle. Lompakko muotoilee ne vakioviestiksi, yhdistää tarvittaessa ja allekirjoittaa sen yhdessä vaiheessa.

solana:signIn-ominaisuuden versio 1.1.0 lisää useOffchainMessage-asetuksen. Kun välität arvon useOffchainMessage: { messageVersion: 1 }, lompakko paketoi SIWS-tekstin version 1 off-chain-viestiin, jossa allekirjoittava tili on ainoa vaadittu allekirjoittaja. Laitelompakot voivat näyttää ja allekirjoittaa sen, ja tuloste ilmoittaa signedMessageFormat: { kind: "offchainMessage", messageVersion: 1 }. Lompakot, jotka ilmoittavat version 1.0.0, eivät tunne asetusta, joten tarkista ensin ominaisuuden versio ja jätä asetus muuten pois.

solana:signIn on lompakon ominaisuus, ei tilin ominaisuus, joten nämä apufunktiot ottavat parametrina UiWallet-olion:

sign-in.ts
import {
SolanaSignIn,
type SolanaSignInFeature,
type SolanaSignInInput
} from "@solana/wallet-standard-features";
import type { UiWallet } from "@wallet-standard/ui";
import { getWalletFeature } from "@wallet-standard/ui-features";
type SignInFeature = SolanaSignInFeature[typeof SolanaSignIn];
export function supportsOffchainSignIn(wallet: UiWallet) {
if (!wallet.features.includes(SolanaSignIn)) return false;
const feature = getWalletFeature(wallet, SolanaSignIn) as SignInFeature;
return feature.version === "1.1.0";
}
export async function signIn(wallet: UiWallet, input: SolanaSignInInput) {
const feature = getWalletFeature(wallet, SolanaSignIn) as SignInFeature;
const [output] = await feature.signIn({
...input,
...(supportsOffchainSignIn(wallet) && {
useOffchainMessage: { messageVersion: 1 }
})
});
return output;
}

Muodosta syöte palvelimellasi kertakäyttöisellä nonce-arvolla ja issuedAt- ajalla ja säilytä kopio noncen mukaan avainnettuna. Kuluta nonce, kun kirjautuminen on varmennettu.

Ilman Wallet Adapteria @solana/wallet-standard-util-paketin verifySignIn tarkistaa vain pelkän SIWS-tulosteen. Kun signedMessageFormat ilmoittaa off-chain- viestin, signedMessage on off-chain-viesti, jonka sisältö on SIWS-teksti. Muodosta odotettu teksti uudelleen tallennetusta syötteestäsi ja allekirjoittavasta osoitteesta @solana/wallet-standard-util-paketin createSignInMessageText-funktiolla ja varmenna se kuten mikä tahansa muu off-chain-viesti, kuten kohdassa Varmenna allekirjoitus palvelimellasi. @solana/offchain-messages-paketin README käsittelee tämän kulun Kitissä.

Lompakoille

Lompakot lisäävät tuen toteuttamalla solana:signOffchainMessage Wallet Standard -ominaisuuden paketista @solana/wallet-standard-features:

  • Ilmoita version: "1.0.0" ja luettele allekirjoittamasi viestiversiot kohdassa supportedMessageVersions. Tällä hetkellä se on [1].
  • Muodosta version 1 johdanto (preamble) requiredSigners-kentän arvoista, jotka lajittelet ja joista tarkistat kaksoiskappaleet. Hylkää pyyntö, jos tili ei ole yksi vaadituista allekirjoittajista.
  • Näytä viestin teksti käyttäjälle kokonaisuudessaan ennen allekirjoittamista, myös laitteistolompakoissa.
  • Palauta täsmälleen allekirjoitetut tavut arvona signedOffchainMessage sekä Ed25519-allekirjoitus (signature).
  • Jos haluat tukea ketjun ulkopuolista Sign In With Solana -kirjautumista, ilmoita solana:signIn-ominaisuuden arvoksi version: "1.1.0". Kun syöte sisältää kentän useOffchainMessage, allekirjoita SIWS-teksti version 1 ketjun ulkopuolisena viestinä, palauta sen tavut arvona signedMessage ja aseta signedMessageFormat.
  • Jatka solana:signMessage-toiminnon tukemista. Se pysyy muuttumattomana, ja sovellukset käyttävät sitä edelleen varavaihtoehtona.

Is this page helpful?

Sisällysluettelo

Muokkaa sivua
© 2026 Solana Foundation. Kaikki oikeudet pidätetään.