iotaledger / integration-services

https://demo-integration-services.iota.cafe/
Apache License 2.0
30 stars 19 forks source link

Investigate create presentation alternative #677

Closed dominic22 closed 2 years ago

dominic22 commented 2 years ago

Please add result in comments.

Check if we really could:

JuriBog commented 2 years ago

For canonicalising a json object we can use this library which has no other dependencies and is licensed unter Apache 2.0: https://www.npmjs.com/package/canonicalize

import { IdentityClient } from './clients/identity';
import { ClientConfig } from './models';
import { ApiVersion } from './models/apiVersion';
import bs58 from 'bs58'
import * as ed from '@noble/ed25519'
import axios from 'axios'
import { Converter } from '@iota/util.js';

const sign = async (privateKey: string, data: string) => {
  const hexData = Converter.utf8ToHex(data)
  const signedHash = await ed.sign(hexData, privateKey);
  return ed.Signature.fromHex(signedHash).toHex();
}

const canonicalize = (object: any) => {
  let buffer = '';
  serialize(object);
  return buffer;

  function serialize(object: any) {
      if (object === null || typeof object !== 'object' ||
          object.toJSON != null) {

          buffer += JSON.stringify(object);

      } else if (Array.isArray(object)) {
          buffer += '[';
          let next = false;
          object.forEach((element) => {
              if (next) {
                  buffer += ',';
              }
              next = true;
              serialize(element);
          });
          buffer += ']';

      } else {
          buffer += '{';
          let next = false;
          Object.keys(object).sort().forEach((property) => {
              if (next) {
                  buffer += ',';
              }
              const val = object[property]
              if (val !== undefined) {
                  buffer += JSON.stringify(property);
                  buffer += ':';
                  serialize(object[property]);
                  next = true;
              }
          });
          buffer += '}';
      }
  }
};

async function signVp() {
  const config: ClientConfig = {
    isGatewayUrl: 'http://localhost:3000',
    apiKey: '1cfa3bce-654d-41f6-a82a-94308dc4adf8',
    apiVersionAuditTrail: ApiVersion.v0_1,
    apiVersionSsiBridge: ApiVersion.v0_2,
    useGatewayUrl: true
  };

  const vp = {
    '@context': 'https://www.w3.org/2018/credentials/v1',
    holder: 'did:iota:DJXVVypAnGn6KKXTMTXMGe4Vs7o3KYxiTCebmWsjVCq8',
    proof: {
      expires: '2022-09-07T18:17:07Z',
      type: 'JcsEd25519Signature2020',
      verificationMethod: 'did:iota:DJXVVypAnGn6KKXTMTXMGe4Vs7o3KYxiTCebmWsjVCq8#sign-0'
    },
    type: 'VerifiablePresentation',
    verifiableCredential: {
      '@context': 'https://www.w3.org/2018/credentials/v1',
      credentialStatus: {
        id: 'did:iota:4o34aESjqUm48bFHaiaND2FYj6qdC9C8Cppa8FnokbnK#signature-bitmap-0',
        revocationBitmapIndex: '1',
        type: 'RevocationBitmap2022'
      },
      credentialSubject: {
        '@context': 'https://schema.org/',
        fullName: 'Full Name Credential',
        id: 'did:iota:DJXVVypAnGn6KKXTMTXMGe4Vs7o3KYxiTCebmWsjVCq8',
        initiator: 'did:iota:DmTb4Wu9q3zngyj4qzabxpHitNVKwHtp87j6aWRpD5sa',
        type: 'Person'
      },
      id: 'did:iota:DJXVVypAnGn6KKXTMTXMGe4Vs7o3KYxiTCebmWsjVCq8',
      issuanceDate: '2022-09-07T10:07:22Z',
      issuer: 'did:iota:4o34aESjqUm48bFHaiaND2FYj6qdC9C8Cppa8FnokbnK',
      proof: {
        signatureValue: '4L4hM45eJ1RdTGn8wXSMGdrEy62Wm1MNTiVqq1Ag8dLoiG57teBjAeXAMZyGVAMTk6Tj8NrFjY2JzgQqWXqd1a1h',
        type: 'JcsEd25519Signature2020',
        verificationMethod: 'did:iota:4o34aESjqUm48bFHaiaND2FYj6qdC9C8Cppa8FnokbnK#sign-0'
      },
      type: [ 'VerifiableCredential', 'VerifiedIdentityCredential' ]
    }
  }
  const identityClient = new IdentityClient(config);

  const canonicalizedVp = canonicalize(vp)

  const decodedPrivateKey = identityClient.getHexEncodedKey('5gFmQ5KRTrmwUKyY3RnfkvB1B6BQjj3RobzjA8Bjvx8w')
  const signature = await sign(
    decodedPrivateKey,
    canonicalizedVp
  );

  const parsedVp = await JSON.parse(JSON.stringify(vp))
  parsedVp.proof.signatureValue = bs58.encode(Converter.hexToBytes(signature))

  const {data} = await axios.post('http://localhost:3002/api/v0.2/verification/check-presentation?api-key=1cfa3bce-654d-41f6-a82a-94308dc4adf8', parsedVp)

  console.log(data)
}

signVp()