nip04.encrypt and nip04.decrypt.

This commit is contained in:
fiatjaf
2022-01-25 20:16:56 -03:00
parent a775dd8b60
commit 4da894dea5
8 changed files with 92 additions and 48 deletions

View File

@@ -10,6 +10,8 @@ It provides a `window.nostr` object which has the following methods:
```
async window.nostr.getPublicKey(): string // returns your public key as hex
async window.nostr.signEvent(event): string // returns the signature as hex
async window.nostr.nip04.encrypt(pubkey, plaintext): string // returns ciphertext+iv as specified in nip04
async window.nostr.nip04.decrypt(pubkey, ciphertext): string // takes ciphertext+iv as specified in nip04
```
## Demo Video

View File

@@ -19,7 +19,7 @@ esbuild
alias({
stream: require.resolve('readable-stream')
}),
nodeGlobals()
nodeGlobals({buffer: true})
],
sourcemap: 'inline',
define: {

View File

@@ -1,6 +1,7 @@
import browser from 'webextension-polyfill'
import {Buffer} from 'buffer'
import {validateEvent, signEvent, getEventHash, getPublicKey} from 'nostr-tools'
import {encrypt, decrypt} from 'nostr-tools/nip04'
import {
PERMISSIONS_REQUIRED,
@@ -38,38 +39,41 @@ async function handleContentScriptMessage({type, params, host}) {
}
}
let results = await browser.storage.local.get('private_key')
if (!results || !results.private_key) {
return {error: 'no private key found'}
}
let sk = results.private_key
try {
switch (type) {
case 'getPublicKey': {
let results = await browser.storage.local.get('private_key')
if (results && results.private_key) {
return Buffer.from(getPublicKey(results.private_key)).toString('hex')
} else {
return {error: 'no private key found'}
}
return Buffer.from(getPublicKey(sk)).toString('hex')
}
case 'signEvent': {
let {event} = params
let results = await browser.storage.local.get('private_key')
if (results && results.private_key) {
if (!event.pubkey)
event.pubkey = Buffer.from(
getPublicKey(results.private_key)
).toString('hex')
event.pubkey = Buffer.from(getPublicKey(sk)).toString('hex')
if (!event.id) event.id = getEventHash(event)
if (!validateEvent(event)) return {error: 'invalid event'}
let signature = await signEvent(event, results.private_key)
let signature = await signEvent(event, sk)
return Buffer.from(signature).toString('hex')
} else {
return {error: 'no private key found'}
}
case 'nip04.encrypt': {
let {peer, plaintext} = params
return encrypt(sk, peer, plaintext)
}
case 'nip04.decrypt': {
let {peer, ciphertext} = params
return decrypt(sk, peer, ciphertext)
}
}
} catch (error) {
return {error}
return {error: {message: error.message, stack: error.stack}}
}
}

View File

@@ -2,17 +2,23 @@ import browser from 'webextension-polyfill'
export const PERMISSIONS_REQUIRED = {
getPublicKey: 1,
signEvent: 10
signEvent: 10,
'nip04.encrypt': 20,
'nip04.decrypt': 20
}
const ORDERED_PERMISSIONS = [
[1, ['getPublicKey']],
[10, ['signEvent']]
[10, ['signEvent']],
[20, ['nip04.encrypt']],
[20, ['nip04.decrypt']]
]
const PERMISSION_NAMES = {
getPublicKey: 'read your public key',
signEvent: 'sign events using your private key'
signEvent: 'sign events using your private key',
'nip04.encrypt': 'encrypt messages to peers',
'nip04.decrypt': 'decrypt messages to peers'
}
export function getAllowedCapabilities(permission) {
@@ -31,6 +37,9 @@ export function getAllowedCapabilities(permission) {
export function getPermissionsString(permission) {
let capabilities = getAllowedCapabilities(permission)
if (capabilities.length === 0) return 'none'
if (capabilities.length === 1) return capabilities[0]
return (
capabilities.slice(0, -1).join(', ') +
' and ' +

View File

@@ -1,7 +1,7 @@
{
"name": "nos2x",
"description": "Nostr Signer Extension",
"version": "1.0.1",
"version": "1.1.0",
"homepage_url": "https://github.com/fiatjaf/nos2x",
"manifest_version": 2,
"icons": {

View File

@@ -26,6 +26,16 @@ window.nostr = {
'*'
)
})
},
nip04: {
encrypt(peer, plaintext) {
return window.nostr._call('nip04.encrypt', {peer, plaintext})
},
decrypt(peer, ciphertext) {
return window.nostr._call('nip04.decrypt', {peer, ciphertext})
}
}
}
@@ -39,9 +49,9 @@ window.addEventListener('message', message => {
return
if (message.data.response.error) {
window.nostr._requests[message.data.id].reject(
new Error(`nos2x: ${message.data.response.error}`)
)
let error = new Error('nos2x: ' + message.data.response.error.message)
error.stack = message.data.response.error.stack
window.nostr._requests[message.data.id].reject(error)
} else {
window.nostr._requests[message.data.id].resolve(message.data.response)
}

View File

@@ -1,14 +1,13 @@
{
"dependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.1.1",
"buffer": "^6.0.3",
"esbuild": "^0.14.11",
"esbuild-plugin-alias": "^0.2.1",
"eslint": "^8.6.0",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-react": "^7.28.0",
"events": "^3.3.0",
"nostr-tools": "^0.17.0",
"nostr-tools": "^0.21.4",
"prettier": "^2.5.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",

View File

@@ -36,11 +36,6 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@leichtgewicht/ip-codec@^2.0.1":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz#0300943770e04231041a51bd39f0439b5c7ab4f0"
integrity sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==
"@noble/hashes@^0.5.5", "@noble/hashes@^0.5.7":
version "0.5.9"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-0.5.9.tgz#9f3051a4cc6f7c168022b3b7fbbe9fe2a35cccf0"
@@ -167,7 +162,7 @@ buffer-xor@^1.0.3:
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
buffer@>=5, buffer@^6.0.3:
buffer@>=5:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
@@ -239,6 +234,13 @@ create-hash@^1.1.0, create-hash@^1.2.0:
ripemd160 "^2.0.1"
sha.js "^2.4.0"
cross-fetch@^3.1.4:
version "3.1.5"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f"
integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==
dependencies:
node-fetch "2.6.7"
cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -290,13 +292,6 @@ des.js@^1.0.0:
inherits "^2.0.1"
minimalistic-assert "^1.0.0"
dns-packet@^5.2.4:
version "5.3.1"
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.3.1.tgz#eb94413789daec0f0ebe2fcc230bdc9d7c91b43d"
integrity sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==
dependencies:
"@leichtgewicht/ip-codec" "^2.0.1"
doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
@@ -1055,22 +1050,29 @@ next-tick@~1.0.0:
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
node-fetch@2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
dependencies:
whatwg-url "^5.0.0"
node-gyp-build@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==
nostr-tools@^0.17.0:
version "0.17.0"
resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-0.17.0.tgz#bcc041d810b710dd8431b3d27576948ccea4dac4"
integrity sha512-1Ld/DxBHC+ljVPlOyGh+LtDQfiFMJO76Nyfberuh8mCwvgut6sAW8iI2pHLJEzmQO5T2JgI3qThU4+9vKzXApg==
nostr-tools@^0.21.4:
version "0.21.4"
resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-0.21.4.tgz#c9cb88955ee55ab751287aa4e492708221748d86"
integrity sha512-ZCYRMfryb2loOFm3WGG5dXPGCJP3OqanNur6q1moZUMKhzDOzb3d95yVBa752LF9cReTjjxyIoZm0TklEAaeAA==
dependencies:
"@noble/hashes" "^0.5.7"
"@noble/secp256k1" "^1.3.0"
browserify-cipher ">=1"
buffer ">=5"
create-hash "^1.2.0"
dns-packet "^5.2.4"
cross-fetch "^3.1.4"
micro-bip32 "^0.1.0"
micro-bip39 "^0.1.3"
websocket-polyfill "^0.0.3"
@@ -1392,6 +1394,11 @@ text-table@^0.2.0:
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
tstl@^2.0.7:
version "2.5.2"
resolved "https://registry.yarnpkg.com/tstl/-/tstl-2.5.2.tgz#655ae93192e4c18ac74495cea2bf862159775cd9"
@@ -1465,6 +1472,11 @@ webextension-polyfill@^0.8.0:
resolved "https://registry.yarnpkg.com/webextension-polyfill/-/webextension-polyfill-0.8.0.tgz#f80e9f4b7f81820c420abd6ffbebfa838c60e041"
integrity sha512-a19+DzlT6Kp9/UI+mF9XQopeZ+n2ussjhxHJ4/pmIGge9ijCDz7Gn93mNnjpZAk95T4Tae8iHZ6sSf869txqiQ==
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
websocket-polyfill@^0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/websocket-polyfill/-/websocket-polyfill-0.0.3.tgz#7321ada0f5f17516290ba1cb587ac111b74ce6a5"
@@ -1485,6 +1497,14 @@ websocket@^1.0.28:
utf-8-validate "^5.0.2"
yaeti "^0.0.6"
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"