Skip to main content

Overview

The PrivateKey class handles ECDSA (secp256k1) private keys for the Hive blockchain. It provides methods for key generation, derivation from seeds/passwords, signing transactions, and encryption operations. All private keys are stored internally as Uint8Array and can be converted to/from Wallet Import Format (WIF) strings for storage and transmission.

Constructor

const key = new PrivateKey(keyBytes)
keyBytes
Uint8Array
required
Raw 32-byte private key as Uint8Array
The constructor validates that the key is valid for secp256k1. Invalid keys will throw an error.

Example

import { PrivateKey } from 'hive-tx'
import { randomBytes } from '@noble/hashes/utils'

// Create from raw bytes (must be valid secp256k1 key)
const keyBytes = randomBytes(32)
const key = new PrivateKey(keyBytes)

Static Methods

from

Creates a PrivateKey instance from a WIF string or raw Uint8Array. Automatically detects the input type.
const key = PrivateKey.from(value)
value
string | Uint8Array
required
WIF formatted string or raw 32-byte key as Uint8Array
returns
PrivateKey
New PrivateKey instance

Example

import { PrivateKey } from 'hive-tx'

// From WIF string
const key = PrivateKey.from('5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw')

// From Uint8Array
const keyBytes = new Uint8Array(32)
const key = PrivateKey.from(keyBytes)

fromString

Creates a PrivateKey from a Wallet Import Format (WIF) encoded string.
const key = PrivateKey.fromString(wif)
wif
string
required
WIF encoded private key string (starts with ‘5’)
returns
PrivateKey
New PrivateKey instance

Example

import { PrivateKey } from 'hive-tx'

const wif = '5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw'
const key = PrivateKey.fromString(wif)

console.log(key.toString()) // Returns original WIF

fromSeed

Creates a PrivateKey from a seed string or Uint8Array. The seed is hashed with SHA256 to produce the private key.
const key = PrivateKey.fromSeed(seed)
seed
string | Uint8Array
required
Seed string (hex or UTF-8) or raw byte array
returns
PrivateKey
New PrivateKey instance derived from seed

Example

import { PrivateKey } from 'hive-tx'

// From UTF-8 string seed
const key1 = PrivateKey.fromSeed('my-secret-seed-phrase')

// From hex string
const key2 = PrivateKey.fromSeed('a0b1c2d3e4f5')

// From Uint8Array
const seedBytes = new Uint8Array([1, 2, 3, 4, 5])
const key3 = PrivateKey.fromSeed(seedBytes)

fromLogin

Derives a PrivateKey from username, password, and role using Hive’s key derivation scheme. This generates the same keys that Hive wallets use for login-based keys.
const key = PrivateKey.fromLogin(username, password, role?)
username
string
required
Hive username (without ’@’)
password
string
required
Master password or seed phrase
role
KeyRole
default:"'active'"
Key role: 'owner', 'active', 'posting', or 'memo'
returns
PrivateKey
New PrivateKey instance for the specified role

Example

import { PrivateKey } from 'hive-tx'

// Generate active key from login
const activeKey = PrivateKey.fromLogin('alice', 'my-master-password', 'active')

// Generate posting key
const postingKey = PrivateKey.fromLogin('alice', 'my-master-password', 'posting')

// Generate owner key
const ownerKey = PrivateKey.fromLogin('alice', 'my-master-password', 'owner')

// Generate memo key
const memoKey = PrivateKey.fromLogin('alice', 'my-master-password', 'memo')
Key Roles:
  • owner: Highest authority, can change all other keys
  • active: Can transfer funds and perform most operations
  • posting: Can post, comment, vote, and follow
  • memo: Used for encrypting private messages

randomKey

Generates a new cryptographically secure random private key using the secp256k1 key generation algorithm.
const key = PrivateKey.randomKey()
returns
PrivateKey
New randomly generated PrivateKey instance
This method may take up to 250ms due to secure entropy collection.

Example

