Understanding Asymmetric Encryption The Hive Way

avatar

hivechain.png

At their core, blockchain technologies rely on cryptography and encryption algorithms. While I am not a developer, I do have curiosity in understanding how blockchains work. Hive has always been a great playground to understand these concepts and see the practical implementations. Recently, I started dedicating time in understanding how encryptions work. In their simplest form there are two kinds of encryption methods: symmetric and asymmetric.

Symmetric encryption requires encrypting a message or a file using a secret phrase. Then to share this encrypted message or file with someone else, we also need to share the secret phrase. The recipient of the encrypted message or file can use the secret phrase to decrypt the message or file. There are many risks involved in sharing secret keys or phrases. Someone that wasn't suppose to or intended to have access may gain access to them and compromise this communication method. But also this may create secret key/phrase management issues, as every single message and file will need a new secret key or phrase.

Another method of encrypting is called Asymmetric Encryption. This method requires public/private key pairs, just like we see keys on Hive. On Hive every account has a public and a private keys. For example each posting private key has its public posting key as well. For encrypting and decrypting messages purposes we will use memo private and public keys.

They way asymmetric encryption works, is when I need to send an encrypted message to someone, all I need is my private memo key and recipient's public memo key. Then, the recipient will be able to decrypt the encrypted message using their private memo key. This way there is no need to share any secret keys or phrases with anybody. Everybody keep their private keys secure and only available to themselves. The public keys sort of work as destination of the message, or a mail box address, or intended recipient. Public keys, as the name suggest are public and anybody can see them.

This public/private keys combination and ability to transact peer-to-peer makes the blockchain magic happen. As long as blockchain is decentralized and there are no risks of core code protocols being tampered with, communicating in peer-to-peer encrypted manner becomes super secure. In fact, we don't even need to use Hive or any other blockchain for asymmetric encryption and decryption. There are libraries available that generated private/public key pairs for this purpose. I main use python, but I am sure other programming languages have similar libraries. But I am more interest in Hive and how we can achieve this using Hive blockchain and keys.

Many of you already might be familiar with encrypted memo messages in Hive wallet. We are able to send encrypted messages and sign them with memo private keys when making transfers in the wallet. For this, we need to start the message with a hashtag. That is not what I am trying to do here. What I want to do is to encrypt a message without storing any of the data on the Hive blockchain, then let the recipient decrypt it. So, let's look at how we can do this using Beem, Hive's python library. I believe, Holger is no longer maintaining or updating Beem. While it works for the most part, there might be things you may not be able to do.

First lets take a look how we can encrypt a message using Beem:

from beem import Hive
from beem.nodelist import NodeList
from beem.memo import Memo
import getpass


def get_hive_nodes():
    nodelist = NodeList()
    nodelist.update_nodes()
    nodes = nodelist.get_hive_nodes()
    return nodes

def encrypt_message(sender, sender_memo_wif, receiver, nodes, message):
    hive = Hive(node=nodes, keys=[sender_memo_wif])
    memo = Memo(from_account=sender,to_account=receiver, blockchain_instance=hive)
    encrypted_message = memo.encrypt(message)
    return encrypted_message

def main():
    nodes = get_hive_nodes()
    sender = 'geekgirl'
    sender_memo_wif = getpass.getpass(prompt="Enter your Hive memo key:")
    receiver = 'librarian'
    message = 'Hive is the most decentralized blockchain!'
    encrypted_message = encrypt_message(sender, sender_memo_wif, receiver, nodes, message)
    print(encrypted_message)

if __name__ == "__main__":
    main()

There is a main function and couple helper functions. If you look at the main function, first we get nodes which will allow us create an instance of Hive. Then we need account names for the sender and receiver of the message. We also need a private memo key of the sender. We get is using a prompt, for security purposes. Once we have the message, we pass all of this data to our helper encrypt function. This function creates a Hive instance using the private memo key. (I will explain why in a minute). Then we create a memo instance using sender name, receiver name, and the blockchain instance. Afterwards we simply using encrypt() method to encrypt the message. Finally, the result is returned to the main function.

The result of this encryption will in a dictionary format that will have three key/pair values: message, sender's public key, receiver's public key. Now we are ready to share this encrypted message dictionary with the recipient, who can use decryption script to find out what the message is. Ok. So, the reason I had to create a Hive instance with private memo key is that .unlock_wallet("secret") method of Memo class didn't work. I have no idea why. If you know please let me know. If that did work, I would prefer not to use private keys in Hive instance and instead unlock the wallet with memo class instance.

Now, we are ready to decrypt the message.

