From 0fecb2dab8cd125acc05b3eef31db569c80fc711 Mon Sep 17 00:00:00 2001 From: Attila Mravik <4715833+evik42@users.noreply.github> Date: Fri, 7 Apr 2023 14:37:09 +0200 Subject: [PATCH] Example JS program to verify Golem certificate signatures. --- examples/js/.gitignore | 1 + examples/js/README.md | 8 ++ examples/js/index.js | 28 +++++++ examples/js/package-lock.json | 83 +++++++++++++++++++ examples/js/package.json | 15 ++++ .../certificate/invalid_signature.signed.json | 4 +- 6 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 examples/js/.gitignore create mode 100644 examples/js/README.md create mode 100644 examples/js/index.js create mode 100644 examples/js/package-lock.json create mode 100644 examples/js/package.json diff --git a/examples/js/.gitignore b/examples/js/.gitignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/examples/js/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/examples/js/README.md b/examples/js/README.md new file mode 100644 index 0000000..b488278 --- /dev/null +++ b/examples/js/README.md @@ -0,0 +1,8 @@ +To use this example install dependencies via `npm install`. + +Verifying a certificate signature (just the signature, not the certificate chain) can be accomplished by running the program: +`node . certificate-path` where certificate path is the path to a Golem certificate json. + +Example: +`node . ../../tests/resources/certificate/happy_path.signed.json` - this should print that the signature is valid +`node . ../../tests/resources/certificate/invalid_signature.signed.json` - this should print that the verification failed diff --git a/examples/js/index.js b/examples/js/index.js new file mode 100644 index 0000000..530d92f --- /dev/null +++ b/examples/js/index.js @@ -0,0 +1,28 @@ +const fs = require('fs'); +const canonicalize = require('canonicalize'); +const elliptic = require('elliptic'); + +const filename = process.argv[process.argv.length - 1]; +console.log("Reading certificate from file " + filename); + +const certificate_data = fs.readFileSync(filename); +const certificate = JSON.parse(certificate_data); +const signing_certificate = certificate.signature.signer === "self" ? certificate : certificate.signature.signer; + +if (certificate.signature.algorithm.hash !== "sha512" + || certificate.signature.algorithm.encryption !== "EdDSA" + || signing_certificate.certificate.publicKey.parameters.scheme !== "Ed25519") { + console.log("Unsupported signature type"); + process.exit(1); +} + +const encoder = new TextEncoder(); +const signed_bytes = encoder.encode(canonicalize(certificate.certificate)); // encode the string into bytes with UTF-8 encoding + +const result = elliptic.eddsa('ed25519').verify(signed_bytes, certificate.signature.value, signing_certificate.certificate.publicKey.key); + +if (result) { + console.log("The signature is valid."); +} else { + console.log("Signature verification failed."); +} diff --git a/examples/js/package-lock.json b/examples/js/package-lock.json new file mode 100644 index 0000000..cf2c765 --- /dev/null +++ b/examples/js/package-lock.json @@ -0,0 +1,83 @@ +{ + "name": "golem-certificate", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "golem-certificate", + "version": "0.1.0", + "license": "GPLv3", + "dependencies": { + "canonicalize": "^2.0.0", + "elliptic": "^6.5.4" + }, + "bin": { + "golem-certificate": "index.js" + } + }, + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "node_modules/canonicalize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.0.0.tgz", + "integrity": "sha512-ulDEYPv7asdKvqahuAY35c1selLdzDwHqugK92hfkzvlDCwXRRelDkR+Er33md/PtnpqHemgkuDPanZ4fiYZ8w==" + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + } + } +} diff --git a/examples/js/package.json b/examples/js/package.json new file mode 100644 index 0000000..db5fbe4 --- /dev/null +++ b/examples/js/package.json @@ -0,0 +1,15 @@ +{ + "name": "golem-certificate", + "version": "0.1.0", + "description": "Example to verify golem-certificate signature", + "main": "index.js", + "bin": { + "golem-certificate": "index.js" + }, + "author": "evik (https://github.com/evik42)", + "license": "GPLv3", + "dependencies": { + "canonicalize": "^2.0.0", + "elliptic": "^6.5.4" + } +} diff --git a/tests/resources/certificate/invalid_signature.signed.json b/tests/resources/certificate/invalid_signature.signed.json index 82036e5..bd67c00 100644 --- a/tests/resources/certificate/invalid_signature.signed.json +++ b/tests/resources/certificate/invalid_signature.signed.json @@ -19,7 +19,7 @@ }, "publicKey": { "algorithm": "EdDSA", - "key": "c6cd286a2474d13ffc8dcd417a446df461751a78dec46d039603ca53a373ac52", + "key": "c6cd286a2474d13ffc8dcd417a446df461751a78dec46d039603ca53a373ac53", "parameters": { "scheme": "Ed25519" } @@ -30,7 +30,7 @@ "hash": "sha512", "encryption": "EdDSA" }, - "value": "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef", + "value": "839a2d43d22690338f4fb282e7bcc790e7352dc99e42dc603d43e51e4e09f2c709f1b9f1f4c90b446107440f8ab13345fbbd1d64337acf70b2777be9a522be0b", "signer": { "$schema": "https://golem.network/schemas/v1/certificate.schema.json", "certificate": {