tornado-classic-ui/utils/crypto.js

102 lines
2.9 KiB
JavaScript

import crypto from 'crypto'
import { BN, toBN } from 'web3-utils'
import { pedersen } from '@/services'
const CUT_LENGTH = 31
export function parseNote(note) {
const [, currency, amount, netId, hexNote] = note.split('-')
return {
...parseHexNote(hexNote),
netId,
amount,
currency
}
}
export function parseHexNote(hexNote) {
const buffNote = Buffer.from(hexNote.slice(2), 'hex')
const commitment = buffPedersenHash(buffNote)
const nullifierBuff = buffNote.slice(0, CUT_LENGTH)
const nullifierHash = BigInt(buffPedersenHash(nullifierBuff))
const nullifier = BigInt(leInt2Buff(buffNote.slice(0, CUT_LENGTH)))
const secret = BigInt(leInt2Buff(buffNote.slice(CUT_LENGTH, CUT_LENGTH * 2)))
return {
secret,
nullifier,
commitment,
nullifierBuff,
nullifierHash,
commitmentHex: toFixedHex(commitment),
nullifierHex: toFixedHex(nullifierHash)
}
}
export function leInt2Buff(value) {
return new BN(value, 16, 'le')
}
export function randomBN(nbytes = 31) {
return toBN(leInt2Buff(crypto.randomBytes(nbytes)).toString())
}
export function buffPedersenHash(buffer) {
const [hash] = pedersen.unpackPoint(buffer)
return pedersen.toStringBuffer(hash)
}
export function toFixedHex(value, length = 32) {
const isBuffer = value instanceof Buffer
const str = isBuffer ? value.toString('hex') : BigInt(value).toString(16)
return '0x' + str.padStart(length * 2, '0')
}
export const isEmptyArray = (arr) => !Array.isArray(arr) || !arr.length
export function packEncryptedMessage(encryptedMessage) {
const nonceBuf = Buffer.from(encryptedMessage.nonce, 'base64')
const ephemPublicKeyBuf = Buffer.from(encryptedMessage.ephemPublicKey, 'base64')
const ciphertextBuf = Buffer.from(encryptedMessage.ciphertext, 'base64')
const messageBuff = Buffer.concat([
Buffer.alloc(24 - nonceBuf.length),
nonceBuf,
Buffer.alloc(32 - ephemPublicKeyBuf.length),
ephemPublicKeyBuf,
ciphertextBuf
])
return '0x' + messageBuff.toString('hex')
}
export function unpackEncryptedMessage(encryptedMessage) {
if (encryptedMessage.slice(0, 2) === '0x') {
encryptedMessage = encryptedMessage.slice(2)
}
const messageBuff = Buffer.from(encryptedMessage, 'hex')
const nonceBuf = messageBuff.slice(0, 24)
const ephemPublicKeyBuf = messageBuff.slice(24, 56)
const ciphertextBuf = messageBuff.slice(56)
return {
version: 'x25519-xsalsa20-poly1305',
nonce: nonceBuf.toString('base64'),
ephemPublicKey: ephemPublicKeyBuf.toString('base64'),
ciphertext: ciphertextBuf.toString('base64')
}
}
export function checkCommitments(events = []) {
events.forEach(({ leafIndex }, i) => {
// TODO reload events, need for if infura provider missing events
if (leafIndex !== i) {
console.error(`Missing deposit event for deposit #${i}`)
throw new Error(window.$nuxt.$t('failedToFetchAllDepositEvents'))
}
})
}