diff options
| author | fiatjaf <fiatjaf@gmail.com> | 2023-08-15 11:40:54 -0300 |
|---|---|---|
| committer | fiatjaf <fiatjaf@gmail.com> | 2023-08-15 11:40:54 -0300 |
| commit | c78bd4cef11d76fd5aa1add31e42cbdc5da1c6ea (patch) | |
| tree | 32d58d37fa719e7c19f612efb0b000e3f6bdfdc5 /44.md | |
| parent | a1f8a82e73dc8324c00c707a89265966a8dc99c4 (diff) | |
encoding implementation doesn't require complicate TLV parsing.
Diffstat (limited to '44.md')
| -rw-r--r-- | 44.md | 46 |
1 files changed, 13 insertions, 33 deletions
| @@ -30,7 +30,7 @@ Example: | |||
| 30 | Encrypting the message `hello` from Alice to Bob results in the base-64 encoded tlv payload: | 30 | Encrypting the message `hello` from Alice to Bob results in the base-64 encoded tlv payload: |
| 31 | 31 | ||
| 32 | ``` | 32 | ``` |
| 33 | AAEBARgeI8gcP/4mnw3mKgtMvD8aGYUnGBlhopoCBd94Ev9i | 33 | AZKyMIHbfVYFlAAK7Ci5wuM5GFOLaeI7LQKDzWJY |
| 34 | ``` | 34 | ``` |
| 35 | 35 | ||
| 36 | # Other Notes | 36 | # Other Notes |
| @@ -47,7 +47,7 @@ This encryption scheme replaces the one described in NIP-04, which is not secure | |||
| 47 | import {xchacha20} from "@noble/ciphers/chacha" | 47 | import {xchacha20} from "@noble/ciphers/chacha" |
| 48 | import {secp256k1} from "@noble/curves/secp256k1" | 48 | import {secp256k1} from "@noble/curves/secp256k1" |
| 49 | import {sha256} from "@noble/hashes/sha256" | 49 | import {sha256} from "@noble/hashes/sha256" |
| 50 | import {randomBytes, concatBytes} from "@noble/hashes/utils" | 50 | import {randomBytes} from "@noble/hashes/utils" |
| 51 | import {base64} from "@scure/base" | 51 | import {base64} from "@scure/base" |
| 52 | 52 | ||
| 53 | export const utf8Decoder = new TextDecoder() | 53 | export const utf8Decoder = new TextDecoder() |
| @@ -100,44 +100,24 @@ export function encrypt(privkey: string, pubkey: string, text: string, v = 1) { | |||
| 100 | const nonce = randomBytes(24) | 100 | const nonce = randomBytes(24) |
| 101 | const plaintext = utf8Encoder.encode(text) | 101 | const plaintext = utf8Encoder.encode(text) |
| 102 | const ciphertext = xchacha20(key, nonce, plaintext) | 102 | const ciphertext = xchacha20(key, nonce, plaintext) |
| 103 | const tlv = encodeTLV({ | ||
| 104 | 0: [new Uint8Array([1])], | ||
| 105 | 1: [nonce], | ||
| 106 | 2: [ciphertext] | ||
| 107 | }) | ||
| 108 | 103 | ||
| 109 | return base64.encode(tlv) | 104 | const payload = new Uint8Array(1 + 24 + ciphertext.length) |
| 105 | payload.set([version], 0) | ||
| 106 | payload.set(nonce, 1) | ||
| 107 | payload.set(ciphertext, 1 + 24) | ||
| 108 | |||
| 109 | return base64.encode(payload) | ||
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | export function decrypt(privkey: string, pubkey: string, payload: string) { | 112 | export function decrypt(privkey: string, pubkey: string, payload: string) { |
| 113 | let byteArray | 113 | const payload = base64.decode(blob) |
| 114 | try { | 114 | if (payload[0] !== 1) { |
| 115 | byteArray = base64.decode(payload) | 115 | throw new Error('NIP44: unknown encryption version') |
| 116 | } catch (e) { | ||
| 117 | throw new Error(`NIP44: failed to base64 decode payload: ${e}`) | ||
| 118 | } | ||
| 119 | |||
| 120 | let tlv | ||
| 121 | try { | ||
| 122 | tlv = parseTLV(byteArray) | ||
| 123 | } catch (e) { | ||
| 124 | throw new Error(`NIP44: failed to decode tlv: ${e}`) | ||
| 125 | } | ||
| 126 | |||
| 127 | if (tlv[0]?.[0]?.[0] !== 1) { | ||
| 128 | throw new Error(`NIP44: invalid version: ${tlv[0]?.[0]?.[0]}`) | ||
| 129 | } | ||
| 130 | |||
| 131 | if (tlv[1]?.[0]?.length !== 24) { | ||
| 132 | throw new Error(`NIP44: invalid nonce: ${tlv[1]?.[0]}`) | ||
| 133 | } | 116 | } |
| 134 | 117 | ||
| 135 | if (!tlv[2]?.[0]) { | 118 | const nonce = payload.subarray(1, 25) |
| 136 | throw new Error(`NIP44: missing ciphertext`) | 119 | const ciphertext = payload.subarray(25) |
| 137 | } | ||
| 138 | 120 | ||
| 139 | const nonce = tlv[1][0] | ||
| 140 | const ciphertext = tlv[2][0] | ||
| 141 | const key = getSharedSecret(privkey, pubkey) | 121 | const key = getSharedSecret(privkey, pubkey) |
| 142 | const plaintext = xchacha20(key, nonce, ciphertext) | 122 | const plaintext = xchacha20(key, nonce, ciphertext) |
| 143 | 123 | ||