Browsed by
Tag: public key

Bitcore.js keys for zeros and ones.

Bitcore.js keys for zeros and ones.

Bitcore is an excellent JavaScript library that is in use in many Bitcoin-related websites. Using the tools in this library one can easily achieve almost every Bitcoin functionality. Creating key pairs, parsing blocks, creating and signing transactions and more. In this post, I’ll focus on the use of Bitcore when dealing with key pair.

 

The zero

A beginner web developer can create a simple key pair by just using:

bitcore = require("bitcore-lib");
privateKey = new bitcore.PrivateKey // Generate a random private key
privateKey.toString()
>> "23bc740f87bd68729e794eb48b5137150f17109f855a34512c3c5f93d7498291"

The privateKey comes with ample of build in methods, most of which are more than enough for basic Bitcoin implementation in many web applications.

privateKey.toAddress().toString()
>> "1LY75mCpuD3xPfLLFwbWccBNoQQY4VBeQj"
privateKey.toPublicKey().toString()
>> "0379d42509499082436c89a4e1637ed14a27e56174843bddb980ab6f155f82431c"

This codes can be implemented in a manner of minutes. Bitcoin can be incorporated into many web applications in less than a day. However, those of you with a keen eye to Bitcoin protocol probably noticed that the public key comes in its compressed format. The uncompressed public key will be twice as long (64 bytes + 1 byte) and will have 0x04 as their leading byte.

This is, of course, a non-issue for most use cases, but it might be somewhat counterproductive when learning the relations between private keys, public keys, and address.

To truly understand something, there’s no better way than to get your hands dirty. And when we’re referring to something as crucial to Bitcoin (and blockchains in general) as key pairs, no shortcuts should be made.

 

To one.

During my first experimentation with this library, I received the impression that, as good as this library is, it might not be sufficient to teach and learn the underlying mechanism of the Bitcoin blockchain itself.

However, after more careful examination I came to realize that this library provides much more granular tools than what I expected. In fact, it seems that I can use it in conjunction to the developer documentation on Bitcoin addresses.

This is done thanks to one specific method that returns the numeric value of each point in the public key (don’t forget, the uncompressed public key is just a set of x-y coordinates).

publicKey.point.x
publicKey.point.y

This is highly useful method for a number of reasons:

  1. It creates a big number object in JavaScript, thus saves us from the hassle of working with 32+ bytes (A big drawback in JavaScript is the lack of native support for any number that is 32 bytes and above).
  2. Each point is given independently; as a result, the students are more aware of the real meaning of what a public key is really is (in terms of x-y coordinates). It’s also an excellent opportunity to show the students how one coordinate can be dropped to achieve the compressed address.

Another two very useful methods are:

