UNPKG

@iden3/js-iden3-core

Version:

Low level API to create and manipulate iden3 Claims.

133 lines (111 loc) 3.53 kB
import { Constants } from './constants'; import { checkBigIntInField, fromLittleEndian, toLittleEndian, encoder } from './utils'; import { Hex, sha256 } from '@iden3/js-crypto'; export class BytesHelper { static intToBytes(int: bigint): Uint8Array { return BytesHelper.intToNBytes(int, Constants.BYTES_LENGTH); } static intToNBytes(int: bigint, n: number): Uint8Array { return Uint8Array.from(toLittleEndian(int, n)); } static checkChecksum(bytes: Uint8Array): boolean { const { typ, genesis, checksum } = BytesHelper.decomposeBytes(bytes); if (!checksum.length || JSON.stringify(Uint8Array.from([0, 0])) === JSON.stringify(checksum)) { return false; } const c = BytesHelper.calculateChecksum(typ, genesis); return JSON.stringify(c) === JSON.stringify(checksum); } static decomposeBytes(b: Uint8Array): { typ: Uint8Array; genesis: Uint8Array; checksum: Uint8Array; } { const offset = 2; const len = b.length - offset; return { typ: b.slice(0, offset), genesis: b.slice(offset, len), checksum: b.slice(-offset) }; } static calculateChecksum(typ: Uint8Array, genesis: Uint8Array): Uint8Array { const toChecksum = [...typ, ...genesis]; const s: number = toChecksum.reduce((acc, cur) => acc + cur, 0); const checksum = [s >> 8, s & 0xff]; return Uint8Array.from(checksum.reverse()); } static hashBytes(str: string): Uint8Array { const hash = sha256(encoder.encode(str)); return new Uint8Array(hash); } static hexToBytes(str: string): Uint8Array { return Hex.decodeString(str); } static bytesToHex(bytes: Uint8Array) { const hex: string[] = []; for (let i = 0; i < bytes.length; i++) { const current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i]; hex.push((current >>> 4).toString(16)); hex.push((current & 0xf).toString(16)); } return hex.join(''); } static bytesToInt(bytes: Uint8Array): bigint { return fromLittleEndian(bytes); } } export class ElemBytes { private _bytes = new Uint8Array(Constants.BYTES_LENGTH); constructor(bytes?: Uint8Array | null) { if (bytes) { this._bytes = bytes; } if (this._bytes.length !== Constants.BYTES_LENGTH) { throw new Error('Invalid bytes length'); } } get bytes(): Uint8Array { return this._bytes; } set bytes(value: Uint8Array) { this._bytes = value; } toBigInt(): bigint { return BytesHelper.bytesToInt(this._bytes); } setBigInt(n: bigint): ElemBytes { if (!checkBigIntInField(n)) { throw Constants.ERRORS.DATA_OVERFLOW; } this._bytes = BytesHelper.intToBytes(n); return this; } slotFromHex(hex: string): ElemBytes { const bytes = Hex.decodeString(hex); if (bytes.length !== Constants.BYTES_LENGTH) { throw new Error('Invalid bytes length'); } this._bytes.set(bytes, 0); return this; } hex(): string { return Hex.encodeString(this._bytes); } // ElemBytesToInts converts slice of ElemBytes to slice of *big.Int static elemBytesToInts(elements: ElemBytes[]): bigint[] { const result: bigint[] = []; for (let i = 0; i < elements.length; i++) { const element = elements[i]; result.push(element.toBigInt()); } return result; } static fromInt(i: bigint): ElemBytes { if (!checkBigIntInField(i)) { throw Constants.ERRORS.DATA_OVERFLOW; } const bytes = BytesHelper.intToBytes(i); return new ElemBytes(bytes); } }