from beem import Hive
from beem.nodelist import NodeList
from beem.memo import Memo
import getpass

def get_hive_nodes():
    nodelist = NodeList()
    nodelist.update_nodes()
    nodes = nodelist.get_hive_nodes()
    return nodes

def decrypt_message(nodes, encrypted_message, receiver_memo_wif):
    hive = Hive(node=nodes, keys=[receiver_memo_wif])
    memo = Memo(blockchain_instance=hive)
    decrypted_message = memo.decrypt(encrypted_message['message'])
    return decrypted_message

def main():
    nodes = get_hive_nodes()
    receiver_memo_wif = getpass.getpass(prompt="Enter your Hive memo key:")
    encrypted_message = {'message': '#55sS1vFysyMbpPKeGcdNz2imc2nXcfn1YwzYgE6jTr37zeT2Bj6ThCkTmzoZmiT8eApbAtEiczVAKNxce71EByVreyJ2otpU4x1eoCEmXn33iCsv9CrQmPvw8Sh6Qk43SVUYckgzkX1xFE8DeErv6PCJFMuiHVzaZYGNyoHpuf1zi', 'from': 'STM6uRCE7yv1XhPuV3mrtQf5mE1oDxF3P3ehqX3dcizDdVb8HooYJ', 'to': 'STM5fWMqNY8J8EStWHM4ogk6cZcW3e5zP9tPzxasA6tMXL91mZCrt'}
    decrypted_message = decrypt_message(nodes, encrypted_message, receiver_memo_wif)
    print(decrypted_message)
    print(len(decrypted_message))

if __name__ == "__main__":
    main()

The code is very similar to the encryption script. This time, however, we do not need to include sender and receiver names. Only receiver's private memo key is enough to decrypt the message. You may include sender and receiver if you like. Originally, that's what I did. Then I found out they are not needed. Of course this is just the basics of encrypting and decrypting messages using Hive memo keys. But I find it to be powerful enough to get started with any ideas you may have to implement these methods in your new cool apps or use cases.

A couple of things to note. When you encrypt the message, a hashtag is automatically added as the first character of the encrypted message. When this message is decrypted, the hashtag remains. You will have to remove the hashtag after decrypting the message, as hashtag wasn't part of the original message.

I tried to keep this as simple as possible to help anybody who is new to coding or encryption methods. If you have any questions feel free to ask in the comments. I am no expert, just trying to learn and understand things. I can see benefits of using encryption in creating new cool apps. I am a fond of privacy, and encryption makes privacy possible. While the examples above only show peer-to-peer communication, it will also be possible to send encrypted message to a group of people. The way you can achieve that is: one send everybody encrypted messages separately, or send encrypted message to a dedicated account that everybody in the group has access to.

Another thing I will need to experiment with is, how changing/updating keys will affect already encrypted/decrypted messages. For example if you gave access to a group of people an access to my content, then changed my mind and wanted to revoke the access, would I be able to achieve this by simply changing my keys? Changing keys is super easy on Hive. Maybe we can talk about this next time.

Huge thanks to @ausbitbank for guiding me to the right direction when I asked him about this topic. When I couldn't figure out how to experiment asymmetric encryption on Hive, Ausbitbank was able to help me with providing a link to Beem documentation page for Memo. That is what I used when writing the codes above. Feel free to read the documentation yourself and correct my mistakes.

Lastly, according to the Beem documentation it is also possible to encrypt and decrypt binary files. I did not get a chance to experiment with that yet. But that will be the next step for me in learning more about encrypting and decrypting using Hive keys. While, this method doesn't require storing anything on Hive blockchain, it is not that difficult to do so either. I have written in the past how super easy it is to store data as custom_json on Hive. I may need to revise that using encryption in the future.

From my understanding symmetric encryption is more efficient compared to asymmetric encryption. The best way to build tools and apps maybe using the combination of symmetric and asymmetric encryptions. For example large amount of data and files can be stored in centralized databases using symmetric encryption, and only the keys that decrypt the symmetric encryption will be stored on blockchain like Hive using asymmetric encryption. Something to consider in building apps or tools. But for personal use that doesn't require scaling, modern computers should be enough to handle the load with only using asymmetric encryption.

Feel free to share your thoughts, knowledge, and experiences with encryption in general and specific to Hive in the comments.



0
0
0.000
15 comments
avatar

I really appreciate this post because you really explained better about the symmetric and asymmetric

0
0
0.000
avatar

This post has been manually curated by @bhattg from Indiaunited community. Join us on our Discord Server.

Do you know that you can earn a passive income by delegating to @indiaunited. We share 100 % of the curation rewards with the delegators.

