> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/mahdiyari/hive-tx/llms.txt
> Use this file to discover all available pages before exploring further.

# Key Management

> Best practices for generating, storing, and using Hive private keys securely

Private keys are the foundation of security on Hive. This guide covers how to generate, derive, and manage keys safely.

## Key Types Overview

Hive accounts have four key types, each with different permissions:

| Key Type    | Permission Level | Use Cases                                           |
| ----------- | ---------------- | --------------------------------------------------- |
| **Owner**   | Highest          | Change passwords, recover account, update authority |
| **Active**  | High             | Transfers, power up/down, witness votes, proposals  |
| **Posting** | Medium           | Post, comment, vote, follow, reblog                 |
| **Memo**    | Special          | Encrypt/decrypt private messages                    |

<Warning>
  Never use your owner key for daily operations. Store it securely offline and only use it for account recovery or key changes.
</Warning>

## Generating Random Keys

Create a new cryptographically secure random key:

<Steps>
  <Step title="Generate a random key">
    ```typescript theme={null}
    import { PrivateKey } from 'hive-tx'

    const privateKey = PrivateKey.randomKey()
    console.log('Private key (WIF):', privateKey.toString())
    // Output: 5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw
    ```

    <Note>
      Key generation may take up to 250ms due to entropy collection for cryptographic security.
    </Note>
  </Step>

  <Step title="Get the public key">
    ```typescript theme={null}
    const publicKey = privateKey.createPublic()
    console.log('Public key:', publicKey.toString())
    // Output: STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA
    ```
  </Step>

  <Step title="Store safely">
    ```typescript theme={null}
    // Export for secure storage
    const wif = privateKey.toString()

    // Store in environment variables or secure key management system
    // NEVER commit keys to version control
    ```
  </Step>
</Steps>

## Deriving Keys from Username and Password

Hive uses a deterministic key derivation scheme. You can generate the same keys from a username, password, and role:

```typescript theme={null}
import { PrivateKey } from 'hive-tx'

const username = 'alice'
const masterPassword = 'my-secure-password-123'

// Derive different role keys
const ownerKey = PrivateKey.fromLogin(username, masterPassword, 'owner')
const activeKey = PrivateKey.fromLogin(username, masterPassword, 'active')
const postingKey = PrivateKey.fromLogin(username, masterPassword, 'posting')
const memoKey = PrivateKey.fromLogin(username, masterPassword, 'memo')

console.log('Owner:', ownerKey.toString())
console.log('Active:', activeKey.toString())
console.log('Posting:', postingKey.toString())
console.log('Memo:', memoKey.toString())
```

Key derivation formula:

```
seed = username + role + password
private_key = SHA256(seed)
```

<Tip>
  This is the same derivation used by Hive wallets. If you have your master password, you can always recover your keys.
</Tip>

## Creating Keys from a Seed

Generate deterministic keys from a seed string or bytes:

```typescript theme={null}
import { PrivateKey } from 'hive-tx'

// From a string seed
const seed = 'my-secure-random-seed-phrase'
const key1 = PrivateKey.fromSeed(seed)

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

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

console.log(key1.toString())
```

<Note>
  The seed is hashed with SHA256 to produce the private key. The same seed always produces the same key.
</Note>

## Loading Existing Keys

Import keys from WIF (Wallet Import Format) strings:

```typescript theme={null}
import { PrivateKey } from 'hive-tx'

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

// Or using fromString explicitly
const key2 = PrivateKey.fromString(wif)

// From Uint8Array (32 bytes)
const keyBytes = new Uint8Array(32) // your key bytes
const key3 = PrivateKey.from(keyBytes)
```

## Working with Public Keys

Derive public keys from private keys:

```typescript theme={null}
import { PrivateKey } from 'hive-tx'

const privateKey = PrivateKey.from('5J...')

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

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

## Secure Key Storage

### Environment Variables

Store keys in environment variables:

```bash theme={null}
# .env file (NEVER commit to git!)
HIVE_POSTING_KEY=5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw
HIVE_ACTIVE_KEY=5K...
```

```typescript theme={null}
import { PrivateKey } from 'hive-tx'
import * as dotenv from 'dotenv'

dotenv.config()

const postingKey = PrivateKey.from(process.env.HIVE_POSTING_KEY!)
const activeKey = PrivateKey.from(process.env.HIVE_ACTIVE_KEY!)
```

### Encrypted Storage

For production applications, use encrypted key storage:

```typescript theme={null}
import { PrivateKey } from 'hive-tx'
import * as crypto from 'crypto'

// Encrypt a private key
function encryptKey(privateKey: PrivateKey, password: string): string {
  const algorithm = 'aes-256-gcm'
  const salt = crypto.randomBytes(32)
  const key = crypto.scryptSync(password, salt, 32)
  const iv = crypto.randomBytes(16)
  
  const cipher = crypto.createCipheriv(algorithm, key, iv)
  const wif = privateKey.toString()
  
  let encrypted = cipher.update(wif, 'utf8', 'hex')
  encrypted += cipher.final('hex')
  
  const authTag = cipher.getAuthTag()
  
  return JSON.stringify({
    encrypted,
    iv: iv.toString('hex'),
    salt: salt.toString('hex'),
    authTag: authTag.toString('hex')
  })
}

