How to encrypt a memo when transferring Steem
Normally steem memos are sent as plain text, this article describes how to format your memos for encryption.
CLI Wallet
When using the cli wallet, if you include '#' as the first character of your memo will be encrypted.
unlocked >>> transfer from to "1.000 STEEM" "#encrypted memo" false
{
"operations": [[ "transfer",{
"from": "steemit",
"to": "steem",
"amount": "1.000 STEEM",
"memo": "#CqojqJfFwawzgnYSFUWokj...xAfynekJtySMsqK8A9doD4gHA5fDKgQTEfUKZgAm8Dx"
} ] ]
}
When the wallet is unlocked and get_account_history is called, the "memo" field will be replaced with "encrypted memo" without the initial '#'. This means that exchanges that upgrade to the latest CLI wallet can transparently support encrypted memos.
Algorithm
The algorithm for encrypting the memo involves the following steps:
1. Generate a memo_data struct containing:
public_key from
public_key to
uint64_t nonce
uint32_t check
vector<char> encrypted
- Calculate the AES encryption key as:
shared_secret = from_private_key.get_shared_secret( to );
/// concatenate nonce and shared secret (binary)
encryption_key = sha512( nonce + shared_secret )
///< check is first 64 bit of sha256 hash treated as uint64_t truncated to 32 bits.
check = sha256( encryption_key )._hash[0]
/// pack the memo as a length-prefixed string, length is serialized as varint
plain_text = pack( memo_text)
encrypted = aes_encrypt( encryption_key, plain_text )
- Serialize memo_data
Now convert the memo data into a vector and then convert it to base58
string result = '#' + to_base58( pack( memodata ) );
The to and from keys should be fetched as the memo_key property on the respective accounts.
This is a random nonce with a time-based component. It returns a unique 64 bit unsigned number string.
npm libraries used:
long
andsecure-random
The purpose of the 'nonce' field is to generate a unique encryption key for every transfer between two accounts. I it should be a random number.
Is this working properly? As far as I can tell the same key is used for every transfer. See test (both used plaintext of "abc"): https://steemd.com/@aaa