hts/internal/keys/src/v1.ts

61 lines
1.7 KiB
TypeScript

import baseX from "base-x";
const alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const base58 = baseX(alphabet);
const SEPARATOR = "_";
/**
* Version 1 keys are constructed of 3 parts
* 1. 1 byte for the version
* 2. 1 byte to let us know the byteLength of the random part
* 3. LEN bytes of random data
* [VERSION, LEN, X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X]
*/
export class KeyV1 {
public readonly version = 1;
public readonly prefix?: string;
public readonly random: Uint8Array;
constructor(s: string);
constructor(opts: { byteLength: number; prefix?: string });
constructor(arg: string | { byteLength: number; prefix?: string }) {
if (typeof arg === "string") {
let s = arg;
const parts = arg.split(SEPARATOR);
if (parts.length === 2) {
this.prefix = parts[0];
s = parts[1];
}
const buf = base58.decode(s);
if (buf[0] !== 1) {
throw new Error("Only version 1 keys are supported");
}
const len = buf[1];
this.random = buf.slice(2, 2 + len);
return;
}
if (arg.byteLength < 8 || arg.byteLength > 255) {
throw new Error("v1 keys must be between 8 and 255 bytes long");
}
this.prefix = arg.prefix;
this.random = crypto.getRandomValues(new Uint8Array(arg.byteLength));
}
static fromString(s: string): KeyV1 {
return new KeyV1(s);
}
public toString(): string {
const buf = new Uint8Array(2 + this.random.length);
buf[0] = this.version;
buf[1] = this.random.length;
buf.set(this.random, 2);
const enc = base58.encode(buf);
if (this.prefix) {
return [this.prefix, enc].join(SEPARATOR);
}
return enc;
}
}