~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
56 lines · 1.4 KB Raw History
/**
 * Tarball hashes in the forms npm expects: an SRI string (SHA-512, base64)
 * and a legacy SHA-1 hex shasum. WebCrypto supplies both digests, so this
 * runs on Cloudflare Workers.
 */

/**
 * @param {Uint8Array} bytes
 * @returns {string}
 */
function toBase64(bytes) {
  let binary = '';
  for (let at = 0; at < bytes.length; at += 0x8000) {
    binary += String.fromCharCode(...bytes.subarray(at, at + 0x8000));
  }
  return btoa(binary);
}

/**
 * @param {Uint8Array} bytes
 * @returns {string}
 */
function toHex(bytes) {
  let hex = '';
  for (const byte of bytes) hex += byte.toString(16).padStart(2, '0');
  return hex;
}

/**
 * @param {Uint8Array} data
 * @returns {Promise<{integrity: string, shasum: string}>}
 */
export async function tarballHashes(data) {
  const buffer = /** @type {BufferSource} */ (data);
  const [sha512, sha1] = await Promise.all([
    crypto.subtle.digest('SHA-512', buffer),
    crypto.subtle.digest('SHA-1', buffer),
  ]);
  return {
    integrity: `sha512-${toBase64(new Uint8Array(sha512))}`,
    shasum: toHex(new Uint8Array(sha1)),
  };
}

/**
 * Decode one base64 attachment. atob answers a byte string; the copy into
 * a typed array is the decode.
 * @param {string} data
 * @returns {Uint8Array}
 */
export function fromBase64(data) {
  const binary = atob(data);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
  return bytes;
}