bitcore.crypto.Hash.sha256ripemd160(pubKey);
bitcore.crypto.Hash.sha256sha256(hashedPublicKey);
The first two methods makes the hashing process really easy to execute. The Bitcoin protocol requires double hashing to be executed at two different locations in order to turn the public key to Bitcoin address. In many other languages (such as Python, which I've been using extensively when teaching this subject), there's a need to import and define each hash function. The process is tedious, and at the end of the day, somewhat messy.

By having these two methods, we save almost 40% in code space, and the students can focus on what’s really important in this lesson.

 

And here’s the final result:

// This code represents a possible approach for teaching Keys
// using JavaScript. 
// Pay attention that even while still using a JS library such as bitcore.js 
// The code still follows all the steps defined in the developers documentation.

bitcore = bitcore = require("bitcore-lib");

privKey = bitcore.PrivateKey.fromString("8c5e5b37ebf1e7a274b9dff4910f9a2004868897f7d845802b77a1b245c26bc7");

pubKey = "04" +
        privKey.publicKey.point.x.toBuffer().toString("hex") +
        privKey.publicKey.point.y.toBuffer().toString("hex");

pubKey = new Buffer(pubKey, "hex");

hashedPublicKey = "00" + bitcore.crypto.Hash.sha256ripemd160(pubKey).toString("hex");

hashedPublicKey = new Buffer(hashedPublicKey, "hex");

checkSum = bitcore.crypto.Hash.sha256sha256(hashedPublicKey).toString("hex").slice(0,8);

checkSum = new Buffer(checkSum, "hex");

binAddress = hashedPublicKey.toString("hex") + checkSum.toString("hex");

binAddress = new Buffer(binAddress, "hex");

address = bitcore.encoding.Base58.encode(binAddress)

 

Now compare to what we might see in Python:

Private_key = bytes.fromhex("BF9795D3FCB4E2181B7B536C2247EA0001397C99BA94D4D4DD62801BB151B091")

import ecdsa

signing_key = ecdsa.SigningKey.from_string(Private_key, curve = ecdsa.SECP256k1)

verifying_key = signing_key.get_verifying_key()

public_key = bytes.fromhex("04") + verifying_key.to_string()

import hashlib

sha256_1 = hashlib.sha256(public_key)

ripemd160 = hashlib.new("ripemd160")
ripemd160.update(sha256_1.digest())

hashed_public_key = bytes.fromhex("00") + ripemd160.digest()

checksum_full = hashlib.sha256(hashlib.sha256(hashed_public_key).digest()).digest()

checksum = checksum_full[:4]

bin_addr = hashed_public_key + checksum

import base58

FINALE_BTC_ADDRESS = base58.b58encode(bin_addr)

In this instance, we can see that the code created with bitcore js is much more straightforward and readable than even the simplest Python code.
This is a clear indication that using JavaScript can be a useful tool when teaching the basics of blockchain development.
The libraries can be used when teaching both web developers as well as more protocol oriented students. The code can be presented in highly simplified manner for beginners while still alluding
to its origin and the logic behind it.

Ethereum signature validation app

Ethereum signature validation app

Import: This article is for educational purposes only. Don’t attempt to incorporate the codes and methods presented here into working applications and don’t use keys that are associated with your real Bitcoin/Ethereum wallets.

 

The key pair

Key pair (Asymmetric encryption) is one of the building blocks of current blockchain solutions and cryptocurrencies, without it, Bitcoin, Ethereum and other blockchains were not possible.

The idea behind this tool is quite simple: Encrypting information using one key (public key) and decryption it using another (private key).

This short video gives a great introduction to the concept of key pairs as well as an explanation to the mathematical background behind RSA asymmetric encryption

  • Rememebr that both Bitcoin and Ethereum aren’t using RSA encryption. Instead they’re using ECC (Elliptic Curve). The mathematical background is different for the two, yet the main principle is the same.

 

As seen in the video, asymmetric encryption has been around for quite some time and it’s by no mean a unique feature of the blockchain. However, both Bitcoin and Ethereum (and probably many other blockchains) utilize it in a slightly different way. Rather than using the public key to encrypt a message, they’re using the private key to sign a message.

This signed message has some interesting proprieties, but the one thing what makes it really useful in the blockchain context is that the public key can be used to validate to authenticity of the signer.

 

original_msg = "hello"

private_key = "0x010203..."

public_key = "0x0f0e0d..."

signed_message = sign(original_msg, private_key) = "0xaabbcc..."

validate(public_key, original_msg) = True

As you can see, the idea wasn’t necessarily to hide the information (the original message need to be presented in order to validate authenticity of the signer). Instead, we use this method to prove the owner of a specific private key is indeed the one who signed the original message.

In the blockchain sense, Bob can sign the original_msg -the transaction (which is of course publicly available to anyone who have a copy of the blockchain), and by providing his own public key and the signature, everyone can verify that that specific message was indeed signed by Bob.

 

The validator

Originally, I planned to write some basics codes demonstrating the process in Bitcoin and Ethereum, but while studying Ethereum more in depth, I encountered the Solidity ecrecover method that returns the address associated with the signed message, and I immediately sat down to create the Validator, a simple app that uses web3.js to sign a message at the client side, and then uses smart contract to get the address of the signer (btw, the ability to display the address of the one who signed the message hints at another interesting property which I might go deeper into in another post).

The source code can be found here:
https://github.com/Shultzi/validator

Step by step

The process was very simple, first I created the smart contract:

contract Validator{
    
    function constVerify(bytes32 r, bytes32 s, uint8 v, bytes32 hash) constant returns(address) {
        return ecrecover(hash, v, r, s);    
    
    function verify(bytes32 r, bytes32 s, uint8 v, bytes32 hash) returns(address) {
        return ecrecover(hash, v, r, s);
    } 
}

The contract Validator contains two functions but both are basically doing the same. The only different is that the first one is constant, that means no transaction is sent to the Ethereum network (caution! request might still be sent to a remote node if you don’t run a local Ethereum node!). This function will instantly return the address of the one who signed the original message. The other function is not a constant function, that means that a transaction will be sent to the Ethereum blockchain and the returned result will be verified by all of the users (consider the implications in terms of privacy!) the result however will not be immediately displayed to the end user – instead, in my app the user will receive the hash of the transaction. The user can then look it up on the blockchain.

The ecrecover function itself is very simple to use, all you need is the hash of the original message (hash) and the signed message (r, s, v).

The original message is hashed to ensure that uniform size, so that regardless to the size of the original message, we’ll always have a hash variable of exactly 32 bytes.

The r, s, v are all parameters of the signed message. The signed message itself (as you might already saw in the above video) is actually a combination of 3 variables.

full_sign = 0x042995e2dd996f8d234be59a623f3a2b02d3fb91187f48eaf563723b342225cc16599133550d998c880ecb1a8d29f47216f0397e30e415b95d92490f3b4ca6201b

r = 042995e2dd996f8d234be59a623f3a2b02d3fb91187f48eaf563723b342225cc //32 bytes

s = 16599133550d998c880ecb1a8d29f47216f0397e30e415b95d92490f3b4ca620 //32 bytes

v = 1b //uint8 (1 byte)

The signed message can be received using the web3.js library. I used meteor (based on nodejs) to launch my application.

Once it was launched, I declared web3 object like so:

if(typeof web3 !== 'undefined'){
  web3 = new Web3(web3.currentProvider);
}else{
	web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8080"));
};

The web3 is connected to metamask via chrome extension, but you can of course use your own preferred client like geth, parity or testrpc.

Once web3 is declared, getting the full signature is a very simple thing to do:

web3.eth.sign(web3.eth.accounts[0], web3.sha3(msgToSign.value), function(err, res){signedmsg = res;});

This is the full signature. r + s + v. We’ll need to break it into their component. Just remember that:

  • The first 32 bytes are the r value
  • The second 32 bytes are the s value
  • The last byte is v value (uint8)

You can read more about signature structure here

Breaking the signature into its r, s, v values is a fairly easy process that can be done with the following JavaScript code.

r = "0x" + signedMsg.value.slice(2, 66); //Treated as hex
s = "0x" + signedMsg.value.slice(66, 130); //treated as hex
v = new Buffer(signedMsg.value.slice(130, 132), "hex"); // we care for the numeric value. The Ethereum function expects uint8 and not hex.
v = v[0].valueOf();
h = web3.sha3(originalMsg.value); //we hash the original message to keep it as 32 bytes, regardless to the input size.

Now the only thing that is remained is to send these values along with the original message to smart contract, and get the result back.

Validator.verify(r, s, v, h, function(err,res){         		
    Template.address.set("The transaction id is: " + res);
});

Validator.constVerify(r, s, v, h, function(err,res){
    Template.address.set("The signer address: " + res);
});

The final result

http://nobelgoeshere.com/ (The site isn’t secured. Don’t sign anything of value!)

Signing and validating message in ethereum

 

Blockchain architecture and JavaScript

Blockchain architecture and JavaScript

Why (and why mot) using JavaScript

Many of my students wishes to create their own blockchain applications. Many of them came from app and web development background, and while they are still highly motivated to learn how the blockchain itself works, their main goal is not purely academic. They want to see a product in action.

When catering for such students, it’s important to adjust the course material to their own background and goals. Mainly it means to provide them with as many JavaScript tools as possible, as it’s the main engine behind many modern websites and apps.

Yet, adjusting the course shouldn’t come at the price of marginalizing the blockchain architecture itself. At the end of the day, the thing that separates such a course from millions of other web/apps development courses is just it – the blockchain.

Bearing this in mind should be a at the heart of every decision taken when creating and conducting such a course. And there’s a very little place for compromises.

This stunt approach led me to prefer teaching the students using more general programming language (mainly, python) while shy away almost completely from using JavaScript, which is fundamentally flawed for teaching protocols such as Bitcoin and the blockchain.

However, when done properly, a substantial part of the Bitcoin protocol can be explained, examined and tested using JavaScrips. And it’s important to develop the proper toolbox of JavaScript codes for that purposes.

 

// This code represents a possible approach for teaching Keys
// using JavaScript. 
// Pay attention that even while still using a JS library such as bitcore.js
// The code still follows all the steps defined in the developers documentation. 

bitcore = require("bitcore-lib");

privKey = bitcore.PrivateKey.fromString("8c5e5b37ebf1e7a274b9dff4910f9a2004868897f7d845802b77a1b245c26bc7");

pubKey = "04" +
        privKey.publicKey.point.x.toBuffer().toString("hex") +
        privKey.publicKey.point.y.toBuffer().toString("hex");

pubKey = new Buffer(pubKey, "hex");

hashedPublicKey = "00" + bitcore.crypto.Hash.sha256ripemd160(pubKey).toString("hex");

hashedPublicKey = new Buffer(hashedPublicKey, "hex");

checkSum = bitcore.crypto.Hash.sha256sha256(hashedPublicKey).toString("hex").slice(0,8);

checkSum = new Buffer(checkSum, "hex");

binAddress = hashedPublicKey.toString("hex") + checkSum.toString("hex");

binAddress = new Buffer(binAddress, "hex");

address = bitcore.encoding.Base58.encode(binAddress);

 

When to use JavaScript

The decision of when, and how to use these codes should be based on 2 main variables.

  1. What the students need to know.

The first one refers to the main reason the students came to the course. The more interested they’re in the blockchain itself, the more they can gain by working with languages such as Python/C++/go etc’. On the other hand, if applications is what they want to create, they can benefit the most by using JavaScrip.

Using JavaScript can be a great experience for them as they’ll both learn how to incorporate many robust libraries into their projects, but (maybe even more important), they’ll understand many of the limitations that surrounds JavaScript and its impact when creating a blockchain app. Limitations such as working on the client side, storing keys, accessing ssl, working with large numbers etc’.

2. What the students already know.

This one is quite simple, what’s the student background. If the student is more competent in JavaScrip, he/she might benefit more from adhering to JavaScript instead of learning another programming language.

 

Can blockchain really be taught using just JavaScript?

I’m still checking it.

I’m trying to migrate as many of the codes that are used for teaching the blockchain itself from Python (most can be found here) to JavaScript.

In the next few posts I hope to provide a more detail accounts on this project, in the hope that it might be more helpful to future students.

 

Transaction part one – The misconceptions about the block chain

Transaction part one – The misconceptions about the block chain

Three levels of abstractification.

The are three level to understand the way the Bitcoin block chain works.

The first level
One of the most simple Bitcoin block chain abstractification

In the first level, we got those who just heard about Bitcoin for the first time. People usually thinks that the coins are just associated with the Bitcoin address. Whenever Alice sends Bob coins, she just place a statement (or transaction) in the block chain specifying that the X coins that were associated with Alice address, should now be associated with Bob address. This is of course wrong since this representation contains only 3 thing: the sender address, the receiver address and the amount of coins to be transferred. But this level of abstraction is usually the first thought most people have when first presented with the idea of the block chain.

The second level
Points to previous transacions

In the second level, people starts to understand that each transaction also contains the origin of each coin. So if Alice wants to send 5 BTC to bob, she first needs to show where she got these 5 BTC from, That is, she also needs to provide a way to point to older translations on the block chain, transactions which proves that Alice is indeed the rightful owner of these five BTC. So now what we have starts to look more like a chain. It’s no longer just a table containing the address and the current BTC balance,  rather the block chain needs to contain a list of all previous transactions. This depiction is more accurate, but still it isn’t complete – introducing the third level.

The third level
Points at previous transaction and set the condition for claiming the coins.

In the third level, people learns that a transaction is more then just a simple statement in the block chain. Transaction contains more then just information about the origin of the coins (the input), the address of the receivers (the outputs) and the amount of coins to be transferred. Rather, the transaction also contains a riddle in it, and only by solving this riddle, can the coins be claimed and transferred. So when Alice send 5 BTC to Bob, she doesn’t only pointing at the transaction from which Alice got the coins, it also solves the riddle specified in that transaction to prove that Alice is allowed to claim those coins, but that’s not the end of it, in the transaction that Alice publish on the block chain she’s also inserting another riddle, a riddle that only Bob can answer. So if Bob would like to use this coins in the future, he’ll have to solve that riddle which was provided to him by Alice. And the process goes on and on and on.

I love riddles! Or, how to solve the riddle and prove that I’m allowed to claim the coins?

A quick reminder. Signing messages and key pair.

In the previous post we’ve talked about mathematical trapdoors and hashing functions. We’ve saw how we can use these types of function so sign a message with a private key and how these signed message can be verified with the corresponding public key.

F("My name is Alice", Alice's_private_key) = signed message.

Verify(signed message, "My name is Alice", Alice's_public key) = true.

Change any component in the Verify statement, and we’ll receive false. This way we can easily prove that the message “My name is Alice” was indeed signed by Alice and that no one tempered with that message.

Pay attention! We cannot sign a message with the public key, it simply wont work! the public key can only be used to verify a message, not to sign it!

So, Alice can now publish a message in the block chain that contains the input (origin of the coins) and the output (the address of the receiver). This is the original message, public for anyone to see and check as he or she pleases. Alice can also now specify the following rules in that public message:

  1. This message is the original message.
  2. Within this message I’ve included Bob’s_public_key (In hashed format – We’ll get there in a second).
  3. Take your public key and hash it. If your hashed public key matches the hashed public key from step 2, you may move to the next step.
  4.  Take this original message, and sign it with your own private key.
    F(This message, Bob’s_private_key) = signed message.
  5. The signed message should be verified only against the public key that is specified in this message.
    Verify(signed message, This message, Bob’s_public_key) = true.
  6. If the verification indeed yield true, you may claim the coins in this transaction

 Getting Bob’s public key

When Alice specify Bob as the recipient of a transaction, she does so by inserting Bob’s hashed public key. The hashed public key (as we already saw in the post dealing with keys) can be deducted from Bob’s Bitcoin address.

The public key is hashed and then added to the final Bitcoin address.
The public key is hashed and then added to the final Bitcoin address.

So basically, knowing Bob’s Bitcoin address is equal to knowing Bob’s hashed public key. All we need to do is to convert the address back from base 58, and remember that out of the 25 bytes of the binary address, we need to omit the first byte and the last 4 bytes.

Scrips – the beginning

As we’ve already saw many times in the past, Bitcoin message is no more then a string of bytes that follow a predefined order. That means that in order to specify conditions and rules like the one Alice is using in her transaction message, we also need all parties to agree on a predefined field that will contain the conditions, and we also need to agree on a way to translate the bytes in that field into a set of rules, or instructions. For this purpose, a scripting language was created for Bitcoin, this langue allocate predefined operation to a predefined byte. For example, the byte 0x8b means “plus 1”, the byte 0x8c means “minus 1”, the byte 0xa9 means “hash the public key. First with SHA-256 and then with RIPEMD-160”, and so on. There’re many more of these operators (also called OP-codes) and these OP-codes helps us to specify the rules that needs to be fulfilled. These rules are transparent and are publicly visible on the block chain. Whenever a node verify a transaction, the nodes follows these rules and make sure that they eventually do yield a true statement.

We’ll talk more about these OP-codes and scrips in the next sections, when we’ll also see a real example of valid transaction script.

 

Keys, addresses and hashing

Keys, addresses and hashing

A key pair is one of the greatest tools that are used in Bitcoin, but it might be a little unintuitive at first. Don’t worry, you’ll get it!

There’s also a short video I made a few months ago that describes the basics of keys. It doesn’t completely corresponds to our current project, but it might provide you with another point of reference. You can watch it over here – Bitcoin python tutorial for beginners – keys and address.

 

One way function

The name “one way function” is quite self explanatory. These function are very easy to solve in one way but almost impossible to invert. Giving function f, and the input x, I can easily calculate the result y.

f(x) = y <- easy to solve

But given the result y, and the function f, It will be almost impossible to find x

f(?) = y <- almost impossible to guess.

The Bitcoin protocol define the use of some of these one way functions (SHA256, ripmed, ECDSA and murmurhash. More functions are being tested and might be used in the future).  Each one of these function has its own place in the protocol. Some functions will be used more then once and/or will be combined with another function to achieve even a grater level of security. For example, signing a message (usually a transaction message) will be done using the SHA256 function, SHA256("hello!"), finding the checksum of the message payload will be done using the SHA256 function twice SHA256(SHA256(message)).

  • Some people have hard time to accept the concept of “hard to guess”, they feel it’s too ambiguous. Well, technically an extremely powerful computer might be able to iterate through all possible results until it will find the right one (this is called brute force), but in practice, it will take a very – very long time. Trying to brute force the result of a SHA256 function on a 32 bytes message will take about 10^65 years. The age of the universe is only 1.4*10^9 year. I think it’s good enough security.
It’s easy to get the result y of function f for a giving x. But almost impossible to tell what the original input was.

 

Mathematical trapdoor and key pair

Mathematical trapdoor is a special type of one way function. The main difference is that in mathematical trapdoor we may also use few extra pieces of information called keys. Bitcoin uses the mathematical trapdoor function ECDSA or Elliptic Curve Digital Signature Algorithm, to produce two keys, or a key pair -A private key, and a public key – Both keys will always come in pairs! there cannot be a public key that matches two different private keys and vice versa!

The private key is used to solve (sign) the function f for message x. The result is the signed message y.

f(private_key, x) = y <- easy to solve

Now I have two messages. The original message x, and the signed message y. I want to prove that I’m the one who signed the original message x, that I’m the owner of the private key. But I don’t want to give my own private key. Anyone who have my private key will be able to sign in my name on other messages as well. So I’m using the public key. The public key can only be used to prove the solution of the function, but it cannot be used to sign messages

f(public_key, x) = y <- easy to prove

f(public_key, x) = null <- I can't sign message x with the public key. only with the private key

  • Pay attention that when we’re using the public key we’re just proving the equation, not solving it.

Here’s a simple numeric example I found on the wikipedia page on mathematical trapdoor:

An example of a simple mathematical trapdoor is “6895601 is the product of two prime numbers. What are those numbers?” A typical solution would be to try dividing 6895601 by several prime numbers until finding the answer. However, if one is told that 1931 is one of the numbers, one can find the answer by entering “6895601 ÷ 1931” into any calculator. This example is not a sturdy trapdoor function – modern computers can guess all of the possible answers within a second – but this sample problem could be improved by using the product of two much larger primes.

 

Let’s see an example:

Step one – create a key pair:

Create key pair using the ECDSA function and some random numbers
Create key pair using the ECDSA function and some random numbers

Step two – sign a message with the private key:

using the private key and the ECDSA algorithm
using the private key and the ECDSA algorithm

Step three – send the original message alongside the encrypted message and the public key

3 items are needed to validate the message. The public key, the original message and the encrypted message
3 items are needed to validate the message. The public key, the original message and the encrypted message

The code

In our project we’ve defined the Key class under Bitpay/Utils/KeyUtils/keys.py. This class contains all the necesery steps that are required in order to generate a private key, trnsform that private key to a public key and then create a Bitcoin address out of that public key.

step one – create (or receive) the private key

The first thing that we’re going to do is to create our private key. The private key is defined as  a random 32 bytes uint. Our class begins with a simple check. If the user initialize the Key class with an already existing private key, that private key will be saved into self.private_key. Otherwise, we’re using the urandom function in the os module to create a random 32 bytes long number.

def __init__(self, private_key=0):
    if private_key == 0:
        self.private_key = os.urandom(32)
        self.printable_pk = str(binascii.hexlify(self.private_key), "ascii")
    else:
        self.printable_pk = private_key
        self.private_key = binascii.unhexlify(private_key.encode('ascii'))

You might’ve noticed that we’ve also created a printable_pk variable. This variable will store the private key in hexadecimals. This way it is easier to store, copy and/or print the private key.

 

Step two – Use the private key to initialize the signing function

After we got our private key it’s time to use it initialize our ECDSA function. This step is similar to declaring our function f with the private key pr_k.

self.sk = f(pr_k, )

We’re defining the variable self.sk (for Signing Key) and use SigningKey.from_string from the ECDSA module with two arguments, the first one is our self.private key, and the second one is the curve (We haven’t talked about the curve yet, But it represent the mathematical part of our function. This is too advance mathematics so we won’t go into it in this project. But for now we just need to know that the Bitcoin protocol requires us to use the ECDSA function with the mathematical curve SECP256k1)

self.sk = ecdsa.SigningKey.from_string(self.private_key, curve = ecdsa.SECP256k1)

 

Step three – Use the initialized function (self.sk) to get the public key

Now that we got our signing key, we can use it in order to create our public key.

self.vk = self.sk.verifying_key

We’re defining a new variable called self.vk which will hold the verifying key, or the public key that can be sent alongside the signed message and the original message. This key will be used to verify that the message was indeed signed by the owner of that public key. And since every public key matches only one specific private key, it also proves that the one who signed the message also possess the corresponding private key.

 

Step four – Formatting the public key.

The variable self.vk holds the public key that will be used to verify our signed messages. But the Bitcoin protocol requires that we’ll represent this public key in couple of different formats.

The following chart from the Bitcoin wiki site shows the way the public key should be formatted:

Converting the public key to Bitcoin address
Converting the public key to Bitcoin address

 

The first line is the real public key, or in our case the verification key self.vk

this is the real public key - but we can't send it like this. We need to do dome formatting
this is the real public key – but we can’t send it like this. We need to do dome formatting

 

The second line tells us that we need to inser the byte 0x04 at the beginning of our public key

self.public_key =  b"04" + binascii.hexlify(self.vk.to_string())

We’re using the function to_string in order to display the variable self.vk  as a string. Then we convert it to hexadecimals so it will be easier to append the byte 0x04.

This is the public key in Bitcoin terminology. Usually, When looking for the public key in signed transactions, that's what it will look like
This is the public key in Bitcoin terminology. Usually, When looking for the public key in signed transactions, that’s what it will look like

 

The third line tells us to hash the public key twice. once using the SHA256 function, and then again using the ripemd160 function.

ripemd160 = hashlib.new('ripemd160') # <-initializing the ripemd160 function 
ripemd160.update(hashlib.sha256(binascii.unhexlify(self.public_key)).digest())
First hashing the public key using the SHA256 function. Then the result is hashed with the ripemd160 function
First hashing the public key using the SHA256 function. Then the result is hashed with the ripemd160 function

The forth line tells us to add another byte at the beginning of the hashed key.

We're working with the main network so we'll add the byte 0x00
We’re working with the main network so we’ll add the byte 0x00

This is the network ID byte which is used to prevent us from using keys and addresses that were generated in the test network, in the main network (and vice versa). In our example we’re using the main network, so the byte we’ll add will be 0x00.

self.hashed_public_key = b”00″ + binascii.hexlify(ripemd160.digest())

In Bitcoin terminology, the result is the hashed public key. This format is used mostly when creating a transactions.

 

The fifth (and sixth) line tells us to take our hashed public key and hash it again, twice, using the SHA256 function. The first 4 bytes of the result will be the checksum.

self.checksum = binascii.hexlify(hashlib.sha256(hashlib.sha256(binascii.unhexlify(self.hashed_public_key)).digest()).digest()[:4])
The checksum is the first 4 bytes
The checksum is the first 4 bytes

 

The seventh line creates the Bitcoin address in its binary form by appending the hashed public key with the checksum. This is a valid Bitcoin address, but it still need to go through one more process before it can be used with most Bitcoin wallets.

self.binary_addr = binascii.unhexlify(self.hashed_public_key + self.checksum)

 

The last line Finally we’ve reached the end point. There’s only one more thing we need to do before we can get the standard Bitcoin address and that is to convert the binary code of the address into a base58 string. The idea behind this conversion is quite simple. In order to reduce human errors, it was decided that some characters will be omitted from the standard Bitcoin address. characters like capital O, the number 0, lower case l and upper case I, as well as many more characters were omitted.

The final address represented in base 58.
The final address represented in base 58.
self.addr = base58.b58encode(self.binary_addr)
  • You might need to install the base58 module using the command pip install base58.

 

User interface

We’ve also added a tab to our graphical user interface which might help. You can use it to see the public key, hashed public key and Bitcoin address or any given private address.

The user interface for the keys can be found in the second tab
The user interface for the keys can be found in the second tab