paulmillr / noble-ed25519

Fastest 4KB JS implementation of ed25519 signatures
https://paulmillr.com/noble
MIT License
420 stars 51 forks source link

Can not make it generate or verify the signature #96

Closed rdzidziguri closed 1 year ago

rdzidziguri commented 1 year ago

I have a situation where the public key and signature were generated using the PHP sodium library and handed over. Unfortunately, we can not verify it using Node 18

node -v v18.12.1 online tools used to verify the signature

https://cyphr.me/ed25519_tool/ed.html https://tweetnacl.js.org/#/sign

here is the code snippet for PoC; however, some tools are verifying it successfully

import * as ed from '@noble/ed25519'
import { webcrypto } from 'crypto'
if (!globalThis.crypto) globalThis.crypto = webcrypto

const pubKey = 'u/zKprNUWuEWIdxEfhj8H0JILQ1H2zMgXeTjwTADS/o='
const sig = 'JvYm5nAQx5Y9dD0JURkTb4JvposPKBUsJ+wFVqmV668J7w+Kebm30mH2eaRfcZgZR8G+bhQtaC7eJ8p9f7YCAA=='
const msg = `GET\n/partner/v5/partners\nTue, 25 Jul 2023 14:29:02 +0000`

const pubKeyh = Uint8Array.from(Buffer.from(pubKey, 'base64'))
const sigH = Uint8Array.from(Buffer.from(sig, 'base64'))
const msgk = Uint8Array.from(Buffer.from(msg, 'utf8'))

await (async () => {
  const isValid = await ed.verifyAsync(sigH, msgk, pubKeyh);
  console.log(isValid);
})();

I suspect it might be related to encoding or some conversion, but I'm not sure where to start.

paulmillr commented 1 year ago

this clearly fails verification with tweetnacl:

import tweetnacl from 'tweetnacl';
console.log(tweetnacl.sign.detached.verify(msgk, sigH, pubKeyh))

so, dig deeper, investigate how utf8/base64 is converted, check if @scure/base conversion is any different, etc.

rdzidziguri commented 1 year ago

@paulmillr strange image

I also tried with https://www.npmjs.com/package/base64-js; unfortunately, I got the same result.

import * as ed from '@noble/ed25519'
import { base64 } from '@scure/base'
import { webcrypto } from 'crypto'
if (!globalThis.crypto) globalThis.crypto = webcrypto

const pubKey = `u/zKprNUWuEWIdxEfhj8H0JILQ1H2zMgXeTjwTADS/o=`
const sig = `JvYm5nAQx5Y9dD0JURkTb4JvposPKBUsJ+wFVqmV668J7w+Kebm30mH2eaRfcZgZR8G+bhQtaC7eJ8p9f7YCAA==`
const msg = `GET\n/partner/v5/partners\nTue, 25 Jul 2023 14:29:02 +0000`

const pubKeyh = base64.decode(pubKey)
const sigH = base64.decode(sig)
const msgk = Uint8Array.from(Buffer.from(msg, 'utf8'))

await (async () => {
    const isValid = await ed.verifyAsync(sigH, msgk, pubKeyh);
    console.log(isValid);
})();

The output is still false.

rdzidziguri commented 1 year ago

I think I found the issue. It has nothing to do with this library or encoding/decoding. Wrong

const msg = `GET\n/partner/v5/partners\nTue, 25 Jul 2023 14:29:02 +0000`

Correct

const msg = 'GET\\n/partner/v5/partners\\nTue, 25 Jul 2023 14:29:02 +0000'

So as in many cases, dummy tupo, when including newling it, should be \\n not \n @paulmillr you can close this issue. My apologies.