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-viesti | Raakaviesti | Transaktio | |
|---|---|---|---|
| Lompakon ominaisuus | signOffchainMessage | signMessage | signTransaction |
| Laitelompakon tuki | Riippuu laitteesta | Ei | Kyllä |
| Käyttäjän luettavissa | Kyllä | Vain ohjelmistolompakoissa | Riippuu laitteesta |
| Ilmoittaa vaadittavat allekirjoittajat | Kyllä | Ei | Kyllä |
| RPC-kutsut ja maksut | Ei mitään | Ei mitään | Blockhash, 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.
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.
Valitse kirjautumistapa
Kaikki lompakot eivät vielä tue off-chain-viestejä. Tarkista yhdistetyn tilin ominaisuudet ennen allekirjoituspyyntöä ja käytä varamenetelmää, jos ominaisuus puuttuu:
- Jos tili tukee
solana:signOffchainMessage-ominaisuutta viestiversiolla 1, allekirjoita off-chain-viesti. - Muussa tapauksessa allekirjoita sama haaste
solana:signMessage-ominaisuudella. Useimmat ohjelmistolompakot tukevat sitä. - 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.
Allekirjoita viesti selaimessa
Asenna Wallet Standard -paketit Kitin rinnalle:
$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:
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: 8f3a1c9eIssued 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:
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:
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:
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 kohdassasupportedMessageVersions. 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
signedOffchainMessagesekä Ed25519-allekirjoitus (signature). - Jos haluat tukea ketjun ulkopuolista Sign In With Solana -kirjautumista, ilmoita
solana:signIn-ominaisuuden arvoksiversion: "1.1.0". Kun syöte sisältää kentänuseOffchainMessage, allekirjoita SIWS-teksti version 1 ketjun ulkopuolisena viestinä, palauta sen tavut arvonasignedMessageja asetasignedMessageFormat. - Jatka
solana:signMessage-toiminnon tukemista. Se pysyy muuttumattomana, ja sovellukset käyttävät sitä edelleen varavaihtoehtona.
Is this page helpful?