From cc2ced1558cb08923fe943e674a7fd407308f075 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Fri, 10 Dec 2021 21:41:05 -0300 Subject: [PATCH] update secp256k1 library, add nip04.js --- .eslintrc.json | 142 +++++++++++++++++++++++++++++++++++++++++++++++ .prettierrc.yaml | 7 ++- event.js | 2 +- nip04.js | 36 ++++++++++++ package.json | 4 +- utils.js | 2 +- 6 files changed, 186 insertions(+), 7 deletions(-) create mode 100644 .eslintrc.json create mode 100644 nip04.js diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..2eb9e3d --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,142 @@ +{ + "parserOptions": { + "ecmaVersion": 9, + "ecmaFeatures": { + "jsx": true + }, + "sourceType": "module", + "allowImportExportEverywhere": false + }, + + "env": { + "es6": true, + "node": true + }, + + "plugins": [ + "babel" + ], + + "globals": { + "document": false, + "navigator": false, + "window": false, + "location": false, + "URL": false, + "URLSearchParams": false, + "fetch": false, + "EventSource": false, + "localStorage": false, + "sessionStorage": false + }, + + "rules": { + "accessor-pairs": 2, + "arrow-spacing": [2, { "before": true, "after": true }], + "block-spacing": [2, "always"], + "brace-style": [2, "1tbs", { "allowSingleLine": true }], + "comma-dangle": 0, + "comma-spacing": [2, { "before": false, "after": true }], + "comma-style": [2, "last"], + "constructor-super": 2, + "curly": [0, "multi-line"], + "dot-location": [2, "property"], + "eol-last": 2, + "eqeqeq": [2, "allow-null"], + "generator-star-spacing": [2, { "before": true, "after": true }], + "handle-callback-err": [2, "^(err|error)$" ], + "indent": 0, + "jsx-quotes": [2, "prefer-double"], + "key-spacing": [2, { "beforeColon": false, "afterColon": true }], + "keyword-spacing": [2, { "before": true, "after": true }], + "new-cap": 0, + "new-parens": 0, + "no-array-constructor": 2, + "no-caller": 2, + "no-class-assign": 2, + "no-cond-assign": 2, + "no-const-assign": 2, + "no-control-regex": 0, + "no-debugger": 0, + "no-delete-var": 2, + "no-dupe-args": 2, + "no-dupe-class-members": 2, + "no-dupe-keys": 2, + "no-duplicate-case": 2, + "no-empty-character-class": 2, + "no-empty-pattern": 2, + "no-eval": 0, + "no-ex-assign": 2, + "no-extend-native": 2, + "no-extra-bind": 2, + "no-extra-boolean-cast": 2, + "no-extra-parens": [2, "functions"], + "no-fallthrough": 2, + "no-floating-decimal": 2, + "no-func-assign": 2, + "no-implied-eval": 2, + "no-inner-declarations": [0, "functions"], + "no-invalid-regexp": 2, + "no-irregular-whitespace": 2, + "no-iterator": 2, + "no-label-var": 2, + "no-labels": [2, { "allowLoop": false, "allowSwitch": false }], + "no-lone-blocks": 2, + "no-mixed-spaces-and-tabs": 2, + "no-multi-spaces": 2, + "no-multi-str": 2, + "no-multiple-empty-lines": [2, { "max": 2 }], + "no-native-reassign": 2, + "no-negated-in-lhs": 2, + "no-new": 0, + "no-new-func": 2, + "no-new-object": 2, + "no-new-require": 2, + "no-new-symbol": 2, + "no-new-wrappers": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-octal-escape": 2, + "no-path-concat": 0, + "no-proto": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-return-assign": 0, + "no-self-assign": 2, + "no-self-compare": 2, + "no-sequences": 2, + "no-shadow-restricted-names": 2, + "no-spaced-func": 2, + "no-sparse-arrays": 2, + "no-this-before-super": 2, + "no-throw-literal": 2, + "no-trailing-spaces": 2, + "no-undef": 2, + "no-undef-init": 2, + "no-unexpected-multiline": 2, + "no-unneeded-ternary": [2, { "defaultAssignment": false }], + "no-unreachable": 2, + "no-unused-vars": [2, { "vars": "local", "args": "none", "varsIgnorePattern": "^_"}], + "no-useless-call": 2, + "no-useless-constructor": 2, + "no-with": 2, + "one-var": [0, { "initialized": "never" }], + "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], + "padded-blocks": [2, "never"], + "quotes": [2, "single", { "avoidEscape": true, "allowTemplateLiterals": true }], + "semi": [2, "never"], + "semi-spacing": [2, { "before": false, "after": true }], + "space-before-blocks": [2, "always"], + "space-before-function-paren": 0, + "space-in-parens": [2, "never"], + "space-infix-ops": 2, + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "spaced-comment": 0, + "template-curly-spacing": [2, "never"], + "use-isnan": 2, + "valid-typeof": 2, + "wrap-iife": [2, "any"], + "yield-star-spacing": [2, "both"], + "yoda": [0] + } +} diff --git a/.prettierrc.yaml b/.prettierrc.yaml index e31d792..16c878e 100644 --- a/.prettierrc.yaml +++ b/.prettierrc.yaml @@ -1,9 +1,10 @@ +semi: false arrowParens: avoid -bracketSpacing: false -jsxBracketSameLine: false +insertPragma: false printWidth: 80 proseWrap: preserve -semi: false singleQuote: true trailingComma: none useTabs: false +jsxBracketSameLine: false +bracketSpacing: false diff --git a/event.js b/event.js index 4f7b848..3e7770d 100644 --- a/event.js +++ b/event.js @@ -1,4 +1,4 @@ -import * as secp256k1 from 'noble-secp256k1' +import * as secp256k1 from '@noble/secp256k1' import {sha256} from './utils' diff --git a/nip04.js b/nip04.js new file mode 100644 index 0000000..4afbd93 --- /dev/null +++ b/nip04.js @@ -0,0 +1,36 @@ +import * as secp256k1 from '@noble/secp256k1' + +export function encrypt(privkey, pubkey, text) { + const key = secp256k1.getSharedSecret(privkey, '02' + pubkey) + const normalizedKey = getOnlyXFromFullSharedSecret(key) + + let iv = crypto.randomFillSync(new Uint8Array(16)) + var cipher = crypto.createCipheriv( + 'aes-256-cbc', + Buffer.from(normalizedKey, 'hex'), + iv + ) + let encryptedMessage = cipher.update(text, 'utf8', 'base64') + encryptedMessage += cipher.final('base64') + + return [encryptedMessage, Buffer.from(iv.buffer).toString('base64')] +} + +export function decrypt(privkey, pubkey, ciphertext, iv) { + const key = secp256k1.getSharedSecret(privkey, '02' + pubkey) + const normalizedKey = getOnlyXFromFullSharedSecret(key) + + var decipher = crypto.createDecipheriv( + 'aes-256-cbc', + Buffer.from(normalizedKey, 'hex'), + Buffer.from(iv, 'base64') + ) + let decryptedMessage = decipher.update(ciphertext, 'base64') + decryptedMessage += decipher.final('utf8') + + return decryptedMessage +} + +function getOnlyXFromFullSharedSecret(fullSharedSecretCoordinates) { + return fullSharedSecretCoordinates.substr(2, 64) +} diff --git a/package.json b/package.json index 24eea1d..ea3bb6d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nostr-tools", - "version": "0.5.0", + "version": "0.6.0", "description": "Tools for making a Nostr client.", "main": "index.js", "repository": { @@ -8,9 +8,9 @@ "url": "https://github.com/fiatjaf/nostr-tools.git" }, "dependencies": { + "@noble/secp256k1": "^1.3.0", "buffer": "^6.0.3", "dns-packet": "^5.2.4", - "noble-secp256k1": "^1.1.1", "websocket-polyfill": "^0.0.3" }, "keywords": [ diff --git a/utils.js b/utils.js index cc45b08..ece6c0f 100644 --- a/utils.js +++ b/utils.js @@ -1,4 +1,4 @@ -import * as secp256k1 from 'noble-secp256k1' +import * as secp256k1 from '@noble/secp256k1' export const makeRandom32 = () => secp256k1.utils.randomPrivateKey() export const sha256 = m => secp256k1.utils.sha256(Uint8Array.from(m))