// Decrypt a private key
function decryptKey(encryptedData: string, password: string): PrivateKey {
  const data = JSON.parse(encryptedData)
  const algorithm = 'aes-256-gcm'
  
  const salt = Buffer.from(data.salt, 'hex')
  const key = crypto.scryptSync(password, salt, 32)
  const iv = Buffer.from(data.iv, 'hex')
  const authTag = Buffer.from(data.authTag, 'hex')
  
  const decipher = crypto.createDecipheriv(algorithm, key, iv)
  decipher.setAuthTag(authTag)
  
  let decrypted = decipher.update(data.encrypted, 'hex', 'utf8')
  decrypted += decipher.final('utf8')
  
  return PrivateKey.from(decrypted)
}

// Usage
const privateKey = PrivateKey.randomKey()
const encrypted = encryptKey(privateKey, 'my-app-password')

// Store encrypted in database
// ...

// Later, decrypt when needed
const decrypted = decryptKey(encrypted, 'my-app-password')
```

## Key Security Best Practices

<Warning>
  **Never commit private keys to version control**. Add `.env` and key files to `.gitignore`.
</Warning>

<Warning>
  **Never log private keys**. Use the `inspect()` method for safe logging.
</Warning>

```typescript theme={null}
import { PrivateKey } from 'hive-tx'

const key = PrivateKey.randomKey()

// BAD - logs full private key
console.log(key.toString())
// Output: 5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw

// GOOD - logs masked version
console.log(key.inspect())
// Output: PrivateKey: 5JdeC9...BsQnsw
```

<Tip>
  **Use the minimum required key authority**. Use posting keys for social actions, active keys for financial operations.
</Tip>

<Tip>
  **Rotate keys periodically**. Update your active and posting keys every few months for security.
</Tip>

<Tip>
  **Use hardware wallets** for owner keys and large amounts. Keep owner keys completely offline.
</Tip>

## Signing Messages

Sign arbitrary 32-byte hashes:

```typescript theme={null}
import { PrivateKey } from 'hive-tx'
import { sha256 } from '@noble/hashes/sha2'

const privateKey = PrivateKey.from('5J...')
const message = 'Hello, Hive!'

// Hash the message (must be 32 bytes)
const messageHash = sha256(new TextEncoder().encode(message))

// Sign the hash
const signature = privateKey.sign(messageHash)
console.log('Signature:', signature.toString())
```

## Shared Secrets (ECDH)

Compute shared secrets for memo encryption:

```typescript theme={null}
import { PrivateKey, PublicKey } from 'hive-tx'

const alicePrivate = PrivateKey.randomKey()
const bobPrivate = PrivateKey.randomKey()

const alicePublic = alicePrivate.createPublic()
const bobPublic = bobPrivate.createPublic()

// Both parties can compute the same shared secret
const aliceShared = alicePrivate.getSharedSecret(bobPublic)
const bobShared = bobPrivate.getSharedSecret(alicePublic)

// aliceShared === bobShared
console.log('Shared secret length:', aliceShared.length) // 64 bytes
```

<Note>
  Shared secrets are used internally by the Memo class for encrypted messages. See the [Memo Encryption](/guides/memo-encryption) guide for details.
</Note>

## Key Validation

Validate key format on import:

```typescript theme={null}
import { PrivateKey } from 'hive-tx'

try {
  const key = PrivateKey.from('invalid-key-format')
} catch (error) {
  console.error('Invalid key:', error.message)
  // Error: invalid private key
}

try {
  const key = PrivateKey.fromString('5J...')
  console.log('Valid key')
} catch (error) {
  if (error.message.includes('checksum mismatch')) {
    console.error('Key checksum failed - corrupted or incorrect key')
  } else if (error.message.includes('network id mismatch')) {
    console.error('Wrong network - this key is not for Hive')
  } else {
    console.error('Invalid key format')
  }
}
```

## Complete Key Management Example

```typescript theme={null}
import { PrivateKey, PublicKey, Transaction } from 'hive-tx'
import * as dotenv from 'dotenv'

dotenv.config()

class KeyManager {
  private postingKey?: PrivateKey
  private activeKey?: PrivateKey
  
  constructor(private username: string) {}
  
  // Load keys from environment
  loadFromEnv() {
    const postingWif = process.env.HIVE_POSTING_KEY
    const activeWif = process.env.HIVE_ACTIVE_KEY
    
    if (postingWif) {
      this.postingKey = PrivateKey.from(postingWif)
    }
    if (activeWif) {
      this.activeKey = PrivateKey.from(activeWif)
    }
  }
  
  // Load keys from password
  loadFromPassword(password: string) {
    this.postingKey = PrivateKey.fromLogin(this.username, password, 'posting')
    this.activeKey = PrivateKey.fromLogin(this.username, password, 'active')
  }
  
  // Get key by type
  getKey(type: 'posting' | 'active'): PrivateKey {
    const key = type === 'posting' ? this.postingKey : this.activeKey
    if (!key) {
      throw new Error(`${type} key not loaded`)
    }
    return key
  }
  
  // Sign and broadcast a transaction
  async signAndBroadcast(
    tx: Transaction,
    keyType: 'posting' | 'active'
  ): Promise<string> {
    const key = this.getKey(keyType)
    tx.sign(key)
    const result = await tx.broadcast(true)
    return result.tx_id
  }
}

// Usage
const keyManager = new KeyManager('alice')
keyManager.loadFromEnv()

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

const txId = await keyManager.signAndBroadcast(tx, 'posting')
console.log('Transaction ID:', txId)
```

## Next Steps

* Learn about [Memo Encryption](/guides/memo-encryption) for private messages
* Set up [Multi-signature](/guides/multi-signature) transactions
* Explore [API Calls](/guides/api-calls) to query blockchain data
