start js bitstring library
This commit is contained in:
+156
-2
@@ -1,15 +1,71 @@
|
||||
/**
|
||||
* Binary utilities
|
||||
* Miscellaneous binary utility functions
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
export {
|
||||
bytes_to_bigint,
|
||||
bigint_to_bytes
|
||||
bigint_to_bytes,
|
||||
concat,
|
||||
strong_rand_bytes
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Concatenate two arrays
|
||||
*/
|
||||
function
|
||||
concat
|
||||
(arr1 : Uint8Array,
|
||||
arr2 : Uint8Array)
|
||||
: Uint8Array
|
||||
{
|
||||
let len1 : number = arr1.length;
|
||||
let len2 : number = arr2.length;
|
||||
let arr1_idx0_offset : number = 0;
|
||||
let arr2_idx0_offset : number = len1;
|
||||
let result_len : number = len1 + len2;
|
||||
let result : Uint8Array = new Uint8Array(result_len);
|
||||
// copy first array into result
|
||||
for (let arr1_idx0 = 0;
|
||||
arr1_idx0 < len1;
|
||||
arr1_idx0++)
|
||||
{
|
||||
// no offset here
|
||||
let result_idx0 : number = arr1_idx0 + arr1_idx0_offset;
|
||||
result[result_idx0] = arr1[arr1_idx0];
|
||||
}
|
||||
// copy second array into result
|
||||
for (let arr2_idx0 = 0;
|
||||
arr2_idx0 < len2;
|
||||
arr2_idx0++)
|
||||
{
|
||||
// offset by the length of the first array
|
||||
let result_idx0 : number = arr2_idx0 + arr2_idx0_offset;
|
||||
result[result_idx0] = arr2[arr2_idx0];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Cryptographically random bytes
|
||||
*/
|
||||
function
|
||||
strong_rand_bytes
|
||||
(how_many : number)
|
||||
: Uint8Array
|
||||
{
|
||||
let arr = new Uint8Array(how_many);
|
||||
Crypto.getRandomValues(arr);
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convert a byte array to a bigint
|
||||
*
|
||||
@@ -58,3 +114,101 @@ bigint_to_bytes
|
||||
arr_reverse.reverse();
|
||||
return new Uint8Array(arr_reverse);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Oh no, bitstrings in a language that only has bytestrings
|
||||
*
|
||||
* By convention these are `Uint8Array`s with byte length `ceil(bit_length /
|
||||
* 8)`, and all trailing bits are zero.
|
||||
*/
|
||||
type bits =
|
||||
{bit_length : number,
|
||||
bytes : Uint8Array};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a bitstring of a given length where every value is 0.
|
||||
*/
|
||||
function
|
||||
zeros
|
||||
(bit_length : number)
|
||||
: bits
|
||||
{
|
||||
let byte_length : number = Math.ceil(bit_length / 8);
|
||||
let result : Uint8Array = new Uint8Array(byte_length);
|
||||
for (let i0 = 0;
|
||||
i0 < byte_length;
|
||||
i0++)
|
||||
{
|
||||
result[i0] = 0;
|
||||
}
|
||||
return {bit_length : bit_length,
|
||||
bytes : result};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a bitstring of a given length where every value is 1.
|
||||
*/
|
||||
function
|
||||
ones
|
||||
(bit_length : number)
|
||||
: bits
|
||||
{
|
||||
let byte_length : number = Math.ceil(bit_length / 8);
|
||||
let result : Uint8Array = new Uint8Array(byte_length);
|
||||
|
||||
// fill everything except the last byte with 255s
|
||||
for (let i0 = 0;
|
||||
i0 < (byte_length - 1);
|
||||
i0++)
|
||||
{
|
||||
result[i0] = 255;
|
||||
}
|
||||
|
||||
// alright so the last byte
|
||||
// ok so the number of leading 0s is
|
||||
// 8 - (bit_length % 8)
|
||||
let num_trailing_zero_bits : number = 8 - (bit_length % 8);
|
||||
// the trailing byte is 255 << that
|
||||
// e.g. 3 trailing 0s
|
||||
// 1111_1111 -> 1111_1000
|
||||
let last_byte : number = 255 << num_trailing_zero_bits;
|
||||
let last_byte_idx0 : number = byte_length - 1;
|
||||
result[last_byte_idx0] = last_byte;
|
||||
|
||||
return {bit_length : bit_length,
|
||||
bytes : result};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the bit at a given 0-index
|
||||
*/
|
||||
function
|
||||
bit_i0th
|
||||
(bit_idx0 : number,
|
||||
bits : bits)
|
||||
: number
|
||||
{
|
||||
// first task is figuring out what byte we're at
|
||||
// for instance if we want bit 27
|
||||
// 3*8 = 24 =< 27 < 4*8
|
||||
// so it's Math.floor(bit_idx0 / 8)
|
||||
let byte_idx0 : number = Math.floor(bit_idx0 / 8);
|
||||
// let's fetch the byte and work with that
|
||||
let the_byte : number = bits.bytes[byte_idx0];
|
||||
|
||||
// ok so let's go with 27 again
|
||||
// 27 = 3 mod 8
|
||||
// so we bitshift right by (8 - 3)
|
||||
// and then take the remainder dividing by 2
|
||||
// --B-_---- -> ----_---B -> 0000_000B
|
||||
let bsr : number = 8 - (bit_idx0 % 8);
|
||||
return (the_byte >> bsr) % 2;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Vanillae Seed Phrase Library
|
||||
*
|
||||
* Refs:
|
||||
* 1. BIP 39: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Get a given number of seed bits.
|
||||
*
|
||||
* `how_many` must be a multiple of 33.
|
||||
*
|
||||
* Ref: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#generating-the-mnemonic
|
||||
*/
|
||||
function
|
||||
seed_and_check_bits
|
||||
(how_many : number)
|
||||
: Uint8Array
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user