Skip to content

Commit

Permalink
Change schema format from uri-encoded string to an object
Browse files Browse the repository at this point in the history
Signed-off-by: lovesh <lovesh.bond@gmail.com>
  • Loading branch information
lovesh committed Jun 29, 2024
1 parent 91eaf8b commit b4a4bf4
Show file tree
Hide file tree
Showing 81 changed files with 522 additions and 122 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@docknetwork/crypto-wasm-ts",
"version": "0.61.0",
"version": "0.62.0",
"description": "Typescript abstractions over Dock's Rust crypto library's WASM wrapper",
"homepage": "https://github.com/docknetwork/crypto-wasm-ts",
"main": "lib/index.js",
Expand Down
8 changes: 5 additions & 3 deletions src/anonymous-credentials/blinded-credential-builder.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CredentialBuilder } from './credential-builder';
import { CredentialBuilderCommon } from './credential-builder-common';
import { IBlindCredentialRequest } from './presentation-specification';
import {
Expand All @@ -16,9 +17,10 @@ import { BDDT16BlindMac, BDDT16MacParams, BDDT16MacSecretKey } from '../bddt16-m
* Used by the signer to create a blinded credential. The signer will know only the unblinded attributes
*/
export abstract class BlindedCredentialBuilder extends CredentialBuilderCommon {
// NOTE: Follows semver and must be updated accordingly when the logic of this class changes or the
// underlying crypto changes.
static VERSION = '0.3.0';
// NOTE: This should match `CredentialBuilder.VERSION` exactly else backward compatibility code won't always work.
// This is because `BlindedCredential.toCredential` outputs a `Credential` which should be same as the one output
// by `CredentialBuilder.sign`
static VERSION = CredentialBuilder.VERSION;

blindedCredReq: IBlindCredentialRequest;

Expand Down
2 changes: 1 addition & 1 deletion src/anonymous-credentials/credential-builder-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export abstract class CredentialBuilderCommon extends Versioned {
// Schema should be part of the credential signature to prevent the credential holder from convincing a verifier of a manipulated schema
const s = {
[CRYPTO_VERSION_STR]: this._version,
[SCHEMA_STR]: this.schema?.toJsonString(),
[SCHEMA_STR]: this.schema?.toJSON(),
[SUBJECT_STR]: this._subject
};
for (const [k, v] of this._topLevelFields.entries()) {
Expand Down
39 changes: 36 additions & 3 deletions src/anonymous-credentials/credential-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
BBS_PLUS_SIGNATURE_PARAMS_LABEL_BYTES,
BBS_SIGNATURE_PARAMS_LABEL_BYTES,
PS_SIGNATURE_PARAMS_LABEL_BYTES,
BDDT16_MAC_PARAMS_LABEL_BYTES
BDDT16_MAC_PARAMS_LABEL_BYTES, CRYPTO_VERSION_STR, SUBJECT_STR, STATUS_STR
} from './types-and-consts';
import { BBSCredential, BBSPlusCredential, BDDT16Credential, Credential, PSCredential } from './credential';
import { flatten } from 'flat';
Expand Down Expand Up @@ -44,7 +44,7 @@ export abstract class CredentialBuilder<
> extends CredentialBuilderCommon {
// NOTE: Follows semver and must be updated accordingly when the logic of this class changes or the
// underlying crypto changes.
static VERSION = '0.5.0';
static VERSION = '0.6.0';

_encodedAttributes?: { [key: string]: Uint8Array };
_sig?: Signature;
Expand Down Expand Up @@ -95,6 +95,39 @@ export abstract class CredentialBuilder<
);
}

/**
* When schema doesn't match the credential, create a new appropriate schema and update the credential. Returns the
* serialized credential. Legacy version. Used by SDK for some older credential versions
* @param signingOpts
*/
updateSchemaIfNeededLegacy(signingOpts?: Partial<ISigningOpts>): object {
const cred = {
[CRYPTO_VERSION_STR]: this._version,
[SCHEMA_STR]: this.schema?.toJsonString(),
[SUBJECT_STR]: this._subject
};
for (const [k, v] of this._topLevelFields.entries()) {
cred[k] = v;
}
if (this._credStatus !== undefined) {
cred[STATUS_STR] = this._credStatus;
}

this.applyDefaultProofMetadataIfNeeded(cred);
const schema = this.schema as CredentialSchema;
if (signingOpts && !CredentialBuilder.hasSameFieldsAsSchema(cred, schema)) {
if (signingOpts.requireSameFieldsAsSchema) {
throw new Error('Credential does not have the fields as schema');
} else {
// Generate new schema
this.schema = CredentialSchema.generateAppropriateSchema(cred, schema);
// @ts-ignore
cred[SCHEMA_STR] = this.schema?.toJsonString();
}
}
return cred;
}

/**
* When schema doesn't match the credential, create a new appropriate schema and update the credential. Returns the
* serialized credential
Expand All @@ -109,7 +142,7 @@ export abstract class CredentialBuilder<
} else {
// Generate new schema
this.schema = CredentialSchema.generateAppropriateSchema(cred, schema);
cred[SCHEMA_STR] = this.schema?.toJsonString();
cred[SCHEMA_STR] = this.schema?.toJSON();
}
}
return cred;
Expand Down
12 changes: 7 additions & 5 deletions src/anonymous-credentials/credential-common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import semver from 'semver/preload';
import { Versioned } from './versioned';
import { CredentialSchema } from './schema';
import { PROOF_STR } from './types-and-consts';
import { PROOF_STR, SCHEMA_STR, STATUS_STR, SUBJECT_STR } from './types-and-consts';
import b58 from 'bs58';
import { isEmptyObject } from '../util';

Expand Down Expand Up @@ -41,11 +42,12 @@ export abstract class CredentialCommon<Sig> extends Versioned {

toJSON(): object {
const j = {};
j['cryptoVersion'] = this._version;
j['credentialSchema'] = this.schema.toJsonString();
j['credentialSubject'] = this.subject;
const schema = semver.gte(this.version, '0.6.0') ? this.schema.toJSON() : this.schema.toJsonString();
j['cryptoVersion'] = this.version;
j[SCHEMA_STR] = schema;
j[SUBJECT_STR] = this.subject;
if (this.credentialStatus !== undefined) {
j['credentialStatus'] = this.credentialStatus;
j[STATUS_STR] = this.credentialStatus;
}
for (const [k, v] of this.topLevelFields.entries()) {
j[k] = v;
Expand Down
7 changes: 4 additions & 3 deletions src/anonymous-credentials/credential.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import semver from 'semver/preload';
import { CredentialSchema } from './schema';
import {
BBS_CRED_PROOF_TYPE,
Expand All @@ -20,7 +21,6 @@ import { BBSPublicKey, BBSSignature, BBSSignatureParams } from '../bbs';
import { PSPublicKey, PSSignature, PSSignatureParams } from '../ps';
import { BBSPlusPublicKeyG2, BBSPlusSignatureG1, BBSPlusSignatureParamsG1 } from '../bbs-plus';
import { CredentialCommon } from './credential-common';
import { BDDT16CredentialBuilder } from './credential-builder';
import {
BDDT16Mac,
BDDT16MacParams,
Expand All @@ -33,12 +33,13 @@ export abstract class Credential<PublicKey, Signature, SignatureParams> extends
abstract verify(publicKey: PublicKey, signatureParams?: SignatureParams): VerifyResult;

serializeForSigning(): object {
const schema = semver.gte(this.version, '0.6.0') ? this.schema?.toJSON() : this.schema?.toJsonString();
// Schema should be part of the credential signature to prevent the credential holder from convincing a verifier of a manipulated schema
const s = {
[CRYPTO_VERSION_STR]: this.version,
// Converting the schema to a JSON string rather than keeping it JSO object to avoid creating extra fields while
// Converting the schema to a JSON string rather than keeping it JSON object to avoid creating extra fields while
// signing which makes the implementation more expensive as one sig param is needed for each field.
[SCHEMA_STR]: this.schema?.toJsonString(),
[SCHEMA_STR]: schema,
[SUBJECT_STR]: this.subject
};
for (const [k, v] of this.topLevelFields.entries()) {
Expand Down
12 changes: 9 additions & 3 deletions src/anonymous-credentials/presentation-builder.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import semver from 'semver/preload';
import { KBUniversalMembershipWitness, KBUniversalNonMembershipWitness } from '../accumulator/kb-acccumulator-witness';
import { KBUniversalAccumulatorValue } from '../accumulator/kb-universal-accumulator';
import { Versioned } from './versioned';
Expand Down Expand Up @@ -39,7 +40,7 @@ import {
PublicKey,
REV_CHECK_STR,
REV_ID_STR,
RevocationStatusProtocol,
RevocationStatusProtocol, SCHEMA_FIELDS,
SCHEMA_STR,
SignatureParams,
STATUS_STR,
Expand Down Expand Up @@ -119,7 +120,7 @@ type Credential = BBSCredential | BBSPlusCredential | PSCredential | BDDT16Crede
export class PresentationBuilder extends Versioned {
// NOTE: Follows semver and must be updated accordingly when the logic of this class changes or the
// underlying crypto changes.
static VERSION = '0.7.0';
static VERSION = '0.8.0';

// This can specify the reason why the proof was created, or date of the proof, or self-attested attributes (as JSON string), etc
_context?: string;
Expand Down Expand Up @@ -539,7 +540,12 @@ export class PresentationBuilder extends Versioned {
// CredentialBuilder version, schema and 2 fields of revocation - registry id (denoting the accumulator) and the check
// type, i.e. "membership" or "non-membership" are always revealed.
revealedNames.add(CRYPTO_VERSION_STR);
revealedNames.add(SCHEMA_STR);
if (semver.gte(cred.version, '0.6.0')) {
SCHEMA_FIELDS.forEach((s) => revealedNames?.add(s));
} else {
revealedNames.add(SCHEMA_STR);
}

if (cred.credentialStatus !== undefined) {
if (
cred.credentialStatus[ID_STR] === undefined ||
Expand Down
4 changes: 2 additions & 2 deletions src/anonymous-credentials/presentation-specification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
REV_CHECK_STR,
TYPE_STR,
InequalityProtocol,
AccumulatorValueType
AccumulatorValueType, VERSION_STR, SCHEMA_DETAILS_STR
} from './types-and-consts';
import b58 from 'bs58';
import { CredentialSchema } from './schema';
Expand Down Expand Up @@ -92,7 +92,7 @@ export interface IPresentedAttributeInequality {
export interface IPresentedCredential {
sigType?: SignatureType;
version: string;
schema: string;
schema: string | {[ID_STR]: string, [TYPE_STR]: string, [VERSION_STR]: string, [SCHEMA_DETAILS_STR]: string};
// Attributes being revealed to the verifier
revealedAttributes: object;
// Credential status used for checking revocation
Expand Down
7 changes: 4 additions & 3 deletions src/anonymous-credentials/presentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ export class Presentation extends Versioned {

for (let credIndex = 0; credIndex < this.spec.credentials.length; credIndex++) {
const presentedCred = this.spec.credentials[credIndex];
const presentedCredSchema = CredentialSchema.fromJSON(JSON.parse(presentedCred.schema));
const credVersionGte6 = semver.gte(presentedCred.version, '0.6.0');
const presentedCredSchema = credVersionGte6 ? CredentialSchema.fromJSON(presentedCred.schema as object) : CredentialSchema.fromJSON(JSON.parse(presentedCred.schema as string));
const flattenedSchema = presentedCredSchema.flatten();
const numAttribs = flattenedSchema[0].length;

Expand Down Expand Up @@ -1202,7 +1203,7 @@ export class Presentation extends Versioned {
let blindCredentialRequest, blindedAttributeCiphertexts;
if (this.spec.blindCredentialRequest !== undefined) {
blindCredentialRequest = _.cloneDeep(this.spec.blindCredentialRequest) as object;
blindCredentialRequest.schema = this.spec.blindCredentialRequest.schema.toJsonString();
blindCredentialRequest.schema = this.spec.blindCredentialRequest.schema.toJSON();
blindCredentialRequest.commitment = b58.encode(this.spec.blindCredentialRequest.commitment);
if (this.blindedAttributeCiphertexts !== undefined) {
blindedAttributeCiphertexts = {};
Expand Down Expand Up @@ -1562,7 +1563,7 @@ export class Presentation extends Versioned {
if (!Object.values(BlindSignatureType).includes(req['sigType'])) {
throw new Error(`sigType should be one of ${BlindSignatureType} but was ${req['sigType']}`);
}
req['schema'] = CredentialSchema.fromJSON(JSON.parse(req['schema']));
req['schema'] = CredentialSchema.fromJSON(req['schema']);
req['commitment'] = b58.decode(req['commitment']);
if (blindedAttributeCiphertexts !== undefined) {
bac = {};
Expand Down
Loading

0 comments on commit b4a4bf4

Please sign in to comment.