mtcute/packages/core/src/utils/bigint-utils.ts
Alina Sireneva d88bc0ea60
chore: code quality improvements
improved eslint config, fixed linter issues, added husky
2023-06-05 00:30:48 +00:00

82 lines
2 KiB
TypeScript

import bigInt, { BigInteger } from 'big-integer'
import { randomBytes } from './buffer-utils'
/**
* Convert a big integer to a buffer
*
* @param value Value to convert
* @param length Length of the resulting buffer (by default it's computed automatically)
* @param le Whether to use little-endian encoding
*/
export function bigIntToBuffer(
value: BigInteger,
length = 0,
le = false,
): Buffer {
const array = value.toArray(256).value
if (length !== 0 && array.length > length) { throw new Error('Value out of bounds') }
if (length !== 0) {
// padding
while (array.length !== length) array.unshift(0)
}
if (le) array.reverse()
const buffer = Buffer.alloc(length || array.length)
buffer.set(array, 0)
return buffer
}
/**
* Convert a buffer to a big integer
*
* @param buffer Buffer to convert
* @param offset Offset to start reading from
* @param length Length to read
* @param le Whether to use little-endian encoding
*/
export function bufferToBigInt(
buffer: Buffer,
offset = 0,
length = buffer.length,
le = false,
): BigInteger {
const arr = [...buffer.slice(offset, offset + length)]
if (le) arr.reverse()
return bigInt.fromArray(arr, 256)
}
/**
* Generate a random big integer of the given size (in bytes)
* @param size Size in bytes
*/
export function randomBigInt(size: number): BigInteger {
return bufferToBigInt(randomBytes(size))
}
/**
* Generate a random big integer in the range [min, max)
*
* @param max Maximum value (exclusive)
* @param min Minimum value (inclusive)
*/
export function randomBigIntInRange(
max: BigInteger,
min = bigInt.one,
): BigInteger {
const interval = max.minus(min)
if (interval.isNegative()) throw new Error('expected min < max')
const byteSize = interval.bitLength().divide(8).toJSNumber()
let result = randomBigInt(byteSize)
while (result.gt(interval)) result = result.minus(interval)
return min.plus(result)
}