Verifying keys with @dfinity/agent + @dfinity/identity

Hello, I’m building an application that does custody verification of cryptographic keys and I’ve been able to create keys and sign messages with @dfinity/identity npm module. Using as follows:

// Key Generation
var [pubKey, privKey] = identity.Ed25519KeyIdentity.generate().toJSON();

// Sign Message
var privArrayBuff = fromHexString(privKey);
var keyIdObject = identity.Ed25519KeyIdentity.fromSecretKey(privArrayBuff);

var msgArrayBuff = fromHexString(msg);
var sig = await keyIdObject.sign(msgArrayBuff);
return toHexString(sig);

// Verify?
const msgArrayBuff = new Uint8Array(fromHexString(msg));
const sigArrayBuff = new Uint8Array(fromHexString(sig));
const pubKeyArrayBuff = new Uint8Array(fromHexString(pubKey));

var isVerified = blsVerify(msgArrayBuff, sigArrayBuff, pubKeyArrayBuff); // from @dfinity/agent

I’m looking the docs and at the source code.

The current implementation is yielding:

(node:11812) UnhandledPromiseRejectionWarning: RuntimeError: unreachable
    at <anonymous>:wasm-function[51]:0x9f87
    at <anonymous>:wasm-function[113]:0xb201
    at <anonymous>:wasm-function[104]:0xb03f
    at <anonymous>:wasm-function[112]:0xb1c2
    at <anonymous>:wasm-function[60]:0xa35c
    at <anonymous>:wasm-function[0]:0xd5a
    at bls_verify (<anonymous>:wasm-function[39]:0x9947)

I am trying to run this application on a node app, is there a way to handle the yield without using WASM? Thanks!

When you build your code for canister deployment, it’s compiled to WASM. And I don’t believe there’s a way around it.

Where does msg come from? Can you provide me with an example case so I can verify your setup?

I also noticed that you’re declaring then overwriting msgArrayBuff here - I assume this is because these snippets are from multiple functions in your codebase

@CarstenJ thanks for the info, I’ll keep that in mind. And @kpeacock msg is a user passed param, just a string.

I ran into that error a couple of times when working with the rust-wasm-bls code, try checking the lengths of each parameter right before it calls the wasm function. I think the bls code will throw if one or some of the parameters (message,key, and signature ) have an invalid length.

1 Like

You’re not going to get around the call to the BLS wasm - it’s vastly more efficient than a JS-implemented solution, and we don’t currently allow for skipping the signature checking. I suppose we could, by allowing for some kind of DANGEROUS_BYPASS_VALIDATION flag, which might also be useful for mobile development.

Node.js is fully supported for BLS validation though; we run all our tests in node. I’d investigate your inputs, and suggest developing in TypeScript, to let the compiler help you catch any assumptions that don’t line up.

1 Like

Thanks for the info - I did build my app in typescript and seem to be able to work with the test data you all used on the bls.test.js. The pk variable passed is a primary key - but I would expect it to be the public key. Are these examples generated from the @dfinity/identity module getKeyPair and sign methods?

Your code is trying to verify an Ed25519 signature with a bls12381 verify function. These are two different cryptography-schemes. The bls is for the verification of the IC’s-single-public-key (I think 48 bytes) , the Ed25519 (I think 32 bytes) is the scheme that is used for the authorization of a call by a user-caller.

How would I then verify an ED25519 signature? I know that the public and private keys generation and signing is dependent on the tweetnacl node package - does Dfinity not provide a way to do this in one of their packages already?

For anyone finding themselves with a similar issue, look at the ED25519 @dfinity/Identity package for the keygen and sign functions and how they implement tweetnacl - then use tweetnacl for the verify as well.

2 Likes

Answered it yourself! Yes, I’d recommend importing tweetnacl and using the package directly