Open2

uuidをbase58でエンコード・デコード

Nakano as a ServiceNakano as a Service

エンコード

// 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 文字
}
Nakano as a ServiceNakano as a Service

デコード

// 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)
  );
}