- Published on
Converting Between Base58 and Uint8Array Private Keys in JavaScript
- Authors
- Name
When working with Solana wallets and keypairs, you'll encounter private keys in two common formats: Base58 encoded strings and Uint8Array (byte arrays). Understanding how to convert between these formats is essential for tasks like importing wallets, signing transactions, or migrating keys between different tools.
Why Two Formats?
- Base58: A human-readable string format commonly used for displaying and storing keys. It's URL-safe and avoids visually ambiguous characters (like
0,O,I,l). - Uint8Array: The raw bytes that cryptographic libraries actually use under the hood.
Using Solana Kit
Solana Kit has built-in utilities for Base58 encoding/decoding.
Installation
npm install @solana/kit
Base58 to Uint8Array
import { getBase58Decoder } from '@solana/kit';
const base58PrivateKey = '5K1gR...yourBase58KeyHere';
const decoder = getBase58Decoder();
const privateKeyBytes = decoder.decode(base58PrivateKey);
console.log(privateKeyBytes); // Uint8Array(64) [...]
Uint8Array to Base58
import { getBase58Encoder } from '@solana/kit';
const privateKeyBytes = new Uint8Array([
174, 47, 154, 16, 202, 193, 206, 113,
// ... rest of your 64 bytes
]);
const encoder = getBase58Encoder();
const base58PrivateKey = encoder.encode(privateKeyBytes);
console.log(base58PrivateKey); // '5K1gR...'
Creating a Keypair from Base58
import { getBase58Decoder, createKeyPairFromBytes } from '@solana/kit';
const base58PrivateKey = '5K1gR...yourBase58KeyHere';
const decoder = getBase58Decoder();
const privateKeyBytes = decoder.decode(base58PrivateKey);
const keypair = await createKeyPairFromBytes(privateKeyBytes);
Using Umi
Umi provides its own Base58 utilities through the @metaplex-foundation/umi package.
Installation
npm install @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults
Base58 to Uint8Array
import { base58 } from '@metaplex-foundation/umi/serializers';
const base58PrivateKey = '5K1gR...yourBase58KeyHere';
const [privateKeyBytes] = base58.serialize(base58PrivateKey);
console.log(privateKeyBytes); // Uint8Array(64) [...]
Uint8Array to Base58
import { base58 } from '@metaplex-foundation/umi/serializers';
const privateKeyBytes = new Uint8Array([
174, 47, 154, 16, 202, 193, 206, 113,
// ... rest of your 64 bytes
]);
const base58PrivateKey = base58.deserialize(privateKeyBytes)[0];
console.log(base58PrivateKey); // '5K1gR...'
Creating a Keypair from Base58 in Umi
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
import { createSignerFromKeypair } from '@metaplex-foundation/umi';
import { base58 } from '@metaplex-foundation/umi/serializers';
const umi = createUmi('https://api.mainnet-beta.solana.com');
const base58PrivateKey = '5K1gR...yourBase58KeyHere';
const [secretKey] = base58.serialize(base58PrivateKey);
const keypair = umi.eddsa.createKeypairFromSecretKey(secretKey);
const signer = createSignerFromKeypair(umi, keypair);
console.log('Public Key:', signer.publicKey);
Using bs58 (Standalone Library)
If you just need the encoding/decoding without a full Solana library, bs58 is a lightweight option:
npm install bs58
import bs58 from 'bs58';
// Base58 to Uint8Array
const privateKeyBytes = bs58.decode('5K1gR...yourBase58KeyHere');
// Uint8Array to Base58
const base58PrivateKey = bs58.encode(privateKeyBytes);
Complete Utility Example (Solana Kit)
import {
getBase58Encoder,
getBase58Decoder,
createKeyPairFromBytes,
getAddressFromPublicKey
} from '@solana/kit';
/**
* Convert a Base58 private key to Uint8Array
*/
function base58ToUint8Array(base58Key) {
const decoder = getBase58Decoder();
return decoder.decode(base58Key);
}
/**
* Convert a Uint8Array private key to Base58
*/
function uint8ArrayToBase58(bytes) {
const encoder = getBase58Encoder();
return encoder.encode(bytes);
}
/**
* Create a Keypair from a Base58 private key
*/
async function keypairFromBase58(base58Key) {
const secretKey = base58ToUint8Array(base58Key);
return await createKeyPairFromBytes(secretKey);
}
// Usage
const originalBase58 = '4wBqpZM9k9...yourKeyHere';
// Round-trip test
const bytes = base58ToUint8Array(originalBase58);
const backToBase58 = uint8ArrayToBase58(bytes);
console.log('Round-trip successful:', originalBase58 === backToBase58);
JSON Array Format
Sometimes you'll see private keys stored as JSON arrays of numbers (like from solana-keygen). Here's how to handle that:
import { getBase58Encoder } from '@solana/kit';
// JSON array format
const jsonArrayKey = [174, 47, 154, 16, 202, 193, /* ... 64 numbers total */];
// Convert to Uint8Array
const uint8ArrayKey = new Uint8Array(jsonArrayKey);
// Convert to Base58
const encoder = getBase58Encoder();
const base58Key = encoder.encode(uint8ArrayKey);
Important Security Notes
- Never expose your private keys in client-side code or commit them to version control
- Use environment variables or secure key management solutions for production
- The secret key is 64 bytes on Solana: the first 32 bytes are the private key, and the last 32 bytes are the public key