> ## 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.

# Memo Encryption

> Guide to encrypting and decrypting private memo messages in Hive transfers

The Memo class provides secure message encryption for private communication between Hive users. This guide shows you how to encrypt and decrypt memos using AES encryption with ECDH key exchange.

## Understanding Memo Encryption

Hive uses the following encryption scheme for memos:

1. **ECDH Key Exchange**: Compute shared secret from sender's private key and recipient's public key
2. **AES Encryption**: Encrypt message using the shared secret
3. **Base58 Encoding**: Encode encrypted data for transmission

<Note>
  Memos must start with `#` to be encrypted. Messages without `#` are sent as plain text.
</Note>

## Basic Memo Encryption

<Steps>
  <Step title="Import required classes">
    ```typescript theme={null}
    import { Memo, PrivateKey, PublicKey } from 'hive-tx'
    ```
  </Step>

  <Step title="Get sender's private key and recipient's public key">
    ```typescript theme={null}
    // Sender's memo private key
    const senderPrivateKey = PrivateKey.fromLogin('alice', 'password', 'memo')

    // Recipient's memo public key (get from blockchain)
    const recipientPublicKey = PublicKey.fromString(
      'STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA'
    )
    ```
  </Step>

  <Step title="Encrypt the message">
    ```typescript theme={null}
    const message = '#This is a secret message'
    const encrypted = Memo.encode(
      senderPrivateKey,
      recipientPublicKey,
      message
    )

    console.log(encrypted)
    // Output: #7vR3...9xKp (long base58 string)
    ```
  </Step>

  <Step title="Use encrypted memo in transfer">
    ```typescript theme={null}
    import { Transaction } from 'hive-tx'

    const tx = new Transaction()
    await tx.addOperation('transfer', {
      from: 'alice',
      to: 'bob',
      amount: '1.000 HIVE',
      memo: encrypted  // Encrypted memo
    })
    ```
  </Step>
</Steps>

## Decrypting Memos

The recipient can decrypt the memo using their private memo key:

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

// Recipient's private memo key
const recipientPrivateKey = PrivateKey.fromLogin('bob', 'password', 'memo')

// Encrypted memo received in transfer
const encryptedMemo = '#7vR3...9xKp'

// Decrypt
const decrypted = Memo.decode(recipientPrivateKey, encryptedMemo)
console.log(decrypted)
// Output: #This is a secret message
```

<Note>
  The decrypted message includes the `#` prefix. Remove it if needed: `decrypted.substring(1)`
</Note>

## Plain Text Memos

Messages without `#` prefix are not encrypted:

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

const plainMemo = 'Public payment note'

// Encode returns the message unchanged (no encryption)
const result = Memo.encode(privateKey, publicKey, plainMemo)
console.log(result) // 'Public payment note'

// Decode also returns unchanged
const decoded = Memo.decode(privateKey, plainMemo)
console.log(decoded) // 'Public payment note'
```

## Complete Transfer with Encrypted Memo

Here's a complete example of sending a transfer with an encrypted memo:

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

async function sendPrivateTransfer(
  from: string,
  to: string,
  amount: string,
  message: string,
  senderPassword: string
) {
  // Get sender's keys
  const activeKey = PrivateKey.fromLogin(from, senderPassword, 'active')
  const memoKey = PrivateKey.fromLogin(from, senderPassword, 'memo')
  
  // Get recipient's public memo key from blockchain
  const accounts = await callRPC('condenser_api.get_accounts', [[to]])
  const recipientMemoKey = PublicKey.fromString(accounts[0].memo_key)
  
  // Encrypt the message
  const encryptedMemo = Memo.encode(
    memoKey,
    recipientMemoKey,
    '#' + message  // Add # prefix for encryption
  )
  
  // Create and send transaction
  const tx = new Transaction()
  await tx.addOperation('transfer', {
    from,
    to,
    amount,
    memo: encryptedMemo
  })
  
  tx.sign(activeKey)
  const result = await tx.broadcast(true)
  
  return result.tx_id
}

// Usage
const txId = await sendPrivateTransfer(
  'alice',
  'bob',
  '5.000 HIVE',
  'Payment for consulting services',
  'alice-password'
)

console.log('Transfer sent:', txId)
```

## Decrypting Received Memos

Retrieve and decrypt memos from incoming transfers:

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

