help icon indicating copy to clipboard operation
help copied to clipboard

How can I sign a message and verify it using ED25519 keys?

Open Dubz opened this issue 5 years ago • 17 comments

  • Node.js Version: 12.8.0
  • OS: Windows 10 (deployment will be on CentOS 7)
  • Scope (install, code, runtime, meta, other?): Code?
  • Module (and version) (if relevant): crypto

I am trying to have servers connect to a centralized server. To validate their identity, I am opting to use encryption/signing keys. I would prefer to use ED25519 if possible, but if I'm mistaking their ability for this, please let me know.

Also, please note that this is not SSL/SSH. This is just general data that will be passed along an application that also accepts clients (hence the verification necessity). The keys will serve to prove the server really is a server, and give it the necessary rights/access for more methods.

I've tried RSA and I can get it partially working, but I cannot get it to load the public key properly.

Here's what I've got so far. Only dependencies are the keys, which anyone can generate. I am using ed25519 and RSA 4096-bit for this test.

"use strict"

const fs = require("fs"),
    crypto = require("crypto");

// Let's set up some key files that can be easily rotated for testing
const keys = [
    {algorithm: 'ed25519', name: 'ed25519', passphrase: 'password', pem: false, ppk: false, pub: false, public: false, private: false},
    {algorithm: 'ed25519', name: 'ed25519_2', passphrase: 'password', pem: false, ppk: false, pub: false, public: false, private: false},
    {algorithm: 'rsa', name: 'rsa', passphrase: 'password', pem: false, ppk: false, pub: false, public: false, private: false},
];

// Select our key from the list above
const key = keys[2];
// Set a message to sign
const message = 'Hello world!';

// Load the files (that exist)
key.pem = (fs.existsSync("./" + key.name + ".pem")) ? fs.readFileSync("./" + key.name + ".pem") : false;
key.ppk = (fs.existsSync("./" + key.name + ".ppk")) ? fs.readFileSync("./" + key.name + ".ppk") : false;
key.pub = (fs.existsSync("./" + key.name + ".pub")) ? fs.readFileSync("./" + key.name + ".pub") : false;

// Verify what was loaded
console.log(key.pem.toString(), "\n\n", key.ppk.toString(), "\n\n", key.pub.toString(), "\n\n");


// At this point, we have our key data and messages. Let's continue

// Create the public/private key objecs for sign/verify
key.private = crypto.createPrivateKey({key: key.pem, passphrase: key.passphrase});
// key.public = crypto.createPublicKey(key.private);
key.public = crypto.createPublicKey({key: key.pub});


// Sign message with private key
const sign = crypto.createSign('RSA-SHA512');
sign.update(message);
const sig = sign.sign(key.private);

console.log('Signed!');
console.log(sig);

// Verify signature with public key
console.log('Verifying signature...');

const verify = crypto.createVerify('RSA-SHA512');
verify.update(message);
const verified = verify.verify(key.public, sig);

// Results?
console.log('Match:', verified);

If I use the private key object to create the public key object, it works. If I use the public key to ry and create the public key object, it fails. Obviously I need to be able to have the public key on a separate server to verify without the private key, so that's where I'm stumped. This is for RSA. ED25519, can't even get the private key object.

RSA public key object error:

internal/crypto/keys.js:321
  handle.init(data, format, type);
         ^

Error: error:0909006C:PEM routines:get_name:no start line
    at Object.createPublicKey (internal/crypto/keys.js:321:10)
    at Object.<anonymous> (C:\Users\...\Desktop\test_signing\exec.js:24:21)
    at Module._compile (internal/modules/cjs/loader.js:868:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:879:10)
    at Module.load (internal/modules/cjs/loader.js:731:32)
    at Function.Module._load (internal/modules/cjs/loader.js:644:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:931:10)
    at internal/main/run_main_module.js:17:11 {
  library: 'PEM routines',
  function: 'get_name',
  reason: 'no start line',
  code: 'ERR_OSSL_PEM_NO_START_LINE'
}

ED25519 private key object error:

internal/crypto/keys.js:329
  handle.init(data, format, type, passphrase);
         ^

Error: error:0909006C:PEM routines:get_name:no start line
    at Object.createPrivateKey (internal/crypto/keys.js:329:10)
    at Object.<anonymous> (C:\Users\...\Desktop\test_signing\exec.js:30:22)
    at Module._compile (internal/modules/cjs/loader.js:868:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:879:10)
    at Module.load (internal/modules/cjs/loader.js:731:32)
    at Function.Module._load (internal/modules/cjs/loader.js:644:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:931:10)
    at internal/main/run_main_module.js:17:11 {
  library: 'PEM routines',
  function: 'get_name',
  reason: 'no start line',
  code: 'ERR_OSSL_PEM_NO_START_LINE'
}

They error with the same reason, but I have no idea what that is. Any help would be greatly appreciated!!!

Dubz avatar Sep 25 '19 15:09 Dubz