Created
October 12, 2022 21:20
-
-
Save tetratorus/303f35ee0871f40e2b91a085d03ca97e to your computer and use it in GitHub Desktop.
Time-locked secret shares
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const NodeRSA = require('node-rsa'); | |
const BN = require('bn.js'); | |
const AesEncryption = require('aes-encryption'); | |
const eccrypto = require('@toruslabs/eccrypto'); | |
const seconds = 10; | |
const sqPerSecond = 20000; | |
const seqSquares = (base, mod, length) => { | |
let table = [base.umod(mod)]; | |
let prev = base.umod(mod); | |
for (let i = 1; i < length; i++) { | |
const squared = prev.pow(new BN(2)).umod(mod); | |
table.push(squared); | |
prev = squared; | |
} | |
return table; | |
} | |
const fastExp = (mod, base, x) => { | |
const binary = x.toString(2).split('').reverse(); | |
const squares = seqSquares(base, mod, binary.length); | |
let sum = new BN(1); | |
binary.map((bit, index) => { | |
if (bit === '1') { | |
sum = sum.mul(squares[index]).umod(mod); | |
} | |
}) | |
return sum; | |
} | |
const aesKey = eccrypto.generatePrivate(); | |
const aesEncryption = new AesEncryption(); | |
aesEncryption.setSecretKey(aesKey.toString('hex').padStart(64, '0')); | |
console.log('generating 2048 bit RSA key...'); | |
const rsa = new NodeRSA({ b: 2048 }); | |
const p = new BN(rsa.keyPair.p.toString(16).padStart(64, '0'), 'hex'); | |
const q = new BN(rsa.keyPair.q.toString(16).padStart(64, '0'), 'hex'); | |
const n = new BN(rsa.keyPair.n.toString(16).padStart(64, '0'), 'hex'); | |
const phi = p.sub(new BN(1)).mul(q.sub(new BN(1))); | |
const unlockedShare = eccrypto.generatePrivate(); | |
console.log('share to time-lock', unlockedShare.toString('hex')); | |
const encryptedShare = aesEncryption.encrypt(unlockedShare.toString('hex')); | |
console.log(`time-locking share for ${seconds} seconds, assuming ${sqPerSecond} squarings per second`); | |
const a = new BN(2); | |
const t = new BN(seconds * sqPerSecond); | |
const e = new BN(2).pow(t).umod(phi); | |
const b = fastExp(n, a, e); | |
const timelockedShare = new BN(aesKey).umod(n).add(b).umod(n); | |
console.log('time-locked share', timelockedShare); | |
console.log('working on time-lock...'); | |
const startTime = process.hrtime(); | |
let B = a.umod(n); | |
for (let i = 0; i < t; i++) { | |
B = B.pow(new BN(2)).umod(n); | |
} | |
let unlockedAesKey = timelockedShare.sub(B).umod(n); | |
const tryAesEncryption = new AesEncryption(); | |
tryAesEncryption.setSecretKey(unlockedAesKey.toString('hex').padStart(64, '0')); | |
const decryptedShare = tryAesEncryption.decrypt(encryptedShare); | |
console.log('unlocked share', decryptedShare.toString('hex')); | |
const timeTaken = process.hrtime(startTime); | |
console.log(`Time taken: ${timeTaken[0]} seconds, ${timeTaken[1]} nanoseconds`); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment