From e4e43ec78bc62354ddf1dad6038bb274c4a992da Mon Sep 17 00:00:00 2001 From: Michael Wallace Date: Mon, 1 Aug 2022 15:40:03 +1000 Subject: [PATCH] fix: test cleanup and improve verbosity & API - Cleanup HTML test, move out of main class file. - Improve verbosity of API & private members. - Add hex & base64 format support. --- src/main/javascript/crypto/parser-test.html | 87 ++++++++++++- src/main/javascript/crypto/src/bundle.ts | 5 +- src/main/javascript/crypto/src/main.spec.ts | 116 ++++++++++++----- .../crypto/src/util/SchemaGenerator.ts | 120 +++++------------- 4 files changed, 205 insertions(+), 123 deletions(-) diff --git a/src/main/javascript/crypto/parser-test.html b/src/main/javascript/crypto/parser-test.html index 204efe91..8b701564 100644 --- a/src/main/javascript/crypto/parser-test.html +++ b/src/main/javascript/crypto/parser-test.html @@ -7,8 +7,93 @@ - + \ No newline at end of file diff --git a/src/main/javascript/crypto/src/bundle.ts b/src/main/javascript/crypto/src/bundle.ts index 26a52a9b..86eead8c 100644 --- a/src/main/javascript/crypto/src/bundle.ts +++ b/src/main/javascript/crypto/src/bundle.ts @@ -2,11 +2,10 @@ import {Authenticator} from "./Authenticator"; import {Eip712AttestationRequest} from "./libs/Eip712AttestationRequest"; import {AttestationCrypto} from "./libs/AttestationCrypto"; import {IntegrationExample} from "./IntegrationExample"; -import {Meh, SchemaGenerator} from "./util/SchemaGenerator"; +import {SchemaGenerator} from "./util/SchemaGenerator"; (window as any).Authenticator = Authenticator; (window as any).Attest = Eip712AttestationRequest; (window as any).AttestationCrypto = AttestationCrypto; (window as any).IntegrationExample = IntegrationExample; -(window as any).SchemaGenerator = SchemaGenerator; -(window as any).Meh = Meh; \ No newline at end of file +(window as any).SchemaGenerator = SchemaGenerator; \ No newline at end of file diff --git a/src/main/javascript/crypto/src/main.spec.ts b/src/main/javascript/crypto/src/main.spec.ts index b3b3ab7d..2790e206 100644 --- a/src/main/javascript/crypto/src/main.spec.ts +++ b/src/main/javascript/crypto/src/main.spec.ts @@ -31,15 +31,8 @@ import {Issuer} from "./libs/Issuer"; import { AttestedObject } from './libs/AttestedObject'; import { AttestableObject } from './libs/AttestableObject'; import { UseToken } from './asn1/shemas/UseToken'; -import subtle from "./safe-connect/SubtleCryptoShim"; -import {EthereumAddressAttestation} from "./safe-connect/EthereumAddressAttestation"; -import {EthereumKeyLinkingAttestation} from "./safe-connect/EthereumKeyLinkingAttestation"; import {SchemaGenerator} from "./util/SchemaGenerator"; import {DevconTicket, SignedDevconTicket} from "./asn1/shemas/SignedDevconTicket"; -import * as util from "util"; -import * as asn1_schema_1 from "@peculiar/asn1-schema"; -import {AsnParser, AsnPropTypes, AsnSerializer} from "@peculiar/asn1-schema"; -import {utils} from "ethers"; const url = require('url'); let EC = require("elliptic"); @@ -689,33 +682,94 @@ describe("Schema Generator", function(){ test("Serialize & parse ASN based on a dynamic schema", async function(){ - let schemaGenerator = new SchemaGenerator(); - - let GeneratedSchema = schemaGenerator.getSchemaObject(); - - console.log(util.inspect(GeneratedSchema)); - - let currentSchema = new GeneratedSchema(); - - currentSchema.ticket.devconId = "6"; - currentSchema.ticket.ticketIdNumber = 10; - currentSchema.ticket.ticketClass = 1; - - currentSchema.ticket.linkedTicket.devconId = "6"; - currentSchema.ticket.linkedTicket.ticketIdNumber = 10; - currentSchema.ticket.linkedTicket.ticketClass = 1; - - currentSchema.signatureValue = new Uint8Array(hexStringToUint8("0xb135ded73c021184158fa6ea91eff0a97753f27163f3b35a57d3fac57146bf0a45795224fefb95edde7dd55a1554829b5be20f3e39b1fb27a52bd63972d1e89c1c")); - - console.log(currentSchema); - - let encoded = AsnSerializer.serialize(currentSchema); + let generatedSchema = new SchemaGenerator({ + ticket: { + name: "Ticket", + items: { + devconId: { + type: "Utf8String", + optional: false + }, + ticketIdNumber: { + type: "Integer", + optional: true + }, + ticketIdString: { + type: "Utf8String", + optional: true + }, + ticketClass: { + type: "Integer", + optional: false + }, + linkedTicket: { + name: "Linked Ticket", + items: { + devconId: { + type: "Utf8String", + optional: false + }, + ticketIdNumber: { + type: "Integer", + optional: true + }, + ticketIdString: { + type: "Utf8String", + optional: true + }, + ticketClass: { + type: "Integer", + optional: false + } + } + } + } + }, + commitment: { + type: "OctetString", + optional: true + }, + signatureValue: { + type: "BitString", + optional: false + } + }); + + let asnObject = generatedSchema.getSchemaObject(); + + asnObject.ticket.devconId = "6"; + asnObject.ticket.ticketIdNumber = 5; + asnObject.ticket.ticketClass = 1; + + asnObject.ticket.linkedTicket.devconId = "6"; + asnObject.ticket.linkedTicket.ticketIdNumber = 10; + asnObject.ticket.linkedTicket.ticketClass = 2; + + asnObject.signatureValue = new Uint8Array(hexStringToUint8("0xb135ded73c021184158fa6ea91eff0a97753f27163f3b35a57d3fac57146bf0a45795224fefb95edde7dd55a1554829b5be20f3e39b1fb27a52bd63972d1e89c1c")); + + console.log(asnObject); + + let encoded = generatedSchema.serializeAndFormat(asnObject); + + console.log("Encoded: "); + console.log(encoded); + + let decoded = generatedSchema.parse(encoded); + + console.log("Decoded: "); + console.log(decoded); - console.log(uint8tohex(new Uint8Array(encoded))); + // Can't do a single match here because nested properties are set in the prototype + expect(asnObject.ticket.devconId).toBe("6"); + expect(asnObject.ticket.ticketIdNumber).toBe(5); + expect(asnObject.ticket.ticketClass).toBe(1); - let decoded = AsnParser.parse(encoded, GeneratedSchema); + expect(asnObject.ticket.linkedTicket.devconId).toBe("6"); + expect(asnObject.ticket.linkedTicket.ticketIdNumber).toBe(10); + expect(asnObject.ticket.linkedTicket.ticketClass).toBe(2); - console.log(decoded); + decoded.signatureValue = new Uint8Array(decoded.signatureValue); + expect(asnObject.signatureValue).toEqual(decoded.signatureValue); }); }); diff --git a/src/main/javascript/crypto/src/util/SchemaGenerator.ts b/src/main/javascript/crypto/src/util/SchemaGenerator.ts index 659fb437..90a29bc4 100644 --- a/src/main/javascript/crypto/src/util/SchemaGenerator.ts +++ b/src/main/javascript/crypto/src/util/SchemaGenerator.ts @@ -1,6 +1,6 @@ import * as asn1_schema_1 from "@peculiar/asn1-schema"; import {AsnParser, AsnPropTypes, AsnSerializer} from "@peculiar/asn1-schema"; -import {hexStringToUint8, uint8tohex} from "../libs/utils"; +import {base64ToUint8array, hexStringToUint8, uint8arrayToBase64, uint8tohex} from "../libs/utils"; import {AsnItemType, AsnRepeatType, IAsn1PropOptions} from "@peculiar/asn1-schema/build/types/decorators"; import {IAsnConverter} from "@peculiar/asn1-schema/build/types/types"; @@ -20,11 +20,13 @@ interface SchemaItemInterface { repeated?: AsnRepeatType; } +export declare type EncodingType = "hex" | "base64"; + export class SchemaGenerator { jsonSchema: any; - schemaObject: any; + generatedSchema: any; private static __decorate = function (decorators: any, target: any, key: any, desc: any) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; @@ -34,61 +36,10 @@ export class SchemaGenerator { return c > 3 && r && Object.defineProperty(target, key, r), r; }; - constructor(jsonSchema: SchemaDefinitionInterface = { - ticket: { - name: "Ticket", - items: { - devconId: { - type: "Utf8String", - optional: false - }, - ticketIdNumber: { - type: "Integer", - optional: true - }, - ticketIdString: { - type: "Utf8String", - optional: true - }, - ticketClass: { - type: "Integer", - optional: false - }, - linkedTicket: { - name: "Linked Ticket", - items: { - devconId: { - type: "Utf8String", - optional: false - }, - ticketIdNumber: { - type: "Integer", - optional: true - }, - ticketIdString: { - type: "Utf8String", - optional: true - }, - ticketClass: { - type: "Integer", - optional: false - } - } - } - } - }, - commitment: { - type: AsnPropTypes.OctetString, - optional: true - }, - signatureValue: { - type: AsnPropTypes.BitString, - optional: false - } - }) { + constructor(jsonSchema: SchemaDefinitionInterface) { this.jsonSchema = jsonSchema; - this.schemaObject = this.generateSchema(); + this.generatedSchema = this.generateSchema(); } private generateSchema(): any { @@ -100,8 +51,7 @@ export class SchemaGenerator { if (this.jsonSchema[i].items){ let childSchemaGenerator: any = new SchemaGenerator(this.jsonSchema[i].items); - let childSchema = childSchemaGenerator.getSchemaObject(); - + let childSchema = childSchemaGenerator.getSchemaType(); Schema.prototype[i] = new childSchema(); SchemaGenerator.__decorate([ @@ -145,45 +95,39 @@ export class SchemaGenerator { return decoratorOptions; } - getSchemaObject(){ - return this.schemaObject; + getSchemaType(){ + return this.generatedSchema; } + getSchemaObject(){ + return new this.generatedSchema(); + } -} - -export class Meh { - - meh() { - - let schemaGenerator = new SchemaGenerator(); - - let GeneratedSchema = schemaGenerator.getSchemaObject(); - - console.log("The full schema object"); - console.log(GeneratedSchema); - - let currentSchema = new GeneratedSchema(); - - currentSchema.ticket.devconId = "6"; - currentSchema.ticket.ticketIdNumber = 10; - currentSchema.ticket.ticketClass = 1; - - currentSchema.ticket.linkedTicket.devconId = "6"; - currentSchema.ticket.linkedTicket.ticketIdNumber = 10; - currentSchema.ticket.linkedTicket.ticketClass = 1; + serialize(object: Object): Uint8Array { + return new Uint8Array(AsnSerializer.serialize(object)); + } - currentSchema.signatureValue = new Uint8Array(hexStringToUint8("0xb135ded73c021184158fa6ea91eff0a97753f27163f3b35a57d3fac57146bf0a45795224fefb95edde7dd55a1554829b5be20f3e39b1fb27a52bd63972d1e89c1c")); + serializeAndFormat(object: Object, encoding: EncodingType = "hex"){ - console.log("Populated schema object"); - console.log(currentSchema); + let uint = this.serialize(object); - let encoded = AsnSerializer.serialize(currentSchema); + if (encoding === "hex"){ + return uint8tohex(uint); + } else { + return uint8arrayToBase64(uint); + } + } - console.log(uint8tohex(new Uint8Array(encoded))); + parse(data: Uint8Array|string, encoding: EncodingType = "hex"): any { - let decoded = AsnParser.parse(encoded, GeneratedSchema); + if (!(data instanceof Uint8Array)){ + if (encoding === "hex"){ + data = hexStringToUint8(data); + } else { + data = base64ToUint8array(data); + } + } - console.log(decoded); + return AsnParser.parse(data, this.generatedSchema); } } \ No newline at end of file