import { PrivateKey } from 'hive-tx'

// Generate a new random key
const randomKey = PrivateKey.randomKey()

// Export to WIF for storage
const wif = randomKey.toString()
console.log('New private key:', wif)

// Get corresponding public key
const publicKey = randomKey.createPublic()
console.log('Public key:', publicKey.toString())

Instance Methods

sign

Signs a 32-byte message hash using ECDSA and returns a recoverable signature. The signature includes recovery information to allow public key recovery.
const signature = key.sign(message)
message
Uint8Array
required
32-byte message hash to sign (typically SHA256 digest)
returns
Signature
Signature object containing the signature data with recovery information

Example

import { PrivateKey, Transaction } from 'hive-tx'
import { sha256 } from '@noble/hashes/sha2'

const key = PrivateKey.fromLogin('alice', 'password', 'active')

// Sign a transaction
const tx = new Transaction()
await tx.addOperation('vote', {
  voter: 'alice',
  author: 'bob',
  permlink: 'my-post',
  weight: 10000
})

const { digest } = tx.digest()
const signature = key.sign(digest)

console.log('Signature:', signature.customToString())

createPublic

Derives the corresponding public key for this private key.
const publicKey = key.createPublic(prefix?)
prefix
string
Optional address prefix (defaults to config.address_prefix, typically ‘STM’)
returns
PublicKey
PublicKey instance derived from this private key

Example

import { PrivateKey } from 'hive-tx'

const key = PrivateKey.fromLogin('alice', 'password', 'posting')

// Get default public key (STM prefix)
const publicKey = key.createPublic()
console.log(publicKey.toString())
// Output: STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA

// Get public key with custom prefix
const customPublic = key.createPublic('TST')
console.log(customPublic.toString())
// Output: TST8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA

getSharedSecret

Computes a shared secret using ECDH key exchange for memo encryption. The shared secret is used as a key for AES encryption/decryption.
const sharedSecret = key.getSharedSecret(publicKey)
publicKey
PublicKey
required
Other party’s public key
returns
Uint8Array
64-byte shared secret (SHA512 hash of ECDH shared point)

Example

import { PrivateKey, PublicKey } from 'hive-tx'

// Alice's keys
const aliceMemoKey = PrivateKey.fromLogin('alice', 'password', 'memo')
const alicePublic = aliceMemoKey.createPublic()

// Bob's keys
const bobMemoKey = PrivateKey.fromLogin('bob', 'password', 'memo')
const bobPublic = bobMemoKey.createPublic()

// Both parties derive the same shared secret
const aliceShared = aliceMemoKey.getSharedSecret(bobPublic)
const bobShared = bobMemoKey.getSharedSecret(alicePublic)

// These are identical and can be used for encryption
console.log('Secrets match:', aliceShared.toString() === bobShared.toString())

toString

Returns the private key as a Wallet Import Format (WIF) encoded string. This includes network ID and checksum for safe storage/transmission.
const wif = key.toString()
returns
string
WIF encoded private key string

Example

import { PrivateKey } from 'hive-tx'

const key = PrivateKey.fromLogin('alice', 'password', 'active')
const wif = key.toString()

console.log('WIF:', wif)
// Output: 5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw

// Store securely
process.env.HIVE_ACTIVE_KEY = wif

// Later, restore from storage
const restoredKey = PrivateKey.fromString(process.env.HIVE_ACTIVE_KEY)

inspect

Returns a masked representation of the private key for debugging/logging. Shows only the first and last 6 characters to avoid accidental exposure.
const masked = key.inspect()
returns
string
Masked key representation for safe logging
Always use inspect() for logging. Never log toString() output as it exposes the full private key.

Example

import { PrivateKey } from 'hive-tx'

const key = PrivateKey.fromLogin('alice', 'password', 'active')

// Safe for logging
console.log(key.inspect())
// Output: PrivateKey: 5JdeC9...BsQnsw

// UNSAFE - exposes full key
console.log(key.toString())
// Output: 5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw

