As part of the Chainlink Virtual Hackathon, developers Kyle Santiago, Thomas Potter, William Santiago, and Thomas Greco used Chainlink VRF to create secure one-time pad encryption keys. Using blockchain RNG to secure message encryption is an exciting use case as encryption relies on random number generation as a core mathematical and security assumption. In this post, Kyle Santiago explain how their team generated verifiably random encryption keys on-chain using Chainlink VRF.

By Kyle Santiago

Before the advent of asymmetric cryptography, which enables blockchain technology, there was no real way to trustlessly send messages over insecure channels. The way most encryption algorithms worked before this innovation was by using symmetric cryptography. One significant encryption method using symmetric cryptography is the One-Time Pad (OTP).

One-Time Pads are unbreakable ciphers where a random key, which is at least the same length of the message, is used to encrypt a message. As the name suggests, the key is used only once to ensure that it remains uncrackable.

## How to Encrypt Plaintext Messages

Encrypting a plaintext message is straightforward. First, we convert the letters of the original message into numbers. Then we generate a random key to add to the original message, creating a new and encrypted version of the original plaintext message. Only the people who know the key can decrypt the message.

For example, to encrypt the message “hello there”, the message needs to be converted to its number equivalent of the 26 letter alphabet and split up into pairs. In this case, that message would become “08 05 12 12 15 20 08 05 18 05”. Then we generate a random number key of at least the same length as the message to add to the original message. Let’s say we generate a key that is “07 15 12 09 01 06 11 08 03 02”. Adding them together using simple arithmetic, we get:

08 05 12 12 15 20 08 05 18 05
07 15 12 09 01 06 11 08 03 02 +
15 20 24 21 16 26 19 13 21 07

“15 20 24 21 16 26 19 13 21 07” is “O T X U P Z S M U G” when converted back to alphabet characters. Before sending this encrypted message to another party, you need to share the key with them so they can decrypt the message. Then we send the encrypted message to the other party who uses the shared key to decrypt it.

This process is similar to encrypting the original message; the only difference being that subtraction is used instead of addition. Subtracting the encrypted message by the key using simple arithmetic, we get:

15 20 24 21 16 26 19 13 21 07
07 15 12 09 01 06 11 08 03 02 –
08 05 12 12 15 20 08 05 18 05

Converting “08 05 12 12 15 00 08 05 18 05” gives us the original message as “hellothere”. As long as we never use the key again to encrypt the message, this encrypted message is virtually uncrackable.

## The Importance of Generating Good Keys

Simple plaintext encryption in this manner can be effective for simple needs. Still, some security dependencies leave our encryption open for attack. Insecure random number generation is one of these attack vectors. Remember the part where we generated a random key? What happens if that key is generated in an insecure manner? What if our randomization method isn’t really random? And what if the attackers know the pattern of the so-called randomization method?

This is known as pseudorandom number generation, and it turns out that many, supposedly, random numbers are really not. Using a pseudorandom number generator makes the encrypted message much easier to crack for anyone who infiltrated the message. This is a case where Chainlink VRF can enhance encryption security.

Chainlink VRF allows us to generate randomness while proving that it was created in a tamper-proof way. The way it works is that a user sends a seed number from a smart contract to Chainlink oracles, which use it to generate a random number. That number is then sent back on-chain to the smart contract along with the proof that it was generated with the user-provided seed. The proof allows for the user’s smart contract to verify randomness to ensure that the number was not generated in a predictable and/or malicious manner.

We designed our project, the Chainlink-OTP project, to mitigate the pseudorandom number generator problem that most One-Time Pad generators have. We used Chainlink VRF to request random numbers from Chainlink oracles and used those random numbers to generate the pads. Users can verify that we created pads using provably fair randomness to encrypt their secure messages.

Chainlink-OTP currently calls the Chainlink VRF to a smart contract to create a verifiably random encryption key, which will eventually help us build a messaging system to encrypt and decrypt plaintext messages.

## The Code

Now that we’ve established a high-level overview of the project, let’s get into the code itself. Here is a link to the GitHub repository where the front end web app is stored. Let’s walk through each step to generate the one-time pads using the random number generated from Chainlink VRF.First, the smart contract containing the VRF code needs to be deployed on-chain; we used the Kovan testnet chain. Use this documentation for reference on deploying the contract: https://docs.chain.link/docs/get-a-random-number. Once the contract is deployed on-chain, we can use that in the code.

