Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | 1x 119x 119x 119x 119x 119x 119x 119x 476x 476x 119x 119x 131x 131x 131x 131x 524x 524x 524x 4192x 2165x 4192x 2027x 2027x 4192x 524x 131x 131x 131x 131x 131x 131x 131x 524x 524x 524x 131x 131x 1x 1x 131x 131x 131x 131x 1x 119x 119x 119x 119x 119x 119x 119x 119x 119x 119x 119x 1x 16x 16x 16x 16x 16x 1x 1x 15x 15x 15x 15x 15x 15x | /**
* ProofID Identity Code Generator
*
* Generates unique, collision-safe identity codes in the format: PFID-XXXX-XXXX
*
* The identity code consists of:
* - Prefix: "PFID" (ProofID identifier)
* - Payload: 4 characters from Base58 alphabet (~11.3M combinations)
* - Checksum: 4 characters derived from CRC16 of the payload
*/
import {
BASE58_ALPHABET,
BASE58_ALPHABET_UPPER,
IDENTITY_PREFIX,
IDENTITY_PAYLOAD_LENGTH,
IDENTITY_CHECKSUM_LENGTH,
RESERVED_IDENTITY_CODES,
} from './constants';
/**
* Generate a random string from the Base58 alphabet (uppercase only for new codes)
*/
function generateBase58String(length: number): string {
const array = new Uint8Array(length);
// Use crypto.getRandomValues in browser, crypto.randomBytes in Node
if (typeof window !== 'undefined' && window.crypto) {
window.crypto.getRandomValues(array);
} else {
// Node.js environment
// eslint-disable-next-line @typescript-eslint/no-var-requires
const crypto = require('crypto') as typeof import('crypto');
const randomBytes = crypto.randomBytes(length);
for (let i = 0; i < length; i++) {
array[i] = randomBytes[i];
}
}
let result = '';
for (let i = 0; i < length; i++) {
// Map each byte to a Base58 character (uppercase only for new codes)
result += BASE58_ALPHABET_UPPER[array[i] % BASE58_ALPHABET_UPPER.length];
}
return result;
}
/**
* Calculate CRC16-CCITT checksum
* This provides error detection for the identity code
*/
function crc16(data: string): number {
let crc = 0xffff;
const polynomial = 0x1021;
for (let i = 0; i < data.length; i++) {
const byte = data.charCodeAt(i);
crc ^= byte << 8;
for (let j = 0; j < 8; j++) {
if (crc & 0x8000) {
crc = ((crc << 1) ^ polynomial) & 0xffff;
} else {
crc = (crc << 1) & 0xffff;
}
}
}
return crc;
}
/**
* Encode a number to Base58 with fixed length (uppercase only)
*/
function encodeBase58(num: number, length: number): string {
const base = BASE58_ALPHABET_UPPER.length;
let result = '';
// Convert number to Base58 (uppercase)
let remaining = num;
while (result.length < length) {
result = BASE58_ALPHABET_UPPER[remaining % base] + result;
remaining = Math.floor(remaining / base);
}
return result.slice(0, length);
}
/**
* Decode a Base58 string to number
*/
export function decodeBase58(str: string): number {
const base = BASE58_ALPHABET.length;
let result = 0;
for (let i = 0; i < str.length; i++) {
const index = BASE58_ALPHABET.indexOf(str[i]);
if (index === -1) {
throw new Error(`Invalid Base58 character: ${str[i]}`);
}
result = result * base + index;
}
return result;
}
/**
* Generate the checksum for a payload
* Normalizes to uppercase for consistent checksum across case variations
*/
export function generateChecksum(payload: string): string {
// Normalize to uppercase for consistent checksum calculation
const normalizedPayload = payload.toUpperCase();
const checksumValue = crc16(normalizedPayload);
return encodeBase58(checksumValue, IDENTITY_CHECKSUM_LENGTH);
}
/**
* Generate a new identity code
*
* @returns Identity code in format PFID-XXXX-XXXX
*/
export function generateIdentityCode(): string {
let code: string;
let attempts = 0;
const maxAttempts = 10;
do {
// Generate random payload
const payload = generateBase58String(IDENTITY_PAYLOAD_LENGTH);
// Calculate checksum
const checksum = generateChecksum(payload);
// Combine into full identity code
code = `${IDENTITY_PREFIX}-${payload}-${checksum}`;
attempts++;
} while (RESERVED_IDENTITY_CODES.includes(code) && attempts < maxAttempts);
return code;
}
/**
* Extract parts from an identity code
* Returns uppercase values for consistent handling
*/
export function parseIdentityCode(code: string): {
prefix: string;
payload: string;
checksum: string;
} | null {
// First try matching with the full Base58 alphabet (handles old mixed-case codes)
const match = code.match(
/^([A-Za-z]+)-([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{4})-([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{4})$/
);
if (!match) {
return null;
}
// Return uppercase values for consistent handling
return {
prefix: match[1].toUpperCase(),
payload: match[2].toUpperCase(),
checksum: match[3].toUpperCase(),
};
}
|