nostr
nostr copied to clipboard
Implement nip/04: Encrypted Direct Message
Summary
- [ ] Ensure the generate secp256k1 is correct
- [ ] Find or implement the new functions required to generate encrypted messages
- [ ] Create the interfaces required to encrypt, decrypt, sign and validate encrypted messages
What we need
- A simple and light way to create encrypted message
- A function to get a shared secret between a private and a public key
- A comprehensible way to do it
Notes
The following javascript code is coming from nip/04 standard.
import crypto from 'crypto'
//--- 8< This part of the code is probably not supported by Erlang
import * as secp from 'noble-secp256k1'
let sharedPoint = secp.getSharedSecret(ourPrivateKey, '02' + theirPublicKey)
let sharedX = sharedPoint.substr(2, 64)
//--- 8< This part of the code is probably not supported by Erlang
let iv = crypto.randomFillSync(new Uint8Array(16))
var cipher = crypto.createCipheriv(
'aes-256-cbc',
Buffer.from(sharedX, 'hex'),
iv
)
let encryptedMessage = cipher.update(text, 'utf8', 'base64')
encryptedMessage += cipher.final('base64')
let ivBase64 = Buffer.from(iv.buffer).toString('base64')
let event = {
pubkey: ourPubKey,
created_at: Math.floor(Date.now() / 1000),
kind: 4,
tags: [['p', theirPublicKey]],
content: encryptedMessage + '?iv=' + ivBase64
}
It seems some of the functions used in this snippet are not available in Erlang (or at least in default libraries).
getSharedSecret
Method
getSharedSecret
method create a common secret between a public and a private key. This function is defined in index.ts
in the noble-secp256k1 project.
In pure Elixir, the function get_shared_secret/3
defined in the Curvey module can do the same action.
In both case, others non-implemented functions will be required, like extracting the coordinate of the public/private key and implement Jacobian multiplication (noble-secp256k1 implementation.
The functions used are very small subset of all the feature available on secp256k1 bitcoin library. It could be interesting to create a function called nostrlib_secp256k1:get_shared_secret/3
functions. The same module could also integrated all other functions related to secp256k1 encryption like:
-
nostrlib_secp256k1:generate_key/0
: generate a new key with default options based oncrypto:generate_key/2
module. -
nostrlib_secp256k1:generate_key/1
: generate a new key with extra options. -
nostrlib_secp256k1:get_private_key/1
: extract the private key from the value returned bygenerate_key/0
function -
nostrlib_secp256k1:get_public_key/1
: extract the public key from the value returnedgenerate_key/0
function -
nostrlib_secp256k1:get_coordinates/1
: extract the coordinates of the key - ...
Using External Implementation
Using our own secp256k1 partial implementation in Erlang
pros:
- no dependencies at all
- only what we need
- could be a good introduction to elliptic curve encryption
cons:
- less secure
- require a lot of work (it should be secure enough to be used)
- require external audit
- using Erlang will be less performant than a C lib
- we should avoid re-implement cryptographic libraries
Using secp256k1 C NIF Elixir Implementation
pros:
- NIF: performance
- Use official bitcoin library
- Used by other projects
cons:
- Elixir: this project wants to use only pure Erlang code with only few external deps
- NIF: if not well implemented can do nasty thing
- NIF: requires to maintain an external C library and compile it for every releases
- old version of the library used by default: a really old version from 2018, based on the build_deps.sh script.
- seems to be not maintained since January 2020 (latest commit)
References and Resources
- Official NIP/04
- Bitcoin secp256k1 C89 Implementation
- secp256k1 Elixir implementation
- secp256k1 C NIF Elixir implementation
- Curvy secp256k1 pure Elixir implementation
- secp256k1 Python implementation using C code
- Secp256k1 on Bitcoin Wiki
- SEC 2: Recommended Elliptic Curve Domain Parameters
- Jacobian Coordinates on Wikibooks
- Elliptic Curve Cryptography in Practice
- Elliptic Curve Cryptography on Wikibooks