Open2
uuidをbase58でエンコード・デコード
エンコード
// Base58 に使う文字集合(Bitcoin 互換)
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
/**
* UUID → Base58 へ短縮変換
*/
export function uuidToBase58(uuid: string): string {
// 1. ハイフン除去 & 妥当性チェック
const hex = uuid.replace(/-/g, '').toLowerCase();
if (!/^[0-9a-f]{32}$/.test(hex)) {
throw new Error('Invalid UUID format');
}
// 2. 16 進 → BigInt
let num = BigInt('0x' + hex);
if (num === 0n) return BASE58_ALPHABET[0]; // 全 0 UUID への対応
// 3. BigInt → Base58
const base = 58n;
let encoded = '';
while (num > 0n) {
const rem = Number(num % base);
encoded = BASE58_ALPHABET[rem] + encoded;
num /= base;
}
// 4. 先頭の 00 バイトは '1' で保存(Base58 の慣例)
const leadingZeroBytes = hex.match(/^00+/);
if (leadingZeroBytes) {
const zeros = leadingZeroBytes[0].length / 2; // 1 バイト = 2 桁
encoded = BASE58_ALPHABET[0].repeat(zeros) + encoded;
}
return encoded; // 通常 22 文字
}
デコード
// Base58 に使う文字集合(Bitcoin 互換)
const BASE58_ALPHABET =
'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
// アルファベット → インデックスの高速参照マップ
const BASE58_MAP: Record<string, number> = {};
for (let i = 0; i < BASE58_ALPHABET.length; i++) {
BASE58_MAP[BASE58_ALPHABET[i]] = i;
}
/**
* Base58 文字列 → 標準 UUID 形式 (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
*/
export function base58ToUuid(base58: string): string {
if (!/^[1-9A-HJ-NP-Za-km-z]+$/.test(base58)) {
throw new Error('Invalid Base58 string');
}
// 1. 先頭の '1' はゼロバイトを表す (Bitcoin 規則)
let leadingZeros = 0;
while (leadingZeros < base58.length && base58[leadingZeros] === '1') {
leadingZeros++;
}
// 2. Base58 → BigInt へデコード
let num = 0n;
for (let i = leadingZeros; i < base58.length; i++) {
const val = BASE58_MAP[base58[i]];
if (val === undefined) throw new Error(`Invalid char '${base58[i]}'`);
num = num * 58n + BigInt(val);
}
// 3. BigInt → 16 進 (偶数桁になるよう 0 パディング)
let hex = num.toString(16);
if (hex.length % 2) hex = '0' + hex;
// 4. 先頭ゼロバイトを復元
hex = '00'.repeat(leadingZeros) + hex;
// 5. 全体を 32 桁に左パディングし、UUID のハイフンを挿入
hex = hex.padStart(32, '0');
return (
hex.slice(0, 8) +
'-' +
hex.slice(8, 12) +
'-' +
hex.slice(12, 16) +
'-' +
hex.slice(16, 20) +
'-' +
hex.slice(20)
);
}