68 lines
1.4 KiB
TypeScript
68 lines
1.4 KiB
TypeScript
|
import * as crypto from './crypto';
|
||
|
|
||
|
interface Addressable {
|
||
|
key(): string
|
||
|
digest(): string
|
||
|
}
|
||
|
|
||
|
function stringToBytes(s:string) {
|
||
|
const a = new Uint8Array(20);
|
||
|
let j = 2;
|
||
|
for (let i = 0; i < a.byteLength; i++) {
|
||
|
const n = parseInt(s.substring(j, j+2), 16);
|
||
|
a[i] = n;
|
||
|
j += 2;
|
||
|
}
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
function bytesToHex(a:Uint8Array) {
|
||
|
let s = '';
|
||
|
for (let i = 0; i < a.byteLength; i++) {
|
||
|
const h = '00' + a[i].toString(16);
|
||
|
s += h.slice(-2);
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
async function mergeKey(a:Uint8Array, s:Uint8Array) {
|
||
|
const y = new Uint8Array(a.byteLength + s.byteLength);
|
||
|
for (let i = 0; i < a.byteLength; i++) {
|
||
|
y[i] = a[i];
|
||
|
}
|
||
|
for (let i = 0; i < s.byteLength; i++) {
|
||
|
y[a.byteLength + i] = s[i];
|
||
|
}
|
||
|
const z = await crypto.subtle.digest('SHA-256', y);
|
||
|
return bytesToHex(new Uint8Array(z));
|
||
|
}
|
||
|
|
||
|
async function toKey(v:string, salt:string) {
|
||
|
const a = stringToBytes(v);
|
||
|
const s = new TextEncoder().encode(salt);
|
||
|
return await mergeKey(a, s);
|
||
|
}
|
||
|
|
||
|
|
||
|
async function toAddressKey(zeroExHex:string, salt:string) {
|
||
|
const a = addressToBytes(zeroExHex);
|
||
|
const s = new TextEncoder().encode(salt);
|
||
|
return await mergeKey(a, s);
|
||
|
}
|
||
|
|
||
|
const re_addrHex = /^0[xX][a-fA-F0-9]{40}$/;
|
||
|
function addressToBytes(s:string) {
|
||
|
if (!s.match(re_addrHex)) {
|
||
|
throw 'invalid address hex';
|
||
|
}
|
||
|
return stringToBytes(s);
|
||
|
}
|
||
|
|
||
|
export {
|
||
|
toKey,
|
||
|
toAddressKey,
|
||
|
bytesToHex,
|
||
|
addressToBytes,
|
||
|
Addressable,
|
||
|
}
|