async function getPrivateTransfers(
  account: string,
  password: string,
  limit: number = 100
) {
  // Get account history
  const history = await callRPC('condenser_api.get_account_history', [
    account,
    -1,    // start from most recent
    limit
  ])
  
  // Get memo private key
  const memoKey = PrivateKey.fromLogin(account, password, 'memo')
  
  // Filter and decrypt transfers
  const transfers = history
    .filter((item: any) => {
      return item[1].op[0] === 'transfer' &&
             item[1].op[1].to === account
    })
    .map((item: any) => {
      const op = item[1].op[1]
      let memo = op.memo
      
      // Decrypt if encrypted
      if (memo.startsWith('#')) {
        try {
          memo = Memo.decode(memoKey, memo)
          // Remove # prefix
          memo = memo.substring(1)
        } catch (error) {
          memo = '[Decryption failed]'
        }
      }
      
      return {
        from: op.from,
        amount: op.amount,
        memo,
        timestamp: item[1].timestamp
      }
    })
  
  return transfers
}

// Usage
const transfers = await getPrivateTransfers('bob', 'bob-password', 50)
transfers.forEach(t => {
  console.log(`${t.from} -> ${t.amount}: ${t.memo}`)
})
```

## Working with Shared Secrets

Understand how shared secrets work under the hood:

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

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

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

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

// These are identical
console.log('Secrets match:', 
  Buffer.from(aliceShared).equals(Buffer.from(bobShared))
) // true

console.log('Secret length:', aliceShared.length) // 64 bytes
```

<Note>
  The shared secret is a 64-byte hash computed using ECDH key exchange. The Memo class uses this internally for AES encryption.
</Note>

## Sender Can Also Decrypt

Both sender and recipient can decrypt the memo:

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

const alicePrivate = PrivateKey.fromLogin('alice', 'password', 'memo')
const bobPrivate = PrivateKey.fromLogin('bob', 'password', 'memo')
const bobPublic = bobPrivate.createPublic()

// Alice encrypts
const encrypted = Memo.encode(alicePrivate, bobPublic, '#Secret message')

// Bob decrypts (recipient)
const bobDecrypted = Memo.decode(bobPrivate, encrypted)
console.log(bobDecrypted) // '#Secret message'

// Alice can also decrypt (sender)
const aliceDecrypted = Memo.decode(alicePrivate, encrypted)
console.log(aliceDecrypted) // '#Secret message'
```

<Tip>
  This allows senders to keep records of encrypted messages they've sent.
</Tip>

## Security Considerations

<Warning>
  **Memo keys are separate from posting/active keys**. Always use memo keys for encryption, never posting or active keys.
</Warning>

<Warning>
  **Memos are stored on the blockchain forever**. Even encrypted memos will be visible to anyone who has both the sender's and recipient's private keys.
</Warning>

<Warning>
  **Never send highly sensitive data** like passwords, seed phrases, or financial credentials via memos, even encrypted.
</Warning>

<Tip>
  For maximum privacy, consider using off-chain messaging systems for truly confidential communications.
</Tip>

## Unicode and Special Characters

Memos support Unicode characters:

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

const privateKey = PrivateKey.from('5J...')
const publicKey = PublicKey.fromString('STM...')

// Unicode characters work
const encrypted = Memo.encode(
  privateKey,
  publicKey,
  '#Hello 世界! 🌍 Привет'
)

const decrypted = Memo.decode(privateKey, encrypted)
console.log(decrypted) // '#Hello 世界! 🌍 Привет'
```

## Error Handling

Handle encryption and decryption errors:

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

try {
  const encrypted = Memo.encode(
    PrivateKey.from('5J...'),
    PublicKey.fromString('STM...'),
    '#My message'
  )
} catch (error) {
  if (error.message.includes('does not support encryption')) {
    console.error('Encryption not available in this environment')
  } else {
    console.error('Encryption failed:', error.message)
  }
}

try {
  const decrypted = Memo.decode(
    PrivateKey.from('5J...'),
    '#corrupted-data'
  )
} catch (error) {
  console.error('Decryption failed:', error.message)
  // Memo might be encrypted with different keys
}
```

## Testing Memo Encryption

The library includes a self-test for encryption:

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

// This runs automatically on first encode/decode call
// Tests encryption roundtrip with known keys
const testWif = '5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw'
const testPubkey = 'STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA'

try {
  const encrypted = Memo.encode(testWif, testPubkey, '#memo爱')
  const decrypted = Memo.decode(testWif, encrypted)
  
  if (decrypted === '#memo爱') {
    console.log('Encryption test passed')
  }
} catch (error) {
  console.error('Encryption not supported in this environment')
}
```

## Next Steps

* Learn about [Key Management](/guides/key-management) best practices
* Explore [Creating Transactions](/guides/creating-transactions)
* Set up [Multi-signature](/guides/multi-signature) transactions