Security Best Practices

Critical Security Guidelines:
  1. Never expose private keys: Never log, transmit, or store private keys in plain text
  2. Use environment variables: Store keys in environment variables or secure key management systems
  3. Use role-appropriate keys: Only use the minimum required key role for each operation
  4. Secure key generation: Always use randomKey() or fromLogin() for key generation
  5. Validate sources: Only load keys from trusted sources
  6. Memory safety: Clear sensitive key material from memory when done

Secure Storage Example

import { PrivateKey } from 'hive-tx'

// ✅ GOOD: Load from secure environment variable
const key = PrivateKey.fromString(process.env.HIVE_ACTIVE_KEY!)

// ✅ GOOD: Use inspect() for logging
console.log('Using key:', key.inspect())

// ❌ BAD: Hardcoded private key
const badKey = PrivateKey.fromString('5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw')

// ❌ BAD: Logging full key
console.log('Key:', key.toString())

Key Role Selection

import { PrivateKey, Transaction } from 'hive-tx'

// ✅ GOOD: Use posting key for posting operations
const postingKey = PrivateKey.fromLogin('alice', 'password', 'posting')
const tx = new Transaction()
await tx.addOperation('vote', {
  voter: 'alice',
  author: 'bob',
  permlink: 'my-post',
  weight: 10000
})
tx.sign(postingKey)

// ❌ BAD: Using active key when posting key would suffice
const activeKey = PrivateKey.fromLogin('alice', 'password', 'active')
tx.sign(activeKey) // Works but unnecessarily exposes more powerful key

KeyRole Type

The KeyRole type defines the four key authority levels in Hive:
type KeyRole = 'owner' | 'active' | 'posting' | 'memo'
RoleAuthority LevelCommon Operations
ownerHighestChange keys, recover account
activeHighTransfer funds, power up/down, witness voting
postingMediumPost, comment, vote, follow, reblog
memoLowEncrypt/decrypt private messages

Complete Examples

Generate and Store New Keys

import { PrivateKey } from 'hive-tx'
import * as fs from 'fs'

// Generate new random keys for all roles
const ownerKey = PrivateKey.randomKey()
const activeKey = PrivateKey.randomKey()
const postingKey = PrivateKey.randomKey()
const memoKey = PrivateKey.randomKey()

// Get public keys for account creation
const keys = {
  owner: {
    private: ownerKey.toString(),
    public: ownerKey.createPublic().toString()
  },
  active: {
    private: activeKey.toString(),
    public: activeKey.createPublic().toString()
  },
  posting: {
    private: postingKey.toString(),
    public: postingKey.createPublic().toString()
  },
  memo: {
    private: memoKey.toString(),
    public: memoKey.createPublic().toString()
  }
}

// Store securely (in production, use a proper key management system)
fs.writeFileSync('.keys.json', JSON.stringify(keys, null, 2), {
  mode: 0o600 // Read/write for owner only
})

console.log('Keys generated and stored securely')

Sign Transaction with Multiple Keys

import { Transaction, PrivateKey } from 'hive-tx'

async function multiSigTransfer() {
  const tx = new Transaction()
  
  // Operation requiring multiple signatures
  await tx.addOperation('transfer', {
    from: 'multisig-account',
    to: 'recipient',
    amount: '100.000 HIVE',
    memo: ''
  })
  
  // Sign with multiple authority keys
  const key1 = PrivateKey.fromString(process.env.SIGNER1_KEY!)
  const key2 = PrivateKey.fromString(process.env.SIGNER2_KEY!)
  
  tx.sign([key1, key2])
  
  const result = await tx.broadcast()
  console.log('Multi-sig transaction broadcast:', result.tx_id)
}

See Also

  • PublicKey - Public key management and verification
  • Signature - Signature creation and verification
  • Transaction - Transaction signing and broadcasting
  • Memo - Encrypted message utilities

Build docs developers (and LLMs) love