How Do I Find Out The Difference in Age Between Bob and Alice, Without Revealing Their Ages?

I have a function on a blockchain which determines the difference between the ages of two users. Let’s say they are Bob and Alice. We now…

How Do I Find Out The Difference in Age Between Bob and Alice, Without Revealing Their Ages?

I have a function on a blockchain which determines the difference between the ages of two users. Let’s say they are Bob and Alice. We now need to create a function which will allow us to read encrypted values, and find the difference between the values, and return an encrypted answer.

For this, we first create a key pair with a public key (pk) and a private key (sk). We then store the public key on the blockchain. Bob and Alice can then store the encrypted ages on the blockchain using the available public key. We can then use homomorphic encryption to perform a subtraction, and return back an encrypted value, and where we then use our private key (sk) to decrypt it. We will then know the difference in the ages between Bob and Alice.

For this we will use HEAAN (Homomorphic Encryption for Arithmetic of Approximate Numbers) which defines a homomorphic encryption method proposed by Cheon, Kim, Kim and Song (CKKS) in 2016 [here]:

The CKKS method uses approximate arithmetics over complex numbers, and where we have a real part (x) and an imaginary part (y). We thus get x + jy HEAAN can be used for homomorphic addition, subtraction, multiplication, and scaling. In this example we will take two values (a and b) and encrypt them. Next we will subtract the encrypted value, and decrypt the result [here]:

package main

import (
"fmt"
"github.com/lca1/lattigo/ckks"

"os"
"strconv"
)

func main() {

var logN, logQ, levels, scale uint64

// Scheme params
logN = 10
logQ = 30
levels = 8
scale = logQ
sigma := 3.19


a:=6.0
b:=7.0

argCount := len(os.Args[1:])

if (argCount>0) {
a,_=strconv.ParseFloat(os.Args[1], 64)

}
if (argCount>1) {
b,_=strconv.ParseFloat(os.Args[2], 64)

}

// Context
var ckkscontext *ckks.CkksContext
ckkscontext, _ = ckks.NewCkksContext(logN, logQ, scale, levels, sigma)

kgen := ckkscontext.NewKeyGenerator()

// Keys
var sk *ckks.SecretKey
var pk *ckks.PublicKey
sk, pk, _ = kgen.NewKeyPair()



// Encryptor
var encryptor *ckks.Encryptor
encryptor, _ = ckkscontext.NewEncryptor(pk)

// Decryptor
var decryptor *ckks.Decryptor
decryptor, _ = ckkscontext.NewDecryptor(sk)


// Values to encrypt
values1 := make([]complex128, 1<<(logN-1))
values2 := make([]complex128, 1<<(logN-1))


values1[0] = complex(a, 0)
values2[0] = complex(b, 0)


fmt.Printf("HEAAN parameters : logN = %d, logQ = %d, levels = %d (%d bits), logPrecision = %d, logScale = %d, sigma = %f \n", logN, logQ, levels, 60+(levels-1)*logQ, ckkscontext.Precision(), scale, sigma)



plaintext1 := ckkscontext.NewPlaintext(levels-1, scale)
plaintext1.EncodeComplex(values1)
plaintext2 := ckkscontext.NewPlaintext(levels-1, scale)
plaintext2.EncodeComplex(values2)

// Encryption process
var ciphertext1,ciphertext2 *ckks.Ciphertext
ciphertext1, _ = encryptor.EncryptNew(plaintext1)
ciphertext2, _ = encryptor.EncryptNew(plaintext2)

evaluator := ckkscontext.NewEvaluator()
evaluator.Sub(ciphertext1, ciphertext2, ciphertext1)


plaintext1, _ = decryptor.DecryptNew(ciphertext1)

valuesTest := plaintext1.DecodeComplex()


fmt.Printf("\nInput: %f-%f", a,b)
fmt.Printf("\nCipher: %v\n\nDecrypted: ", ciphertext1)


ch:=real(valuesTest[0])
fmt.Printf("%.2f", ch)




}

A sample run is [here]:

HEAAN parameters : logN = 10, logQ = 30, levels = 8 (270 bits), logPrecision = 13, logScale = 30, sigma = 3.190000 

Input: 3.200000-7.300000
Cipher: &{[0xc00012b500 0xc00012b520] 0xc0000962c0 30 0xc00012b540 true false}

Decrypted: -4.10

We need to start to think of a world which is full of encrypted values, but still to be able to process them.