digitalbazaar / jsonld-signatures

An implementation of the Linked Data Signatures specification for JSON-LD. Works in the browser and Node.js.
BSD 3-Clause "New" or "Revised" License
136 stars 41 forks source link

Readme example out of date #79

Closed OR13 closed 4 years ago

OR13 commented 4 years ago

"jsonld-signatures": "^4.4.0",

Signature verification error: Error: Could not verify any proofs; no proofs matched the required suite and purpose.

The following code with corrected keys for reproducing:

const jsigs = require("jsonld-signatures");
const { Ed25519KeyPair } = require("crypto-ld");
const { Ed25519Signature2018 } = jsigs.suites;
const { AssertionProofPurpose, AuthenticationProofPurpose } = jsigs.purposes;

const { documentLoaders } = require("jsonld");

const publicKeyBase58 = "J5QHWFQNREPBnmwCDXZgzy5FjvDGFkLEgWVoEociTfXz";
const privateKeyBase58 =
  "2zFSMA9EHEuEfFNydcMehd8a11PjFwKdTTkHaXKEvoajSAKAMi1zny5Bob4eCgWYUNa7RTkkYydz6CBAS6eqGmLg";

// specify the public key object
const publicKey = {
  "@context": jsigs.SECURITY_CONTEXT_URL,
  type: "Ed25519VerificationKey2018",
  id: "https://example.com/i/alice/keys/2",
  controller: "https://example.com/i/alice",
  publicKeyBase58
};

// specify the public key controller object
const controller = {
  "@context": jsigs.SECURITY_CONTEXT_URL,
  id: "https://example.com/i/alice",
  publicKey: [publicKey],
  // this authorizes this key to be used for authenticating
  authentication: [publicKey.id]
};

// create the JSON-LD document that should be signed
const doc = {
  "@context": {
    schema: "http://schema.org/",
    action: "schema:action"
  },
  action: "AuthenticateMe"
};

describe("ed25519", () => {
  it("sign verify", async () => {
    const signed = await jsigs.sign(doc, {
      suite: new Ed25519Signature2018({
        verificationMethod: publicKey.id,
        key: new Ed25519KeyPair({ privateKeyBase58, publicKeyBase58 })
      }),
      purpose: new AuthenticationProofPurpose({
        challenge: "abc",
        domain: "example.com"
      })
      //   compactProof: false
    });

    console.log("Signed document:", signed);
    // we will need the documentLoader to verify the controller
    const { node: documentLoader } = documentLoaders;

    // verify the signed document
    const result = await jsigs.verify(signed, {
      documentLoader,
      suite: new Ed25519Signature2018({
        key: new Ed25519KeyPair({ publicKeyBase58 })
      }),
      purpose: new AuthenticationProofPurpose({
        controller,
        challenge: "abc",
        domain: "example.com"
      })
      //   compactProof: false
    });

    if (result.verified) {
      console.log("Signature verified.");
    } else {
      console.log("Signature verification error:", result.error);
    }
  });
});
OR13 commented 4 years ago

This is likely to do with the differences in "Ed25519KeyPair" in crypto-ld...

The id property is expected... and must be passed as constructor args:

key: new Ed25519KeyPair({ publicKeyBase58, id: publicKey.id })

https://github.com/digitalbazaar/jsonld-signatures/blob/master/lib/suites/JwsLinkedDataSignature.js#L184

OR13 commented 4 years ago

This is my bad, I copied the example incorrectly.

OR13 commented 4 years ago

For any future searches, here is example code for working with DID Documents...

const jsigs = require("jsonld-signatures");
const { Ed25519KeyPair } = require("crypto-ld");
const { Ed25519Signature2018 } = jsigs.suites;
const { AssertionProofPurpose, AuthenticationProofPurpose } = jsigs.purposes;

const wrappedDocumentLoader = require("../func/wrappedDocumentLoader");

const keypair = {
  publicKey: "J5QHWFQNREPBnmwCDXZgzy5FjvDGFkLEgWVoEociTfXz",
  privateKey:
    "2zFSMA9EHEuEfFNydcMehd8a11PjFwKdTTkHaXKEvoajSAKAMi1zny5Bob4eCgWYUNa7RTkkYydz6CBAS6eqGmLg"
};

