41 lines
1.2 KiB
TypeScript
41 lines
1.2 KiB
TypeScript
import { base64 } from '@scure/base'
|
|
import { randomBytes } from '@noble/hashes/utils'
|
|
import { secp256k1 } from '@noble/curves/secp256k1'
|
|
import { sha256 } from '@noble/hashes/sha256'
|
|
import { xchacha20 } from '@noble/ciphers/chacha'
|
|
|
|
import { utf8Decoder, utf8Encoder } from './utils.ts'
|
|
|
|
export const getSharedSecret = (privkey: string, pubkey: string): Uint8Array =>
|
|
sha256(secp256k1.getSharedSecret(privkey, '02' + pubkey).subarray(1, 33))
|
|
|
|
export function encrypt(key: Uint8Array, text: string, v = 1) {
|
|
if (v !== 1) {
|
|
throw new Error('NIP44: unknown encryption version')
|
|
}
|
|
|
|
const nonce = randomBytes(24)
|
|
const plaintext = utf8Encoder.encode(text)
|
|
const ciphertext = xchacha20(key, nonce, plaintext)
|
|
|
|
const payload = new Uint8Array(25 + ciphertext.length)
|
|
payload.set([v], 0)
|
|
payload.set(nonce, 1)
|
|
payload.set(ciphertext, 25)
|
|
|
|
return base64.encode(payload)
|
|
}
|
|
|
|
export function decrypt(key: Uint8Array, payload: string) {
|
|
let data = base64.decode(payload)
|
|
if (data[0] !== 1) {
|
|
throw new Error(`NIP44: unknown encryption version: ${data[0]}`)
|
|
}
|
|
|
|
const nonce = data.slice(1, 25)
|
|
const ciphertext = data.slice(25)
|
|
const plaintext = xchacha20(key, nonce, ciphertext)
|
|
|
|
return utf8Decoder.decode(plaintext)
|
|
}
|