`````````const VRFaddress = "0x2487d4ec9c4a721595925005be6fd2eba0c5628b";
const vrfContract = new eth.Contract(abi, VRFaddress);

var seed = parseInt(Math.random());

const tx = {
// this would be the user’s address
from: null,
// data for the specific VRF number function we want to use
data: vrfContract.methods.getRandomNumber(seed).encodeABI()
};

const vrfNumber = async () => {
var allowed = true;
await window.web3.eth.getAccounts().then(async e => {
if(!e[0]){
window.ethereum && window.ethereum.enable();
allowed = false;
return;
}
tx.from = e[0];
var result = await window.web3.eth.sendTransaction(tx);
return result;
})
if(!allowed)
return [];
var result = await vrfContract.methods.randomResult().call();
return result;
}`````````

This code is from the smartContract.js file where the `vrfNumber` function sends a transaction from the user’s address to the deployed VRF contract to request a new VRF number. Once the new VRF number is posted back on-chain, we’ll use it to generate the one-time pads.

For the actual pad generation, the front end web app calls a function `genPads(length)` which takes a length (default 7) and returns character arrays which are used as pads. The function generates the pads by taking the VRF number returned by calling `vrfNumber` and changing each number with its corresponding ASCII character and storing it into an array. It then calls `chunkArray()` which turns the large array into small chunks, the length of which is defined by the length parameter. Finally, it deletes any remaining arrays whose length is smaller than the length parameter. The full code can be found in the VRF.js file.

`````````async function genPads(length){
var vrfNum = await vrfNumber();
const arrayOfDigits = Array.from(String(vrfNum), Number);
var arrayOfLetters = [];
for(let i = 0; i < arrayOfDigits.length; i++)
arrayOfLetters.push(String.fromCharCode(97 + arrayOfDigits[i]))
arrayOfLetters = chunkArray(arrayOfLetters, length);
for(let i = 0; i < arrayOfLetters.length; i++){
if(arrayOfLetters[i].length < length)
delete arrayOfLetters[i];
}
return arrayOfLetters;
}`````````

We now have one-time pads that allow us to encrypt a message, and if we share the pad with a contact, they can decrypt the message.

In future development, we will allow users to not only generate pads but also to type a message that could be encrypted using those pads. This would automate the way users encrypt and decrypt their messages and make the whole process a seamless messaging app.

Initially, we anticipate counting up the number of characters in the entire message to make a rough estimate of the needed VRF number length to call the oracles enough times to cover each character of the original message. This way, users who wanted to encrypt larger messages would need to pay more gas fees than those who wanted a small message encrypted due to the amount of Chainlink VRF calls required. There are also opportunities to use a gas price estimator and several other features that access on-chain data.

Overall, we had a great time implementing Chainlink VRF and were pleased with how easy it was to integrate into our web app. We plan on building more applications using Chainlink VRF and expanding the use cases with universally connected smart contracts powered by Chainlink.

If you are a smart contract developer and want to take advantage of Chainlink VRF for generating verifiable randomness for one-time pads and other applications, visit the Chainlink developer documentation.

Website | Twitter | Discord | Reddit | YouTube | Telegram | Events | GitHub | Price Feeds | DeFi

Mr Bitcointehttps://www.bitcointe.com/
“Fact You Need To Know About Cryptocurrency - The first Bitcoin purchase was for pizza.” ― Mohsin Jameel
468Fans
76Followers
4,567Followers
5,261Followers
1,558Followers
2,230Subscribers
USD - United States Dollar
EUR
1.21
GBP
1.37
CHF
1.12
NOK
0.12
JPY
0.01
0.78
AUD
0.77

### What is Bitcoin’s biggest flaw? Here’s what Cardano’s Hoskinson says

Bitcoin (BTC) \$ 30,814.00
Ethereum (ETH) \$ 1,294.54
XRP (XRP) \$ 0.254034
Tether (USDT) \$ 1.01
Bitcoin Cash (BCH) \$ 385.14
Bitcoin SV (BSV) \$ 162.86
Litecoin (LTC) \$ 125.81
EOS (EOS) \$ 2.53
Binance Coin (BNB) \$ 40.83
OKB (OKB) \$ 5.32
Tezos (XTZ) \$ 2.78
LEO Token (LEO) \$ 1.42
Monero (XMR) \$ 130.37
Stellar (XLM) \$ 0.245288
Huobi Token (HT) \$ 5.49
TRON (TRX) \$ 0.028596
USD Coin (USDC) \$ 0.997746
Dash (DASH) \$ 98.45
NEO (NEO) \$ 21.32
IOTA (MIOTA) \$ 0.398283
NEM (XEM) \$ 0.236616
Zcash (ZEC) \$ 81.10
Maker (MKR) \$ 1,381.52
Paxos Standard (PAX) \$ 0.999778
Ethereum Classic (ETC) \$ 6.96
VeChain (VET) \$ 0.027277
TrueUSD (TUSD) \$ 1.01
FTX Token (FTT) \$ 9.67
KuCoin Token (KCS) \$ 1.13
Waves (WAVES) \$ 6.27