const didDoc = {
  "@context": "https://w3id.org/did/v1",
  id: "did:example:456",
  publicKey: [
    {
      "@context": jsigs.SECURITY_CONTEXT_URL,
      type: "OpenPgpVerificationKey2019",
      id: "did:example:456#nUN4nXQS5MwaLtSGPiWv0Cx7_WbZ6-BcXow6g6g_LEs",
      controller: "did:example:456",
      publicKeyPem:
        "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: OpenPGP.js v4.4.7\r\nComment: https://openpgpjs.org\r\n\r\nxk8EXNtmfBMFK4EEAAoCAwQ22JuKLOw0REjgH3KPldvpQLyPbevO6nd/vs/h\r\nUyBgRDFhB66eam0Kg0K/bFspd7EqBQf5sg4MjtW2g+UlMNuAzRdhbm9uIDxh\r\nbm9uQGV4YW1wbGUuY29tPsJ3BBATCAAfBQJc22Z8BgsJBwgDAgQVCAoCAxYC\r\nAQIZAQIbAwIeAQAKCRDWxr9HLkZ5BNroAP9SBAXVyU8FWTMPoKagkeiZO5ke\r\nLKAi3bQXZp/20YNEFwD/c87ILNqic2LS5poaSimnBOIgU6gKX81z3NFdLkyz\r\nNnvOUwRc22Z8EgUrgQQACgIDBDbYm4os7DRESOAfco+V2+lAvI9t687qd3++\r\nz+FTIGBEMWEHrp5qbQqDQr9sWyl3sSoFB/myDgyO1baD5SUw24ADAQgHwmEE\r\nGBMIAAkFAlzbZnwCGwwACgkQ1sa/Ry5GeQRkEQD+LG6fEloMaItQNk5rca2A\r\nfwAFlvz4zKzaU+WtftJbgskA/i2vlR/dEZGMGjH4X/Nfe/bvg58MruAPa+mH\r\nGj0YBs1U\r\n=W2LQ\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"
    },
    {
      type: "Ed25519VerificationKey2018",
      id: "did:example:456#Wer8LMAAQgUAmj78VhIVwVs3pmn7fPNLf_09_jPgQHk",
      controller: "did:example:456",
      publicKeyBase58: "J5QHWFQNREPBnmwCDXZgzy5FjvDGFkLEgWVoEociTfXz"
    }
  ],
  authentication: [
    "did:example:456#Wer8LMAAQgUAmj78VhIVwVs3pmn7fPNLf_09_jPgQHk"
  ],
  service: [],
  capabilityDelegation: [
    "did:example:456#Wer8LMAAQgUAmj78VhIVwVs3pmn7fPNLf_09_jPgQHk"
  ],
  capabilityInvocation: [
    "did:example:456#Wer8LMAAQgUAmj78VhIVwVs3pmn7fPNLf_09_jPgQHk"
  ],
  assertionMethod: [
    "did:example:456#Wer8LMAAQgUAmj78VhIVwVs3pmn7fPNLf_09_jPgQHk"
  ],
  keyAgreement: [
    {
      id: "did:example:456#zCHdZuV6kizwRtLTYKL4KF57vtbvxQdB5YxXZBLERvh6co",
      type: "X25519KeyAgreementKey2019",
      controller: "did:example:456",
      publicKeyBase58: "J8rC7uwXdC9TEQZrvZkGuxFbMf9T4UU44eG9V9dXarWb"
    }
  ],
  proof: {
    type: "Ed25519Signature2018",
    created: "2019-11-15T23:05:57Z",
    verificationMethod:
      "did:example:456#Wer8LMAAQgUAmj78VhIVwVs3pmn7fPNLf_09_jPgQHk",
    proofPurpose: "assertionMethod",
    jws:
      "eyJhbGciOiJFZERTQSIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..dd-RtJ7dVrcccN3JsGkZlQUoBOBBZ5mzyT3pHp02QWPLnZH9dN1y5dzPBvat9tLkkbkcFjO5nU1JNT41I3-9Aw"
  }
};

const data = {
  "@context": [
    "https://w3id.org/did/v1",
    {
      schema: "http://schema.org/",
      action: "schema:action"
    }
  ],
  action: "AuthenticateMe"
};

describe("ed25519", () => {
  it("sign verify", async () => {
    const signed = await jsigs.sign(data, {
      documentLoader: wrappedDocumentLoader({
        //args that are needed in the wrapper.. such as zcaps
      }),
      suite: new Ed25519Signature2018({
        verificationMethod: didDoc.publicKey[1].id,
        key: new Ed25519KeyPair({
          privateKeyBase58: keypair.privateKey,
          publicKeyBase58: keypair.publicKey
        })
      }),
      // purpose: new AssertionProofPurpose({ controller }),
      purpose: new AuthenticationProofPurpose({
        challenge: "abc",
        domain: "example.com"
      }),
      compactProof: false
    });

    // console.log(signed);

    const result = await jsigs.verify(signed, {
      documentLoader: wrappedDocumentLoader({
        //args that are needed in the wrapper.. such as zcaps
      }),
      suite: new Ed25519Signature2018({
        key: new Ed25519KeyPair(didDoc.publicKey[1])
      }),
      // purpose: new AssertionProofPurpose({ controller })
      purpose: new AuthenticationProofPurpose({
        controller: didDoc,
        challenge: "abc",
        domain: "example.com"
      })
    });
    expect(result.verified).toBe(true);
  });
});
nikosft commented 4 years ago

I wasn't able to run the example file in README. I created my own example for node. I just post the link here in case somebody is interested.

https://github.com/nikosft/linked-data-signature

OR13 commented 4 years ago

@nikosft https://github.com/nikosft/linked-data-signature/blob/master/sign.js#L69

when you pass the controller like this, the documentLoader will not be used to verify.

You should past a log of what is returned from verify, it will likely tell you exactly what the problem is, but if it will be very hard to understand if you are not familiar with JSON-LD.

another thing to try is to provide more properties to the key when it is added to the suite...

This example might help: https://github.com/decentralized-identity/EcdsaSecp256k1RecoverySignature2020/blob/master/src/__tests__/sanity.spec.js

If you do get a working example, please open a PR to update the README.

nikosft commented 4 years ago

I was not receiving any error. The result.verified was True. I modified the example and I put everything inside a DID document. I still receive no error and the output of verify is as expected.

https://github.com/nikosft/linked-data-signature/blob/master/sign.js

OR13 commented 4 years ago

@nikosft ahh sorry, i misinterpreted your comment. If you are willing to make a PR to update the readme with a passing example... that would be awesome!