v.3.2.3: add support for secp256k1 keys

This commit is contained in:
nixer89
2025-09-25 10:40:34 +02:00
parent e364fae513
commit 9b5de61a2f
2 changed files with 50 additions and 10 deletions

View File

@@ -5,6 +5,8 @@
import elliptic from 'elliptic'
const ed25519 = elliptic.eddsa('ed25519')
const secp256k1 = elliptic.ec('secp256k1')
import { createHash } from 'crypto';
import fetch from 'node-fetch'
import address from 'ripple-address-codec'
@@ -97,12 +99,36 @@ const fetchUnl = (url, master_public_key) => {
const manifest = parse_manifest(Buffer.from(json.manifest, 'base64'))
// verify manifest signature and payload signature
const master_key = ed25519.keyFromPublic(master_public_key.slice(2), 'hex')
assert(master_key.verify(manifest.without_signing_fields, manifest.MasterSignature),
"Master signature in master manifest does not match vl key")
let signing_key = ed25519.keyFromPublic(manifest.SigningPubKey.slice(2), 'hex')
assert(signing_key.verify(blob.toString('hex'), json.signature),
"Payload signature in mantifest failed verification")
// distinguish between ed25519 and secp256k1
let master_key = null;
if(master_public_key.startsWith('ED')) {
master_key = ed25519.keyFromPublic(master_public_key.slice(2), 'hex');
assert(master_key.verify(manifest.without_signing_fields, manifest.MasterSignature),
"Master signature in master manifest does not match ed25519 vl key")
} else {
master_key = secp256k1.keyFromPublic(master_public_key, 'hex');
assert(master_key.verify(manifest.without_signing_fields, manifest.MasterSignature),
"Master signature in master manifest does not match secp256k1 vl key");
}
let signing_key = null;
if(manifest.SigningPubKey.toUpperCase().startsWith('ED')) {
signing_key = ed25519.keyFromPublic(manifest.SigningPubKey.slice(2), 'hex')
assert(signing_key.verify(blob.toString('hex'), json.signature),
"Payload signature in mantifest failed verification with ed25519")
} else {
signing_key = secp256k1.keyFromPublic(manifest.SigningPubKey.toString('hex'), 'hex');
//sha512 half the blob!
//https://xrpl.org/cryptographic-keys.html#key-derivation
let sha512Blob = createHash("sha512").update(blob);
let sha512HalfBuffer = sha512Blob.digest().slice(0,32);
assert(signing_key.verify(sha512HalfBuffer, json.signature),
"Payload signature in mantifest failed verification with SECP256K1")
}
blob = JSON.parse(blob)
assert(blob.validators !== undefined, "validators missing from blob")
@@ -118,10 +144,24 @@ const fetchUnl = (url, master_public_key) => {
let manifest = parse_manifest(Buffer.from(blob.validators[idx].manifest, 'base64'))
// verify signature
signing_key = ed25519.keyFromPublic(blob.validators[idx].validation_public_key.slice(2), 'hex')
assert(signing_key.verify(manifest.without_signing_fields, manifest.MasterSignature),
"Validation manifest " + idx + " signature verification failed")
let publicKey = blob.validators[idx].validation_public_key;
if (publicKey.slice(0, 1) === 'n') {
const publicKeyBuffer = codec.address.decodeNodePublic(publicKey);
publicKey = publicKeyBuffer.toString("hex").toUpperCase();
}
if(publicKey.toUpperCase().startsWith('ED')) {
signing_key = ed25519.keyFromPublic(publicKey.slice(2), 'hex')
assert(signing_key.verify(manifest.without_signing_fields, manifest.MasterSignature),
"Validation manifest " + idx + " signature verification failed with ed25519");
} else {
signing_key = secp256k1.keyFromPublic(publicKey, 'hex');
const computedHash = createHash("sha512").update(manifest.without_signing_fields).digest().toString("hex").slice(0, 32);
assert(signing_key.verify(computedHash, manifest.MasterSignature), "Validation manifest " + idx + " signature verification failed with secp256k1");
}
blob.validators[idx].validation_public_key = Buffer.from(blob.validators[idx].validation_public_key, 'hex')
blob.validators[idx].manifest = manifest

View File

@@ -1,6 +1,6 @@
{
"name": "xpopgen",
"version": "3.2.2",
"version": "3.2.3",
"description": "Store XRPL Proof of Validation messages",
"main": "index.mjs",
"scripts": {