Big Integers in Go language: a developer’s Reference for Printing, Converting and Serializing

Ido Zilberberg
The Orbs Blog
Published in
5 min readAug 6, 2018
Banner by Marina Rudinsky

At Orbs, we are building a blockchain for large-scale consumer apps. An inseparable part of this is dealing with aspects of encryption such as key generation, encryption/decryption, and digital signatures.

As part of our blockchain solution, we are implementing a Distributed Key Generation scheme. This necessitates dealing with very large numbers (specifically integers) in the Go language — our language of choice.

While Go has standard library support for dealing with big integers, I found documentation to be lacking when having to deal with conversions, printing, and calculations.

This post attempts to organize useful operations in one place for the benefit of the reader who needs to deal with big integers in Go.

Creating secure encryption keys is out of scope and is not a subject to be taken lightly, especially if they are meant to protect significant value. Also handing large floating-point numbers is not covered.

The package that deals with big integers in Go is “math/big”. The type we are dealing with here is big.Int.

Converting to and from other types

The Go code I needed to write compiles to an executable which is invoked from NodeJS as a utility for crypto-related calculations. This required serializing big integers between JavaScript and Go. The most straightforward method is transferring this data in string format, usually as properties of some JSON object. Here are some examples for converting values to and from big.Int.

Converting from int

Converting an int to big.Int is simple, but has to pass through int64, like so:

newBigInt := big.newInt(int64(someInt))

Converting to int

To convert a big integer to uint64, run this code:

var smallnum, _ = new(big.Int).SetString("2188824200011112223", 10)
num := smallnum.Uint64()

Note that Go does not perform bounds checking — if the value of the big integer does not fit inside a uint64 you will not get any warning and num will overflow and hold an incorrect value.

To convert to a signed 64-bit integer use Int64()instead of Uint64().

Converting from a string

Assuming you hold a big integer as a string, you create a big.Int out of it like so:

var bignum, ok = new(big.Int).SetString("218882428714186575617", 0)

If the string input tosetString() starts with “0x”, base 16 (hexadecimal) will be used. If the string starts with “0” base 8 (octal) will be used. Otherwise it will use base 10 (decimal). You can also specify the base manually (up to 62). The returned value is of type *big.Int. If Go fails to create the big.Int, ok is set to false.

Converting to a string

Converting to a string lets you serialize as JSON, print to console, and more, so it is very useful.

To convert a big.Int to a string in hex notation, use:

str1 := prime1.Text(16) // or: str1 := fmt.Sprintf("0x%x", bigInt)

To convert to a decimal notation, use:

str1 := prime1.Text(10) // fmt.Sprintf("%v", bigInt)

Using JSON

JSON format is very useful for passing values between different languages, especially when JavaScript is one of them.

Adhering to string format in JSON properties that hold big integers can be useful for printing, debugging and in conversions between Go and JavaScript.

In the following snippet notice the difference in output between printing objPt and objStrPt (lines 38–39).

The object objPt holds big integers without double quotes, whereas objStrPt holds them with double quotes.

I found the format of objStrPt to be easier to print for debugging, because string properties of objStrPt are printed as-is, whereas number properties of objPt are printed in exponential notation (e.g. 2.345677e⁷⁶) instead of actual digits and in case of keys, you would want to precise value to be printed.

Create, print and serialize a big.Int that holds a large prime

Interacting with other languages

Go — JavaScript

The easiest way I found to pass big integers to and from JavaScript was through JSON serialization to strings, as explained above. This lends itself to easy debugging as you can print out the values. The downside is being very inefficient in terms of space.

JavaScript — Solidity

While this may be a little off-topic as no Go is involved here, it is still useful to demonstrate passing 256-bit values (very common key length) as big integers using web3 library (in JavaScript) and Solidity, as these play a significant role in crypto.

Assuming your JavaScript code receives big integers as strings, as explained above, it can then convert them to web3 big integers like so:

// Convert string to web3’s big integer
const secretKey = web3.toBigNumber(secretKeyStr);
// Call the smart contract (assuming you use Truffle to generate a contract instance - beyond our scope here)
myContract.someMethod(secretKey, {props...}, (err, result)=>{...});

This would work if the Solidity code on the other side accepts a uint256 value:

contract someContract {...
function someMethod(uint256 sk} {...}
...
}

Generating random numbers

Warning: this code is not to be used to generate truly random numbers, as used for generating secret keys for protecting cryptocurrency or any other value in general. The numbers generated here are not truly random because the seed used to generate them is not random. You can observe this easily by consecutively running this snippet several times in the Go playground, then observe that you generate the same “random” numbers.

Generating random numbers (under the above warning) can be done like so:

Generating a random big integer

Notice the difference between math/rand and crypto/rand packages. Crypto claims to be geared toward protecting sensitive data but you will need to educate yourself further to be certain of that.

Performing calculations

See this snippet on how to multiply large primes.

Calling prime1.Mul() will overwrite the value of prime1 with the product of multiplication, so if you want the result to be stored in another variable, use:

Multiplying 2 large primes (big integers)

This shows the multiplication of 2 large primes and their product. Other arithmetic operations are similar.

That’s it! I hope this short post about Go conversions was. useful! Of course, all comments are welcome.

Found this interesting? Check out our projects on GitHub:

--

--