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 | 110x 110x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 17x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 21x | import bs58 from 'bs58';
import { Buffer as BufferPolyfill } from 'buffer';
// @ts-expect-error: not a typescript package
import * as base64url from 'base64url-universal';
const buffer = typeof Buffer === 'undefined' ? BufferPolyfill : Buffer;
/** Secp256k1 Public Key */
export interface IPublicKeyJwk {
/** key type */
kty: string;
/** curve */
crv: string;
/** public point */
x: string;
/** public point */
y?: string;
/** key id */
kid?: string;
}
const ECDSA_CURVE = {
P256: 'P-256',
P384: 'P-384',
P521: 'P-521',
// compatibility with @peculiar/webcrypto
secp256k1: 'K-256',
}
function getSecretKeySize({ curve }: { curve: string }): number {
if (curve === ECDSA_CURVE.P256 || curve === ECDSA_CURVE.secp256k1 || curve === 'secp256k1') {
return 32
}
if (curve === ECDSA_CURVE.P384) {
return 48
}
if (curve === ECDSA_CURVE.P521) {
return 66
}
throw new TypeError(`Unsupported curve "${curve}".`)
}
function toPublicKeyBytes({ jwk } = {} as any): Uint8Array {
if (jwk?.kty !== 'EC') {
throw new TypeError('"jwk.kty" must be "EC".')
}
const { crv: curve } = jwk
const secretKeySize = getSecretKeySize({ curve })
// convert `x` coordinate to compressed public key
const x = base64url.decode(jwk.x)
const y = base64url.decode(jwk.y)
// public key size is always secret key size + 1
const publicKeySize = secretKeySize + 1
const publicKey = new Uint8Array(publicKeySize)
// use even / odd status of `y` coordinate for compressed header
const even = y[y.length - 1] % 2 === 0
publicKey[0] = even ? 2 : 3
// write `x` coordinate at end of multikey buffer to zero-fill it
publicKey.set(x, publicKey.length - x.length)
return publicKey
}
/** convert jwk to hex encoded public key */
export const publicKeyHexFromJwkSecp256k1 = (jwk: IPublicKeyJwk): string => {
return buffer.from(toPublicKeyBytes({ jwk })).toString('hex');
};
/** convert publicKeyHex to base58 */
export const publicKeyBase58FromPublicKeyHex = (publicKeyHex: string): string => {
return bs58.encode(buffer.from(publicKeyHex, 'hex'));
};
export const publicKeyBase58FromUint8Array = (publicKey: Uint8Array<any>): string => {
return bs58.encode(publicKey);
}
export function jwkToPublicKeyBytesEd25519(jwk: IPublicKeyJwk) {
const { kty, crv, x } = jwk;
if (kty !== 'OKP') {
throw new TypeError('"jwk.kty" must be "OKP".');
}
if (crv !== 'Ed25519') {
throw new TypeError('"jwk.crv" must be "Ed25519".');
}
if (typeof x !== 'string') {
throw new TypeError('"jwk.x" must be a string.');
}
const publicKey = base64url.decode(jwk.x);
if (publicKey.length !== 32) {
throw new Error(
`Invalid public key size (${publicKey.length}); ` +
`expected 32.`);
}
return publicKey;
}
export const jwkToMultibaseEd25519 = (jwk: IPublicKeyJwk): string => {
// multicodec ed25519-pub header as varint
const MULTICODEC_PUBLIC_HEADER = new Uint8Array([0xed, 0x01]);
const publicKeyBytes = jwkToPublicKeyBytesEd25519(jwk);
const uint8ArrayPublicKey = new Uint8Array(MULTICODEC_PUBLIC_HEADER.length + publicKeyBytes.length);
uint8ArrayPublicKey.set(MULTICODEC_PUBLIC_HEADER);
uint8ArrayPublicKey.set(publicKeyBytes, MULTICODEC_PUBLIC_HEADER.length);
const publicKeyBase58 = publicKeyBase58FromUint8Array(uint8ArrayPublicKey);
return `z${publicKeyBase58}`;
}
export function publicKeyMultibaseToBytes (publicKeyMultibase: string): Uint8Array {
return Uint8Array.from((bs58 as any).decode(publicKeyMultibase.slice(1)).slice(2))
}
|