Here are some handy links for delegations: 100HP, 250HP, 500HP, 1000HP.

Read our latest announcement post to get more information.

image.png

Please contribute to the community by upvoting this comment and posts made by @indiaunited.

0
0
0.000
avatar

Its a quite complex topic. Especially for someone who is just starting out. So I took my time well to read through.

At least I now have basic knowledge about encryption now!

Thank you @geekgirl

0
0
0.000
avatar

For someone who is not a developer you sure know code

0
0
0.000
avatar

Hive is so vast that it can sometimes overwhelm all the information I consume every day, although I will eventually understand it. Thanks for the content!

0
0
0.000
avatar

Did you read my article on the Mathematics of Bitcoin. It is the same except, I used a different elliptic curve and use 5 as the field size rather than the 76 digit number bitcoin uses.

I have found that because the web-centric nature of the Hive applications, there is a strong reason to keep Node JavaScript APIs updated. There is an even stronger incentive to keep the C++ interface working. The blockchain software itself is written in C++.

You can build HiveD and you'll get FC library at the same time. For myself, I followed the instructions here and it worked for me. C++ is really sweet with its syntax-sugar, but it is a pain with linking (but you want blockchains, you should be okay with linking.) A problem though is the 'make install' commands installs libraries to /usr/lib but not the dependencies of the libraries. A find command can copy in the library files to some library directory. Copying to /opt/hive/lib makes sense to me because I can just easily get rid of them.


using namespace std;
const string message = "{"authors":["leprechaun"],"timestamp":1639778661"
","signed_message":{"type":"posting","app":"steemfiles"}}";
const auto signature_data = "2010c2a34894b1a1a73f60cfefa0642c10842dd07f97"
"63e76ffcbf432a02beaac04dc3fe91b5c25e55210a92395eea471e8ad8d5330467d8"
"11e0559b050fe3d407";

void example2() {
cerr << "Example 2 ";

fc::sha256::encoder ssummer;        
ssummer.write(
    message.c_str(), message.length());
fc::sha256 message_hash = ssummer.result(); 


// fill a random privateKey
fc::ecc::private_key q;
q = q.generate();

fc::ecc::public_key Q = q.get_public_key();

fc::ecc::compact_signature sig = q.sign_compact( message_hash );

fc::ecc::public_key U( sig, message_hash );

if (U == Q) {
    cerr << "Valid signature: Verification Procedure Success!" << endl;
} else {
    cerr << "Recovery procedure failed!" << endl;
}

cerr << Q.to_base58() << endl;
cerr << U.to_base58() << endl;

}

int main() {
example2();
}

This verifies this signature belongs to the private key q which corresponds to the public key Q without needing the private key. I am unable to reproduce key recovery from signatures read from the block explorers though unfortunately. It must be an issue with how I am encoding the data, though I am using methods in the same library for that. I wonder what @ura-soul or @gtg would say about what is the proper way to hash a message for signatures.

Perhaps you can use this and combine it with the RPC properties for RPC access to nodes. It has classes for the transactions and operations after all.

0
0
0.000
avatar

Thank you for sharing this. Now I know who to go to when I have questions on this topic. :)
I will keep your math post as a reference. I don't speak C++ though.

0
0
0.000
avatar

Not sure if I am correct, but most wallets and one blockchain I stumbled with prior to knowing Hive use this seed phrase type of encryption. I was still adjusting myself to this method. Many of my friends are afraid of it, and yet here comes Hive that when I signed up on Splinterlands, I was surprised to be given so many keys to register an account. It’s only now that I see that they are two different methods of encryption. Thanks! Haven't started yet with Python. Though the encryption and decryption code parts of the article are tough for me, but I find them very interesting.

0
0
0.000
avatar

awesome pic! it looks like cyber CAD. so that's what the memo key is actually for? i thought it did nothing..

0
0
0.000
avatar

Is the encryption bit of the HIVE key hierarchy actually used by any application at the moment? I'm currently working on the coinZdense project, a slow moving multi year project that aims to provide a quantum-computing resistant replacement for ECDSA signatures for key-reuse-by-design chains like HIVE, and so far everything in my project is just about signing and I haven't factored in any hooks for encryption because I was under the strong impression that encryption keys remained an unused feature, even in HIVE, that technically supports it.

If there are actual HIVE DApps and/or tools plus a user base that use it though, I might need to support at least hooks for master-key to raw encryption-key derivation.

0
0
0.000
avatar

I don't have an answer for your question. I don't even fully understand it. :) I am just getting started with learning encryption. I would recommend asking the wizard of Hive, @gtg who knows everything on this topic.

0
0
0.000