You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
56 lines
1.9 KiB
56 lines
1.9 KiB
// nip49.ts |
|
import { scrypt } from "@noble/hashes/scrypt"; |
|
import { xchacha20poly1305 } from "@noble/ciphers/chacha"; |
|
import { concatBytes as concatBytes2, randomBytes } from "@noble/hashes/utils"; |
|
|
|
// nip19.ts |
|
import { bytesToHex, concatBytes, hexToBytes } from "@noble/hashes/utils"; |
|
import { bech32 } from "@scure/base"; |
|
var Bech32MaxSize = 5e3; |
|
function encodeBech32(prefix, data) { |
|
let words = bech32.toWords(data); |
|
return bech32.encode(prefix, words, Bech32MaxSize); |
|
} |
|
function encodeBytes(prefix, bytes) { |
|
return encodeBech32(prefix, bytes); |
|
} |
|
|
|
// nip49.ts |
|
import { bech32 as bech322 } from "@scure/base"; |
|
function encrypt(sec, password, logn = 16, ksb = 2) { |
|
let salt = randomBytes(16); |
|
let n = 2 ** logn; |
|
let key = scrypt(password.normalize("NFKC"), salt, { N: n, r: 8, p: 1, dkLen: 32 }); |
|
let nonce = randomBytes(24); |
|
let aad = Uint8Array.from([ksb]); |
|
let xc2p1 = xchacha20poly1305(key, nonce, aad); |
|
let ciphertext = xc2p1.encrypt(sec); |
|
let b = concatBytes2(Uint8Array.from([2]), Uint8Array.from([logn]), salt, nonce, aad, ciphertext); |
|
return encodeBytes("ncryptsec", b); |
|
} |
|
function decrypt(ncryptsec, password) { |
|
let { prefix, words } = bech322.decode(ncryptsec, Bech32MaxSize); |
|
if (prefix !== "ncryptsec") { |
|
throw new Error(`invalid prefix ${prefix}, expected 'ncryptsec'`); |
|
} |
|
let b = new Uint8Array(bech322.fromWords(words)); |
|
let version = b[0]; |
|
if (version !== 2) { |
|
throw new Error(`invalid version ${version}, expected 0x02`); |
|
} |
|
let logn = b[1]; |
|
let n = 2 ** logn; |
|
let salt = b.slice(2, 2 + 16); |
|
let nonce = b.slice(2 + 16, 2 + 16 + 24); |
|
let ksb = b[2 + 16 + 24]; |
|
let aad = Uint8Array.from([ksb]); |
|
let ciphertext = b.slice(2 + 16 + 24 + 1); |
|
let key = scrypt(password.normalize("NFKC"), salt, { N: n, r: 8, p: 1, dkLen: 32 }); |
|
let xc2p1 = xchacha20poly1305(key, nonce, aad); |
|
let sec = xc2p1.decrypt(ciphertext); |
|
return sec; |
|
} |
|
export { |
|
decrypt, |
|
encrypt |
|
};
|
|
|