use tiny-secp256k1, updated nip06 and other utils.

This commit is contained in:
fiatjaf
2021-12-29 14:29:43 -03:00
parent faa308049f
commit 60fc0d7940
7 changed files with 61 additions and 31 deletions

View File

@@ -67,4 +67,6 @@ pool.addRelay('<url>')
// will automatically subscribe to the all the events called with .sub above // will automatically subscribe to the all the events called with .sub above
``` ```
All functions expect bytearrays as hex strings and output bytearrays as hex strings.
For other utils please read the source (for now). For other utils please read the source (for now).

View File

@@ -1,7 +1,6 @@
import {Buffer} from 'buffer' import {Buffer} from 'buffer'
import * as secp256k1 from '@noble/secp256k1' import createHash from 'create-hash'
import {signSchnorr, verifySchnorr} from 'tiny-secp256k1'
import {sha256} from './utils'
export function getBlankEvent() { export function getBlankEvent() {
return { return {
@@ -24,20 +23,24 @@ export function serializeEvent(evt) {
]) ])
} }
export async function getEventHash(event) { export function getEventHash(event) {
let eventHash = await sha256(Buffer.from(serializeEvent(event))) let eventHash = createHash('sha256')
.update(Buffer.from(serializeEvent(event)))
.digest()
return Buffer.from(eventHash).toString('hex') return Buffer.from(eventHash).toString('hex')
} }
export async function verifySignature(event) { export function verifySignature(event) {
return await secp256k1.schnorr.verify( if (event.id !== getEventHash(event)) return false
event.sig, return verifySchnorr(
await getEventHash(event), Buffer.from(event.id, 'hex'),
event.pubkey Buffer.from(event.pubkey, 'hex')
Buffer.from(event.sig, 'hex'),
) )
} }
export async function signEvent(event, key) { export function signEvent(event, key) {
let eventHash = await getEventHash(event) let eventHash = Buffer.from(getEventHash(event), 'hex')
return await secp256k1.schnorr.sign(eventHash, key) let key = Buffer.from(key, 'hex')
return Buffer.from(signSchnorr(eventHash, key)).toString('hex')
} }

View File

@@ -1,3 +1,4 @@
import {generatePrivateKey, getPublicKey} from './keys'
import {relayConnect} from './relay' import {relayConnect} from './relay'
import {relayPool} from './pool' import {relayPool} from './pool'
import { import {
@@ -8,7 +9,6 @@ import {
getEventHash getEventHash
} from './event' } from './event'
import {matchFilter, matchFilters} from './filter' import {matchFilter, matchFilters} from './filter'
import {makeRandom32, sha256, getPublicKey} from './utils'
export { export {
relayConnect, relayConnect,
@@ -17,8 +17,6 @@ export {
verifySignature, verifySignature,
serializeEvent, serializeEvent,
getEventHash, getEventHash,
makeRandom32,
sha256,
getPublicKey, getPublicKey,
getBlankEvent, getBlankEvent,
matchFilter, matchFilter,

19
keys.js Normal file
View File

@@ -0,0 +1,19 @@
import randomBytes from 'randombytes'
import {isPrivate, pointFromScalar} from 'tiny-secp256k1'
export function generatePrivateKey() {
let i = 8
while (i--) {
let r32 = Buffer.from(randomBytes(32))
if (isPrivate(r32)) return r32.toString('hex')
}
throw new Error(
'Valid private key was not found in 8 iterations. PRNG is broken'
)
}
export function getPublicKey(privateKey) {
return Buffer.from(
pointFromScalar(Buffer.from(privateKey, 'hex'), true)
).toString('hex')
}

View File

@@ -1,17 +1,28 @@
import createHmac from 'create-hmac' import createHmac from 'create-hmac'
import randomBytes from 'randombytes' import {wordlist} from 'micro-bip39/wordlists/english'
import * as bip39 from 'bip39' import {
generateMnemonic,
mnemonicToSeedSync,
validateMnemonic
} from 'micro-bip39'
import BIP32Factory from 'bip32'
import * as ecc from 'tiny-secp256k1'
const bip32 = BIP32Factory(ecc)
export function privateKeyFromSeed(seed) { export function privateKeyFromSeed(seed) {
let hmac = createHmac('sha512', Buffer.from('Nostr seed', 'utf8')) let root = bip32.fromSeed(Buffer.from(seed, 'hex'))
hmac.update(seed) return root.derivePath(`m/44'/1237'/0'/0'`).privateKey.toString('hex')
return hmac.digest().slice(0, 32).toString('hex')
} }
export function seedFromWords(mnemonic) { export function seedFromWords(mnemonic) {
return bip39.mnemonicToSeedSync(mnemonic) return Buffer.from(mnemonicToSeedSync(mnemonic, wordlist)).toString('hex')
} }
export function generateSeedWords() { export function generateSeedWords() {
return bip39.entropyToMnemonic(randomBytes(16).toString('hex')) return generateMnemonic(wordlist)
}
export function validateWords(words) {
return validateMnemonic(words, wordlist)
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "nostr-tools", "name": "nostr-tools",
"version": "0.11.0", "version": "0.12.1",
"description": "Tools for making a Nostr client.", "description": "Tools for making a Nostr client.",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -8,12 +8,15 @@
}, },
"dependencies": { "dependencies": {
"@noble/secp256k1": "^1.3.0", "@noble/secp256k1": "^1.3.0",
"bip39": "^3.0.4", "bip32": "^3.0.1",
"browserify-cipher": ">=1", "browserify-cipher": ">=1",
"buffer": ">=5", "buffer": ">=5",
"create-hash": "^1.2.0",
"create-hmac": ">=1", "create-hmac": ">=1",
"dns-packet": "^5.2.4", "dns-packet": "^5.2.4",
"micro-bip39": "^0.1.3",
"randombytes": ">=2", "randombytes": ">=2",
"tiny-secp256k1": "^2.1.2",
"websocket-polyfill": "^0.0.3" "websocket-polyfill": "^0.0.3"
}, },
"keywords": [ "keywords": [

View File

@@ -1,6 +0,0 @@
import * as secp256k1 from '@noble/secp256k1'
export const makeRandom32 = () => secp256k1.utils.randomPrivateKey()
export const sha256 = m => secp256k1.utils.sha256(Uint8Array.from(m))
export const getPublicKey = privateKey =>
secp256k1.schnorr.getPublicKey(privateKey)