Keypairs y Direcciones
La identidad de Solana se basa en keypairs Ed25519. La clave pública es la dirección de la cuenta; la clave secreta autoriza las transacciones. Comprender los roles de firma previene errores de autorización y fugas de claves.
Busca en todas las páginas de la documentación
La identidad de Solana se basa en keypairs Ed25519. La clave pública es la dirección de la cuenta; la clave secreta autoriza las transacciones. Comprender los roles de firma previene errores de autorización y fugas de claves.
Tarjeta de referencia rápida - lista para copiar y pegar.
solana-keygen new --outfile ./keypair.json --no-bip39-passphrase
solana-keygen pubkey ./keypair.jsonimport { createKeyPairSignerFromBytes, address } from "@solana/kit";
import { readFileSync } from "node:fs";
const secret = Uint8Array.from(JSON.parse(readFileSync("./keypair.json", "utf8")));
const signer = await createKeyPairSignerFromBytes(secret);
console.log(signer.address);Cuándo usar esto:
isSigner: trueimport {
createSolanaRpc,
createKeyPairSignerFromBytes,
createTransactionMessage,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
signTransactionMessageWithSigners,
getSignatureFromTransaction,
pipe,
} from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
import { readFileSync } from "node:fs";
const rpc = createSolanaRpc("https://api.devnet.solana.com");
// Cargar firmante desde archivo keypair
const secret = Uint8Array.from(
JSON.parse(readFileSync(process.env.HOME + "/.config/solana/id.json", "utf8")),
);
const feePayer = await createKeyPairSignerFromBytes(secret);
const recipient = await createKeyPairSignerFromBytes(
crypto.getRandomValues(new Uint8Array(64)),
);
const { value: blockhash } = await rpc.getLatestBlockhash().send();
const message = pipe(
createTransactionMessage({ version: 0 }),
(m) => setTransactionMessageFeePayer(feePayer.address, m),
(m) => setTransactionMessageLifetimeUsingBlockhash(blockhash, m),
(m) =>
appendTransactionMessageInstruction(
getTransferSolInstruction({
source: feePayer.address,
destination: recipient.address,
amount: 1_000_000n,
}),
m,
),
);
const signed = await signTransactionMessageWithSigners(message, [feePayer]);
const signature = getSignatureFromTransaction(signed);
console.log("Signature:", signature);Lo que esto demuestra:
createKeyPairSignerFromBytes envuelve el keypair como un firmante de KitisSigner y isWritable| Rol | ¿Firma? | Cuenta Típica |
|---|---|---|
| Pagador de tarifas | Sí | Primer firmante; paga la tarifa de transacción |
| Autoridad | Sí | Propietario de lamports o cuenta de tokens |
| Programa | No | Cuenta ejecutable invocada por la instrucción |
| PDA | No (el programa firma a través de semillas) | Dirección derivada sin clave privada |
use anchor_lang::prelude::*;
#[derive(Accounts)]
pub struct UpdateData<'info> {
#[account(mut, signer)]
pub authority: Signer<'info>,
#[account(mut, has_one = authority)]
pub data_account: Account<'info, MyData>,
}Signer<'info> verifica que la cuenta firmó la transaccióninvoke_signed con semillas en lugar de una clave privada.gitignore, variables de entorno o billeteras de hardware para producción.isSigner - transacción rechazada en tiempo de ejecución. Solución: marcar cada cuenta firmante como firmante en las cuentas de la instrucción.find_program_address y dejar que el programa firme.solana-keygen o helpers de Kit, no segmentación de bytes en bruto.| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
CLI solana-keygen | Billeteras rápidas de desarrollo | Gestión de claves de producción |
| Billetera de hardware (Ledger) | Firma en Mainnet | Firma automatizada de servidor con alto rendimiento |
Firmantes de @solana/kit | Construcción de transacciones en TypeScript | Lógica de programa en cadena |
| PDAs con semillas | Cuentas controladas por programa | Billeteras de usuario |
Ed25519. Las claves públicas son de 32 bytes, codificadas en base58 para visualización.
Un array JSON de 64 bytes: la semilla secreta de 32 bytes concatenada con la clave pública de 32 bytes.
Sí. Los términos son intercambiables: la clave pública Ed25519 de 32 bytes codificada en base58.
No. Cada keypair válido se mapea a exactamente una clave pública/dirección.
Una dirección derivada de semillas y un ID de programa. No tiene clave privada; el programa firma por ella a través de invoke_signed.
Hasta 16 firmas por transacción en el formato actual. El pagador de tarifas es siempre uno de ellos.
No. Solo la autoridad de la cuenta de origen (y el pagador de tarifas) deben firmar.
import { address } from "@solana/kit";
try {
address("invalid!");
} catch {
console.log("Invalid address");
}No. La clave secreta no se puede derivar de la clave pública (función unidireccional).
11111111111111111111111111111111 - maneja la creación de cuentas y las transferencias de SOL.
No. Utiliza keypairs de servicio dedicados con saldos mínimos financiados y controles de acceso estrictos.
La clave privada nunca sale del dispositivo. La aplicación envía el mensaje de transacción; el dispositivo devuelve la firma.
Versiones de Stack: Esta página fue escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, y LiteSVM 0.6.x.
Revisado por Chris St. John·Última actualización: 19 jul 2026