question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ed25519Signature2018 verification yields "Invalid Signature" error

See original GitHub issue

Hi,

I am having difficulties in actually verifying the VP I have created.

The error is simply:

Error: Invalid signature.
 at Ed25519Signature2018.verifyProof (/Users/moustachiste/work/verifiable-presentation/node_modules/jsonld-signatures/lib/suites/LinkedDataSignature.js:162:15)

So tried to dive into where the error was coming from, but I reached a low level of node-gyp (from here: https://github.com/digitalbazaar/crypto-ld/blob/master/lib/Ed25519KeyPair.js#L551) and with non human readable data so that didn’t help.

My hunch is that the suite I use to sign and to verify are somehow not identical, or wrongly used/implemented.

So here is my process:

  • I create and sign a presentation as follows:
  const presentation = vc.createPresentation({
    verifiableCredential: certs
  });

  const suite = await generateSigningSuite();

  const verifiablePresentation = await vc.signPresentation({
    presentation,
    suite,
    challenge: 'yo',
    documentLoader // custom loader resolves Blockcerts, DID document and context urls 
  });
  • I generate the suite as follows
  const keyPair = await Ed25519KeyPair.generate({
    id: DID.authentication[0],
    controller: DID.id
  });

  const suite = new Ed25519Signature2018({
    verificationMethod: keyPair.id,
    key: keyPair
  });

And this is the DID document I am using to generate the signature:

{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca",
  "publicKey": [
    {
      "id": "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca#z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca",
      "type": "Ed25519VerificationKey2018",
      "controller": "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca",
      "publicKeyBase58": "Asrb847AmCCTmjeiQCHR5DtRaHs5KfvjXBWCNM1zh3qC"
    }
  ],
  "authentication": [
    "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca#z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca"
  ],
  "assertionMethod": [
    "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca#z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca"
  ],
  "capabilityDelegation": [
    "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca#z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca"
  ],
  "capabilityInvocation": [
    "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca#z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca"
  ],
  "keyAgreement": [
    {
      "id": "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca#zCHKnNyBrWe3eoiaUZhgcNtNYrcP25XwfDVnCXxbedk3MT",
      "type": "X25519KeyAgreementKey2019",
      "controller": "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca",
      "publicKeyBase58": "Hq4fc13KGJNNcXW7JC3QjCsZN7D7yF3ibtuW7WrEdoFF"
    }
  ]
}
  • To verify, this is the code I have written:
  const suite = [new Ed25519Signature2018(presentation.proof), prepareMerkleProof2019Suite(presentation.verifiableCredential[0].proof)]; // second suite to verify Blockcerts VC
  vc.verify({presentation, suite, documentLoader, challenge: 'yo'}).then((verificationStatus) => {
    return res.json(verificationStatus);
  });

And the presentation.proof, in my assumption, coming from the previous signPresentation instruction:

  "proof": {
    "type": "Ed25519Signature2018",
    "created": "2020-02-27T13:15:57Z",
    "challenge": "yo",
    "jws": "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..62FLffkSzfVJ26E2kAIrQKgp1bKii54u1KJbLxkYqtW_6hEPCL0voaxrR0hufUyYQZc8tvzJ0UgpbxvSFBODCQ",
    "proofPurpose": "authentication",
    "verificationMethod": "did:key:z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca#z6MkpL7diJMc6jgvtEVR5mFFvKSRPs8vjZB6DCR8Ccz1cGca"
  }

(you may find the full presentation example in the previous issue I opened https://github.com/digitalbazaar/vc-js/issues/48#issue-570605457 although note that the JWS is likely different since I regenerated the presentation multiple times to investigate).

It is worth noting, than contrary to the unit tests (https://github.com/digitalbazaar/vc-js/blob/master/tests/10-verify.spec.js#L184), this happens in 2 different and separate node instructions, so I do not maintain one and unique JS object for the suite, but rather rely on JSON data to “communicate between suites”. I run npm run generate:presentation and npm run verify:presentation.

Thanks for reading

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:18 (13 by maintainers)

github_iconTop GitHub Comments

1reaction
aljones15commented, Feb 27, 2020

So that all worked, thanks @aljones15 for pointing to the right direction. @dlongley since I had the VC already verifying, it wasn’t polluting the output, so once I implemented the correct way the verification was easy.

The only thing I don’t like in my implementation (and since this is PoC work it does not matter much), is that everything is sequential and happening in the same execution. I would like to be able to separate items to be instructed step by step. However, what I have noticed is that often times, the different methods (ie: Ed25519KeyPair or Ed25519Signature2018) not only produce data, but also are classes with executable methods. Would I be able to reinstantiate the classes with the data that was initially produced?

More concrete example: This is my keyPair generated data.

{
  "passphrase": null,
  "id": "did:key:z6Mkq3L1jEDDZ5R7eT523FMLxC4k6MCpzqD7ff1CrkWpoJwM#z6Mkq3L1jEDDZ5R7eT523FMLxC4k6MCpzqD7ff1CrkWpoJwM",
  "controller": "did:key:z6Mkq3L1jEDDZ5R7eT523FMLxC4k6MCpzqD7ff1CrkWpoJwM",
  "type": "Ed25519VerificationKey2018",
  "privateKeyBase58": "3AvNk9VpgjGPwyThyWqxPmZtW5BrdWaFJNJejNWAhXWkKjPapA8qjwUF85L3kyatS1KcHqbjTSktmRD2m1ARHoco",
  "publicKeyBase58": "Bb4y8yxnDXveXxEKMgPW76WkGmvyawxkye6H2UYot69y"
}

If I don’t maintain the JS object (execute in the same runtime), am I able to re-create a keyPair object from this data, but with methods attached?

yes, use the Ed25519KeyPair.from method. This will save time in tests to as you can store the keymaterial as json. Because your key.export contains the type you could even use LDKeyPair.from using that JSON output.

https://github.com/digitalbazaar/crypto-ld/blob/892c5950b739847ae2aa2b893152a26f14f32a1d/lib/LDKeyPair.js#L89-L117

You would need to call keyToDidDoc on the result of the from though.

1reaction
aljones15commented, Feb 27, 2020

Actually you need to go the other way (this is WRT to having a signing key and a didKey that match):

const {keyToDidDoc} = require('did-method-key').driver();
const {Ed25519KeyPair} = require('crypto-ld');
// this produces a keypair with private key material
  // used for signing credentials / presentations
  keyPair = await Ed25519KeyPair.generate();
  // this is a did key document which only contains
  // the public key material used to verify a credential
 didDocument = keyToDidDoc(keyPair);
 // this can be assertionMethod etc.
 // if your purpose is Authentication then use authentication
 keyPair.id = didDocument.authentication[0];

yeah looking at this further I think this is your mistake: you are creating a new private key to sign the presentation and then using a didDocument’s authentication key to verify. You need to go the other way around:

  1. create a keyPair
  2. use that keyPair to create the didDocument
  3. use the keyPair to sign
  4. use the didDocument’s authentication key to verify.
Read more comments on GitHub >

github_iconTop Results From Across the Web

Invalid signature error from ethers when trying to verify a ...
When trying to verify a signature from Ambire wallet, I get "Error: invalid signature string" from ethers.utils.verifyMessage For example ...
Read more >
Ed25519 Signature 2018 - W3C Credentials Community Group
This specification describes a standard signature suite created in 2018 ... This specification was published by the W3C Digital Verification ...
Read more >
Why am I getting an "Invalid Signature" error when the
When I double-click on the signature there is a yellow banner at the top that says "Verification error - This signature was not...
Read more >
@transmute/ed25519-signature-2018 - npm
Start using @transmute/ed25519-signature-2018 in your project by running `npm i @transmute/ed25519-signature-2018`.
Read more >
Signature Verification Errors in solidity-coverage
contract Member { using ECDSAUpgradeable for bytes32; ... function join( bytes memory signature, ) public returns (uint256) { bytes32 _hash ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found