Utility functions to make dealing with Uint8Arrays easier
—
Bitwise XOR operations and distance comparison functions for cryptographic applications, DHT (Distributed Hash Table) implementations, and Kademlia-style routing. These functions are essential for peer-to-peer networking and cryptographic protocols.
Performs bitwise XOR operation on two equal-length Uint8Arrays, returning a new array with the XOR result.
/**
* Returns the xor distance between two Uint8Arrays
* @param a - First array for XOR operation
* @param b - Second array for XOR operation
* @returns New Uint8Array containing XOR result
* @throws Error if arrays have different lengths
*/
function xor(a: Uint8Array, b: Uint8Array): Uint8Array;Usage Examples:
import { xor } from "uint8arrays/xor";
// Basic XOR operation
const array1 = new Uint8Array([1, 0, 1, 0]);
const array2 = new Uint8Array([0, 1, 1, 1]);
const result = xor(array1, array2);
console.log(result); // Uint8Array(4) [1, 1, 0, 1]
// Cryptographic XOR (one-time pad)
const message = new Uint8Array([72, 101, 108, 108, 111]); // "Hello"
const key = new Uint8Array([31, 42, 17, 5, 89]);
const encrypted = xor(message, key);
const decrypted = xor(encrypted, key); // XOR with same key to decrypt
console.log(decrypted); // [72, 101, 108, 108, 111] - original message
// DHT node distance calculation
const nodeId1 = new Uint8Array([0x12, 0x34, 0x56, 0x78]);
const nodeId2 = new Uint8Array([0x9A, 0xBC, 0xDE, 0xF0]);
const distance = xor(nodeId1, nodeId2);
console.log(distance); // Uint8Array showing XOR distance
// Binary operations
const bits1 = new Uint8Array([0b10101010]);
const bits2 = new Uint8Array([0b11110000]);
const xorBits = xor(bits1, bits2);
console.log(xorBits[0].toString(2)); // "1011010" (binary result)Compares XOR distances for DHT and Kademlia applications. Determines which of two XOR results represents a smaller distance.
/**
* Compares two Uint8Arrays representing two xor distances. Returns -1 if a
* is a lower distance, 1 if b is a lower distance or 0 if the distances
* are equal.
* @param a - First XOR distance to compare
* @param b - Second XOR distance to compare
* @returns -1 if a is closer, 1 if b is closer, 0 if equal
* @throws Error if arrays have different lengths
*/
function xorCompare(a: Uint8Array, b: Uint8Array): -1 | 0 | 1;Usage Examples:
import { xor, xorCompare } from "uint8arrays";
// DHT routing example
const target = new Uint8Array([0xFF, 0xFF, 0x00, 0x00]);
const node1 = new Uint8Array([0xFF, 0xFE, 0x01, 0x23]);
const node2 = new Uint8Array([0xFF, 0xFC, 0x45, 0x67]);
// Calculate distances to target
const distance1 = xor(target, node1);
const distance2 = xor(target, node2);
// Compare which node is closer to target
const comparison = xorCompare(distance1, distance2);
console.log(comparison); // -1 (node1 is closer), 1 (node2 is closer), or 0 (equal)
// Kademlia k-bucket sorting
const targetKey = new Uint8Array([0x12, 0x34, 0x56, 0x78]);
const peers = [
new Uint8Array([0x11, 0x22, 0x33, 0x44]),
new Uint8Array([0x99, 0xAA, 0xBB, 0xCC]),
new Uint8Array([0x13, 0x35, 0x57, 0x79])
];
// Sort peers by distance to target
const sortedPeers = peers.sort((a, b) => {
const distanceA = xor(targetKey, a);
const distanceB = xor(targetKey, b);
return xorCompare(distanceA, distanceB);
});
console.log("Peers sorted by distance to target:", sortedPeers);
// Equal distance detection
const equalDist1 = new Uint8Array([0x01, 0x02, 0x03]);
const equalDist2 = new Uint8Array([0x01, 0x02, 0x03]);
console.log(xorCompare(equalDist1, equalDist2)); // 0 (equal distances)import { xor, xorCompare } from "uint8arrays";
class KademliaNode {
constructor(public id: Uint8Array) {}
findClosestPeers(targetId: Uint8Array, peers: Uint8Array[], k: number = 20): Uint8Array[] {
return peers
.map(peerId => ({
id: peerId,
distance: xor(targetId, peerId)
}))
.sort((a, b) => xorCompare(a.distance, b.distance))
.slice(0, k)
.map(peer => peer.id);
}
shouldReplaceInBucket(targetId: Uint8Array, currentPeer: Uint8Array, candidatePeer: Uint8Array): boolean {
const currentDistance = xor(targetId, currentPeer);
const candidateDistance = xor(targetId, candidatePeer);
return xorCompare(candidateDistance, currentDistance) === -1; // candidate is closer
}
}import { xor, xorCompare, fromString } from "uint8arrays";
// Find nodes responsible for storing content
function findStorageNodes(contentHash: string, availableNodes: string[]): string[] {
const contentId = fromString(contentHash, "hex");
const nodeDistances = availableNodes.map(nodeIdHex => {
const nodeId = fromString(nodeIdHex, "hex");
return {
nodeId: nodeIdHex,
distance: xor(contentId, nodeId)
};
});
// Sort by XOR distance and take closest nodes
return nodeDistances
.sort((a, b) => xorCompare(a.distance, b.distance))
.slice(0, 3) // Store on 3 closest nodes
.map(node => node.nodeId);
}import { xor, fromString, toString } from "uint8arrays";
function encryptMessage(message: string, key: Uint8Array): Uint8Array {
const messageBytes = fromString(message, "utf8");
if (messageBytes.length > key.length) {
throw new Error("Key must be at least as long as message");
}
return xor(messageBytes, key.slice(0, messageBytes.length));
}
function decryptMessage(encrypted: Uint8Array, key: Uint8Array): string {
const decrypted = xor(encrypted, key.slice(0, encrypted.length));
return toString(decrypted, "utf8");
}
// Usage
const key = new Uint8Array(256).map(() => Math.floor(Math.random() * 256));
const message = "Secret message";
const encrypted = encryptMessage(message, key);
const decrypted = decryptMessage(encrypted, key);
console.log(decrypted); // "Secret message"import { xor } from "uint8arrays/xor";
function streamCipherXOR(data: Uint8Array, keystream: Uint8Array): Uint8Array {
if (data.length !== keystream.length) {
throw new Error("Data and keystream must be same length");
}
return xor(data, keystream);
}
// Generate keystream (simplified example)
function generateKeystream(length: number, seed: number): Uint8Array {
const keystream = new Uint8Array(length);
let state = seed;
for (let i = 0; i < length; i++) {
state = (state * 1103515245 + 12345) & 0x7FFFFFFF;
keystream[i] = (state >> 16) & 0xFF;
}
return keystream;
}Both functions validate input parameters:
// Length mismatch errors
try {
xor(new Uint8Array([1, 2]), new Uint8Array([1, 2, 3]));
} catch (error) {
console.log(error.message); // "Inputs should have the same length"
}
try {
xorCompare(new Uint8Array([1]), new Uint8Array([1, 2]));
} catch (error) {
console.log(error.message); // "Inputs should have the same length"
}Install with Tessl CLI
npx tessl i tessl/npm-uint8arrays