Slightly simplified for the sake of... well, simplicity

Nowadays, many programmers don't ever expect to think about bits and bytes. After all, bits are the most basic unit of how computers store and communicate information. High level languages like Javascript and Python often manage the size of data types for the programmer, and abstract many lower level concepts. So, in most cases those programmers would be right; there is really no need to ever think about bits and the other icky low level stuffs.

However, there are some situations where programmers would need to know at least a little about these topics, such as reading a file in bytes or working with cryptography.

A bit is, apparently, a combination of the words "binary digit". Binary of course means only two states, so of course a bit has two states, 0 and 1.

8 bits make a byte, and since each bit has two possible states (0 or 1), that means 1 byte has 256 (2^8) states. Yes, that is why you see the numbers 255 or 256 used all the time.

Bytes can be represented in several different ways.

- Decimal: Decimal in this case means the base 10 system. Byte (s) can be represented as a conventional number. For example, a single byte can be represented
- Hexadecimal: Base 16! It uses the numbers 0-9 and A-F for a total of 16 digits. Conveniently, one byte will go from 00 to FF because 16^2 is 256.
- Array of Booleans: Each boolean (true/false) can represent a bit.

For Javascript, bytes are typically represented by an Uint8Array, where each number (Uint8, so from 0-255) in the array represents one byte.

Here are some examples of how to work with these Uint8Arrays, as well as some utility functions.

Useful utility functions:

function decimal_to_bits(decimal) { let binary_string = ""; while (true) { if (decimal === 0) { break; } binary_string += String(decimal % 2); decimal = Math.floor(decimal / 2); } //reverses return binary_string.split("").reverse().join(""); } //an even simpler version of the above function decimal_to_bits_simple(decimal) { return decimal.toString(2); } function bits_to_decimal(bits) { return parseInt(bits, 2); } //like `decimal_to_bits`, but ensures bits returned is 8 function decimal_to_byte(decimal) { if (decimal > 255) return; let binary_string = ""; while (true) { if (decimal === 0) { break; } binary_string += String(decimal % 2); decimal = Math.floor(decimal / 2); } //pad if not one byte long if (binary_string.length !== 8) { binary_string = binary_string+"0".repeat(8 - binary_string.length); } //reverse binary array return binary_string.split("").reverse(); } function hex_to_decimal(hex_string) { return parseInt(hex_string, 16); }

To hexadecimal:

function uint8_to_hex(uint8) { let hex_string = ""; for (let i=0; i < uint8.length; i++) { let hex = uint8[i].toString(16); //if hex is one character long, that means it is 4 bits (1/2 byte) //so, pad it with 0, so that the hex string is 8 bits (1 byte) //this ensures the returned hex string is the same amount of bytes as the uint8 array provided if (hex.length === 1) { hex = "0" + hex; } hex_string += hex; } return hex_string; }

To decimal:

function uint_to_decimal(uint8) { //convert uint8array into binary let binary_string = ""; for (let i=0; i < uint8.length; i++) { binary_string += decimal_to_byte(uint8[i]); } //then convert binary into decimal return bits_to_decimal(binary_string); }

Random bytes:

Note: Especially when dealing with cryptography, it is very important to use a secure source of randomness. Especially NOT use: Math.random or timestamps or unchanging seeds.

function random_bytes(bytes_num) { //this may not work in older browsers let uint8 = new Uint8Array(bytes_num); window.crypto.getRandomValues(uint8); return uint8; }

Please let me know if you need further help, questions, or found a mistake in the code in my Discord Server.