Skip to content

Commit

Permalink
specify protocol version in getSupportedProfiles (#295)
Browse files Browse the repository at this point in the history
* specify protocol version in getSupportedProfiles
  • Loading branch information
volodymyr-basiuk authored Dec 23, 2024
1 parent 74069f7 commit e72b3d0
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 68 deletions.
45 changes: 18 additions & 27 deletions src/iden3comm/handlers/auth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MediaType, ProtocolVersion } from '../constants';
import { MediaType } from '../constants';
import { IProofService } from '../../proof/proof-service';
import { PROTOCOL_MESSAGE_TYPE } from '../constants';

Expand Down Expand Up @@ -489,35 +489,26 @@ export class AuthHandler
profile?: string[] | undefined
): MediaType {
let mediaType: MediaType;
if (profile?.length) {
const supportedMediaTypes: MediaType[] = [];
for (const acceptProfile of profile) {
// 1. check protocol version
const { protocolVersion, env } = parseAcceptProfile(acceptProfile);
const responseTypeVersion = Number(responseType.split('/').at(-2));
if (
protocolVersion !== ProtocolVersion.V1 ||
(protocolVersion === ProtocolVersion.V1 &&
(responseTypeVersion < 1 || responseTypeVersion >= 2))
) {
continue;
}
// 2. check packer support
if (this._packerMgr.isProfileSupported(env, acceptProfile)) {
supportedMediaTypes.push(env);
}
if (!profile?.length) {
return ctx.mediaType || MediaType.ZKPMessage;
}
const supportedMediaTypes: MediaType[] = [];
for (const acceptProfile of profile) {
const { env } = parseAcceptProfile(acceptProfile);
if (this._packerMgr.isProfileSupported(env, acceptProfile)) {
supportedMediaTypes.push(env);
}
}

if (!supportedMediaTypes.length) {
throw new Error('no packer with profile which meets `accept` header requirements');
}
if (!supportedMediaTypes.length) {
throw new Error('no packer with profile which meets `accept` header requirements');
}

mediaType = supportedMediaTypes[0];
if (ctx.mediaType && supportedMediaTypes.includes(ctx.mediaType)) {
mediaType = ctx.mediaType;
}
} else {
mediaType = ctx.mediaType || MediaType.ZKPMessage;
mediaType = supportedMediaTypes.includes(MediaType.ZKPMessage)
? MediaType.ZKPMessage
: supportedMediaTypes[0];
if (ctx.mediaType && supportedMediaTypes.includes(ctx.mediaType)) {
mediaType = ctx.mediaType;
}
return mediaType;
}
Expand Down
27 changes: 18 additions & 9 deletions src/iden3comm/packers/jws.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { BasicMessage, IPacker, JWSPackerParams } from '../types';
import { AcceptJwsAlgorithms, MediaType, SUPPORTED_PUBLIC_KEY_TYPES } from '../constants';
import {
AcceptJwsAlgorithms,
MediaType,
ProtocolVersion,
SUPPORTED_PUBLIC_KEY_TYPES
} from '../constants';
import { extractPublicKeyBytes, resolveVerificationMethods } from '../utils/did';
import { keyPath, KMS } from '../../kms/';

Expand All @@ -23,6 +28,9 @@ import { parseAcceptProfile } from '../utils';
* @implements implements IPacker interface
*/
export class JWSPacker implements IPacker {
private readonly supportedAlgorithms = [AcceptJwsAlgorithms.ES256K, AcceptJwsAlgorithms.ES256KR];
private readonly supportedProtocolVersions = [ProtocolVersion.V1];

/**
* Creates an instance of JWSPacker.
*
Expand Down Expand Up @@ -105,12 +113,18 @@ export class JWSPacker implements IPacker {

/** {@inheritDoc IPacker.getSupportedProfiles} */
getSupportedProfiles(): string[] {
return [`env=${this.mediaType()}&alg=${this.getSupportedAlgorithms().join(',')}`];
return this.supportedProtocolVersions.map(
(v) => `${v};env=${this.mediaType()};alg=${this.supportedAlgorithms.join(',')}`
);
}

/** {@inheritDoc IPacker.isProfileSupported} */
isProfileSupported(profile: string) {
const { env, circuits, alg } = parseAcceptProfile(profile);
const { protocolVersion, env, circuits, alg } = parseAcceptProfile(profile);

if (!this.supportedProtocolVersions.includes(protocolVersion)) {
return false;
}
if (env !== this.mediaType()) {
return false;
}
Expand All @@ -119,16 +133,11 @@ export class JWSPacker implements IPacker {
throw new Error(`Circuits are not supported for ${env} media type`);
}

const supportedAlgArr = this.getSupportedAlgorithms();
const algSupported =
!alg?.length || alg.some((a) => supportedAlgArr.includes(a as AcceptJwsAlgorithms));
!alg?.length || alg.some((a) => this.supportedAlgorithms.includes(a as AcceptJwsAlgorithms));
return algSupported;
}

private getSupportedAlgorithms(): AcceptJwsAlgorithms[] {
return [AcceptJwsAlgorithms.ES256K, AcceptJwsAlgorithms.ES256KR];
}

private async resolveDidDoc(from: string) {
let didDocument: DIDDocument;
try {
Expand Down
12 changes: 9 additions & 3 deletions src/iden3comm/packers/plain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BasicMessage, IPacker } from '../types';
import { MediaType } from '../constants';
import { MediaType, ProtocolVersion } from '../constants';
import { byteDecoder, byteEncoder } from '../../utils';
import { parseAcceptProfile } from '../utils';

Expand All @@ -11,6 +11,8 @@ import { parseAcceptProfile } from '../utils';
* @implements implements IPacker interface
*/
export class PlainPacker implements IPacker {
private readonly supportedProtocolVersions = [ProtocolVersion.V1];

/**
* Packs a basic message using the specified parameters.
*
Expand Down Expand Up @@ -57,12 +59,16 @@ export class PlainPacker implements IPacker {

/** {@inheritDoc IPacker.getSupportedProfiles} */
getSupportedProfiles(): string[] {
return [`env=${this.mediaType()}`];
return this.supportedProtocolVersions.map((v) => `${v};env=${this.mediaType()}`);
}

/** {@inheritDoc IPacker.isProfileSupported} */
isProfileSupported(profile: string) {
const { env, circuits, alg } = parseAcceptProfile(profile);
const { protocolVersion, env, circuits, alg } = parseAcceptProfile(profile);

if (!this.supportedProtocolVersions.includes(protocolVersion)) {
return false;
}
if (env !== this.mediaType()) {
return false;
}
Expand Down
36 changes: 19 additions & 17 deletions src/iden3comm/packers/zkp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
ErrStateVerificationFailed,
ErrUnknownCircuitID
} from '../errors';
import { AcceptAuthCircuits, AcceptJwzAlgorithms, MediaType } from '../constants';
import { AcceptAuthCircuits, AcceptJwzAlgorithms, MediaType, ProtocolVersion } from '../constants';
import { byteDecoder, byteEncoder } from '../../utils';
import { DEFAULT_AUTH_VERIFY_DELAY } from '../constants';
import { parseAcceptProfile } from '../utils';
Expand Down Expand Up @@ -86,6 +86,10 @@ export class VerificationHandlerFunc {
* @implements implements IPacker interface
*/
export class ZKPPacker implements IPacker {
private readonly supportedProtocolVersions = [ProtocolVersion.V1];
private readonly supportedAlgorithms = [AcceptJwzAlgorithms.Groth16];
private readonly supportedCircuitIds = [AcceptAuthCircuits.AuthV2];

/**
* Creates an instance of ZKPPacker.
* @param {Map<string, ProvingParams>} provingParamsMap - string is derived by JSON.parse(ProvingMethodAlg)
Expand Down Expand Up @@ -178,37 +182,35 @@ export class ZKPPacker implements IPacker {

/** {@inheritDoc IPacker.getSupportedProfiles} */
getSupportedProfiles(): string[] {
return [
`env=${this.mediaType()}&alg=${this.getSupportedAlgorithms().join(
','
)}&circuitIds=${this.getSupportedCircuitIds().join(',')}`
];
return this.supportedProtocolVersions.map(
(v) =>
`${v};env=${this.mediaType()};alg=${this.supportedAlgorithms.join(
','
)};circuitIds=${this.supportedCircuitIds.join(',')}`
);
}

/** {@inheritDoc IPacker.isProfileSupported} */
isProfileSupported(profile: string) {
const { env, circuits, alg } = parseAcceptProfile(profile);
const { protocolVersion, env, circuits, alg } = parseAcceptProfile(profile);

if (!this.supportedProtocolVersions.includes(protocolVersion)) {
return false;
}

if (env !== this.mediaType()) {
return false;
}

const supportedCircuitIds = this.getSupportedCircuitIds();
const supportedCircuitIds = this.supportedCircuitIds;
const circuitIdSupported =
!circuits?.length || circuits.some((c) => supportedCircuitIds.includes(c));

const supportedAlgArr = this.getSupportedAlgorithms();
const supportedAlgArr = this.supportedAlgorithms;
const algSupported =
!alg?.length || alg.some((a) => supportedAlgArr.includes(a as AcceptJwzAlgorithms));
return algSupported && circuitIdSupported;
}

private getSupportedAlgorithms(): AcceptJwzAlgorithms[] {
return [AcceptJwzAlgorithms.Groth16];
}

private getSupportedCircuitIds(): AcceptAuthCircuits[] {
return [AcceptAuthCircuits.AuthV2];
}
}

const verifySender = async (token: Token, msg: BasicMessage): Promise<void> => {
Expand Down
26 changes: 15 additions & 11 deletions tests/handlers/discover-protocol.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('discovery-protocol', () => {
expect(disclosures[0][DiscoverFeatureQueryType.FeatureType]).to.be.eq(
DiscoveryProtocolFeatureType.Accept
);
expect(disclosures[0].id).to.be.eq('env=application/iden3comm-plain-json');
expect(disclosures[0].id).to.be.eq('iden3comm/v1;env=application/iden3comm-plain-json');
});

it('jws and plain message accept disclosures', async () => {
Expand All @@ -72,8 +72,10 @@ describe('discovery-protocol', () => {
DiscoveryProtocolFeatureType.Accept
);
const disclosureIds = disclosures.map((d) => d.id);
expect(disclosureIds).to.include('env=application/iden3comm-plain-json');
expect(disclosureIds).to.include('env=application/iden3comm-signed-json&alg=ES256K,ES256K-R');
expect(disclosureIds).to.include('iden3comm/v1;env=application/iden3comm-plain-json');
expect(disclosureIds).to.include(
'iden3comm/v1;env=application/iden3comm-signed-json;alg=ES256K,ES256K-R'
);
});

it('zkp and plain message accept disclosures', async () => {
Expand All @@ -95,9 +97,9 @@ describe('discovery-protocol', () => {
DiscoveryProtocolFeatureType.Accept
);
const disclosureIds = disclosures.map((d) => d.id);
expect(disclosureIds).to.include('env=application/iden3comm-plain-json');
expect(disclosureIds).to.include('iden3comm/v1;env=application/iden3comm-plain-json');
expect(disclosureIds).to.include(
'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2'
'iden3comm/v1;env=application/iden3-zkp-json;alg=groth16;circuitIds=authV2'
);
});

Expand All @@ -123,11 +125,13 @@ describe('discovery-protocol', () => {
DiscoveryProtocolFeatureType.Accept
);
const disclosureIds = disclosures.map((d) => d.id);
expect(disclosureIds).to.include('env=application/iden3comm-plain-json');
expect(disclosureIds).to.include('iden3comm/v1;env=application/iden3comm-plain-json');
expect(disclosureIds).to.include(
'iden3comm/v1;env=application/iden3-zkp-json;alg=groth16;circuitIds=authV2'
);
expect(disclosureIds).to.include(
'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2'
'iden3comm/v1;env=application/iden3comm-signed-json;alg=ES256K,ES256K-R'
);
expect(disclosureIds).to.include('env=application/iden3comm-signed-json&alg=ES256K,ES256K-R');
});

it('zkp, jws and plain message accept disclosures with exact match', async () => {
Expand All @@ -140,7 +144,7 @@ describe('discovery-protocol', () => {
const acceptQueryMessageWithMatch = createDiscoveryFeatureQueryMessage([
{
[DiscoverFeatureQueryType.FeatureType]: DiscoveryProtocolFeatureType.Accept,
match: 'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2'
match: 'iden3comm/v1;env=application/iden3-zkp-json;alg=groth16;circuitIds=authV2'
}
]);

Expand All @@ -153,7 +157,7 @@ describe('discovery-protocol', () => {
DiscoveryProtocolFeatureType.Accept
);
expect(disclosures[0].id).to.include(
'env=application/iden3-zkp-json&alg=groth16&circuitIds=authV2'
'iden3comm/v1;env=application/iden3-zkp-json;alg=groth16;circuitIds=authV2'
);
});

Expand Down Expand Up @@ -306,7 +310,7 @@ describe('discovery-protocol', () => {
DiscoveryProtocolFeatureType.Protocol
);
const disclosureIds = disclosures.map((d) => d.id);
expect(disclosureIds).to.include('env=application/iden3comm-plain-json');
expect(disclosureIds).to.include('iden3comm/v1;env=application/iden3comm-plain-json');
expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE);
expect(disclosureIds).to.include(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_REQUEST_MESSAGE_TYPE);
});
Expand Down
6 changes: 6 additions & 0 deletions tests/iden3comm/jws.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { DIDResolutionResult } from 'did-resolver';
import { ES256KSigner } from 'did-jwt';
import { DID, getChainId, Id } from '@iden3/js-iden3-core';
import { Hex } from '@iden3/js-crypto';
import { MediaType } from '../../src/iden3comm/constants';

const didExample = {
'@context': [
Expand Down Expand Up @@ -217,4 +218,9 @@ describe('jws packer tests', () => {
const data = await packer.unpack(tokenBytes);
expect(data).to.not.be.undefined;
});

it('test getSupportedProfiles', () => {
const [accept] = packer.getSupportedProfiles();
expect(accept).to.be.eq(`iden3comm/v1;env=${MediaType.SignedMessage};alg=ES256K,ES256K-R`);
});
});
12 changes: 12 additions & 0 deletions tests/iden3comm/packageManager.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
DataPrepareHandlerFunc,
PackageManager,
PlainPacker,
VerificationHandlerFunc,
ZKPPacker
} from '../../src/iden3comm/index';
Expand Down Expand Up @@ -70,6 +71,17 @@ describe('tests packageManager with ZKP Packer', () => {
expect(senderDID.string()).to.deep.equal(unpackedMessage.from);
expect(byteDecoder.decode(msgBytes)).to.deep.equal(JSON.stringify(unpackedMessage));
});

it('test getSupportedProfiles', () => {
const pm = new PackageManager();
pm.registerPackers([new ZKPPacker(new Map(), new Map()), new PlainPacker()]);
const supportedProfiles = pm.getSupportedProfiles();
expect(supportedProfiles.length).to.be.eq(2);
expect(supportedProfiles).to.include(
`iden3comm/v1;env=${MediaType.ZKPMessage};alg=groth16;circuitIds=authV2`
);
expect(supportedProfiles).to.include(`iden3comm/v1;env=${MediaType.PlainMessage}`);
});
});

const createFetchCredentialMessage = (typ: MediaType, from: DID, to: DID) => {
Expand Down
10 changes: 9 additions & 1 deletion tests/iden3comm/zkp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DID } from '@iden3/js-iden3-core';
import { Token, ProvingMethodAlg } from '@iden3/js-jwz';
import { ZKPPackerParams } from '../../src/iden3comm/types';
import { AuthV2PubSignals } from '../../src/circuits';
import { PROTOCOL_MESSAGE_TYPE } from '../../src/iden3comm/constants';
import { MediaType, PROTOCOL_MESSAGE_TYPE } from '../../src/iden3comm/constants';
import { byteDecoder, byteEncoder } from '../../src';
import { expect } from 'chai';
import { initZKPPacker } from './mock/proving';
Expand Down Expand Up @@ -41,4 +41,12 @@ describe('zkp packer tests', () => {

expect(PROTOCOL_MESSAGE_TYPE.AUTHORIZATION_RESPONSE_MESSAGE_TYPE).to.deep.equal(iden3msg.type);
});

it('test getSupportedProfiles', async () => {
const p = await initZKPPacker();
const [accept] = p.getSupportedProfiles();
expect(accept).to.be.eq(
`iden3comm/v1;env=${MediaType.ZKPMessage};alg=groth16;circuitIds=authV2`
);
});
});

0 comments on commit e72b3d0

Please sign in to comment.