Skip to content

Commit

Permalink
fix: wip testing
Browse files Browse the repository at this point in the history
  • Loading branch information
elribonazo committed May 7, 2024
1 parent 78b6100 commit 442bba4
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 17 deletions.
12 changes: 10 additions & 2 deletions src/domain/models/VerifiableCredential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,14 @@ export interface JWTRevocationStatus extends W3CVerifiableCredentialData {
statusListCredential: string
}

export enum JWTProofType {
DataIntegrityProof = 'DataIntegrityProof'
}

export enum JWTProofPurpose {
ProofPurpose = 'assertionMethod'
}

export interface JWTStatusListResponse {
"@context": [
W3CVerifiableCredentialContext.credential,
Expand All @@ -218,8 +226,8 @@ export interface JWTStatusListResponse {
encodedList: string
},
proof: {
type: string,
proofPurpose: string,
type: JWTProofType,
proofPurpose: JWTProofPurpose,
verificationMethod: string,
created: string,
proofValue: string,
Expand Down
18 changes: 18 additions & 0 deletions src/domain/models/errors/Pollux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,24 @@ export class CredentialRevocationTypeInvalid extends Error {
}
}

export class InvalidCredentialStatus extends Error {
constructor(message?: string) {
super(message || "CredentialStatus status is invalid");
}
}

export class InvalidRevocationStatusResponse extends Error {
constructor(message?: string) {
super(message || "CredentialStatus response is invalid");
}
}

export class InvalidRevocationStatusResponseSignature extends Error {
constructor(message?: string) {
super(message || "CredentialStatus response proof signatue mismatch or invalid.");
}
}

export class CredentialTypeNotSupported extends Error {
constructor(message?: string) {
super(message || "Credential type not supported");
Expand Down
53 changes: 41 additions & 12 deletions src/pollux/Pollux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { uuid } from "@stablelib/uuid";

import { Castor } from "../domain/buildingBlocks/Castor";
import { Pollux as IPollux } from "../domain/buildingBlocks/Pollux";
import { base64 } from "multiformats/bases/base64";
import { base64, base64url } from "multiformats/bases/base64";
import { AnoncredsLoader } from "./AnoncredsLoader";
import pako from 'pako';

Expand Down Expand Up @@ -47,6 +47,7 @@ import { DescriptorPath } from "./utils/DescriptorPath";
import { JWT } from "./utils/JWT";
import { InvalidVerifyCredentialError, InvalidVerifyFormatError } from "../domain/models/errors/Pollux";
import { HttpStatusCode } from "axios";
import { base58btc } from "multiformats/bases/base58";

/**
* Implementation of Pollux
Expand All @@ -64,20 +65,46 @@ export default class Pollux implements IPollux {
private jwt = new JWT(castor)
) { }

extractVerificationStatus(credentialStatus: any): credentialStatus is JWTRevocationStatus {
const type = credentialStatus.type;
if (typeof type === "string" && credentialStatus.type === RevocationType.StatusList2021Entry) {
return true;
private extractVerificationStatus(credentialStatus: any): credentialStatus is JWTRevocationStatus {
try {
const type = credentialStatus.type;
if (typeof type === "string" && credentialStatus.type === RevocationType.StatusList2021Entry) {
return true;
}
return false;
} catch (err) {
throw new PolluxError.InvalidCredentialStatus()
}
return false;
}

extractEncodedList(body: JWTStatusListResponse): Uint8Array {
const encodedList = Buffer.from(body.credentialSubject.encodedList, 'base64');
return pako.ungzip(encodedList);
private extractEncodedList(body: JWTStatusListResponse): Uint8Array {
try {
const encodedList = Buffer.from(body.credentialSubject.encodedList, 'base64');
return pako.ungzip(encodedList);
} catch (err) {
throw new PolluxError.InvalidRevocationStatusResponse()
}
}

private async verifyRevocationProof(proof: JWTStatusListResponse['proof']): Promise<boolean> {
const verificationMethod = proof.verificationMethod;
const base64VerificationMethod = verificationMethod.split(",").at(1);
if (!base64VerificationMethod) {
throw new PolluxError.InvalidRevocationStatusResponse(`CredentialStatus proof invalid verificationMethod`);
}
const decodedVerificationMethod = JSON.parse(Buffer.from(base64.baseDecode(base64VerificationMethod)).toString());
const multibaseKey = decodedVerificationMethod.publicKeyMultibase;
try {
const decodedKey = base64url.decode(multibaseKey)
return true
} catch (err) {
throw new PolluxError.InvalidRevocationStatusResponse(`CredentialStatus proof invalid public key multibase base64Url`);

}
}

async isCredentialRevoked(credential: Credential): Promise<boolean> {

if (credential instanceof JWTCredential) {
if (!this.extractVerificationStatus(credential.credentialStatus)) {
throw new PolluxError.CredentialRevocationTypeInvalid()
Expand All @@ -91,10 +118,12 @@ export default class Pollux implements IPollux {
null
)
if (response.httpStatus !== HttpStatusCode.Ok) {
throw new PolluxError.CredentialRevocationTypeInvalid()
throw new PolluxError.InvalidRevocationStatusResponse(`CredentialStatus response status code ${response.httpStatus}`)
}
const list = this.extractEncodedList(response.body);
if (list[revocationStatus.statusListIndex] === 1) {
if (
(await this.verifyRevocationProof(response.body.proof)) &&
this.extractEncodedList(response.body)[revocationStatus.statusListIndex] === 1
) {
return true;
}
return false
Expand Down
61 changes: 58 additions & 3 deletions tests/pollux/Pollux.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as sinon from "sinon";
import SinonChai from "sinon-chai";
import { expect, assert } from "chai";

import { AttachmentDescriptor, Claims, CredentialRequestOptions, CredentialType, Curve, DID, JWTCredentialPayload, JWTPresentationPayload, JWTVerifiableCredentialProperties, KeyTypes, LinkSecret, Message, PolluxError, PresentationOptions, PrivateKey, W3CVerifiableCredentialContext, W3CVerifiableCredentialType } from "../../src/domain";
import { AttachmentDescriptor, Claims, CredentialRequestOptions, CredentialType, Curve, DID, JWTCredentialPayload, JWTPresentationPayload, JWTRevocationStatus, JWTRevocationStatusPurpose, JWTVerifiableCredentialProperties, KeyTypes, LinkSecret, Message, PolluxError, PresentationOptions, PrivateKey, RevocationType, W3CVerifiableCredentialContext, W3CVerifiableCredentialType, Credential, AttachmentFormats } from "../../src/domain";
import { JWTCredential } from "../../src/pollux/models/JWTVerifiableCredential";
import Castor from "../../src/castor/Castor";
import { Apollo } from "../../src/domain/buildingBlocks/Apollo";
Expand All @@ -15,11 +15,15 @@ import { AnonCredsCredential, AnonCredsRecoveryId } from "../../src/pollux/model
import { PresentationRequest } from "../../src/pollux/models/PresentationRequest";
import * as Fixtures from "../fixtures";
import { JWT } from "../../src/pollux/utils/JWT";
import axios from "axios";

chai.use(SinonChai);
chai.use(chaiAsPromised);
let sandbox: sinon.SinonSandbox;

jest.mock("axios");


jest.mock("../../src/pollux/utils/JWT", () => ({
JWT: jest.fn(() => ({
sign: jest.fn(() => "JWT.sign.result"),
Expand Down Expand Up @@ -738,7 +742,7 @@ describe("Pollux", () => {
sandbox.stub(pollux as any, "fetchSchema").resolves(Fixtures.Credentials.Anoncreds.schema);
sandbox.stub(pollux as any, "fetchCredentialDefinition").resolves(Fixtures.Credentials.Anoncreds.credentialDefinition);

const pr = new PresentationRequest(CredentialType.AnonCreds, Fixtures.Credentials.Anoncreds.presentationRequest);
const pr = new PresentationRequest(AttachmentFormats.AnonCreds, Fixtures.Credentials.Anoncreds.presentationRequest);
const cred = new AnonCredsCredential(Fixtures.Credentials.Anoncreds.credential);

const result = await pollux.createPresentationProof(pr, cred, { linkSecret: Fixtures.Credentials.Anoncreds.linkSecret });
Expand All @@ -750,7 +754,7 @@ describe("Pollux", () => {
describe("JWT", () => {
test("ok", async () => {

const pr = new PresentationRequest(CredentialType.JWT, Fixtures.Credentials.JWT.presentationRequest);
const pr = new PresentationRequest(AttachmentFormats.JWT, Fixtures.Credentials.JWT.presentationRequest);
const cred = JWTCredential.fromJWS(Fixtures.Credentials.JWT.credentialPayloadEncoded);
const did = Fixtures.DIDs.peerDID1;
const privateKey = Fixtures.Keys.secp256K1.privateKey;
Expand Down Expand Up @@ -1868,6 +1872,57 @@ describe("Pollux", () => {
expect(pollux.verifyPresentationSubmission(presentationSubmissionJSON, {
presentationDefinitionRequest: presentationDefinition
})).to.eventually.equal(true)
})

it("Should correctly determine that a Credential is revoked when calling the credentialStatus list endpoints", async () => {
const revocableJWTCredential = `eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6cHJpc206YmM5ZGFhZWFmMGFkNjczZjVkNTViM2I2NjEyYTE2NTNiYzcyYWMxNjU5Y2VmYTgxYzZlZWY0NWMxZjcyMTYzOTpDcmtCQ3JZQkVqb0tCbUYxZEdndE1SQUVTaTRLQ1hObFkzQXlOVFpyTVJJaEFqRDNnM3ctcHNnRXZQcUJxUDJmVjhPQXAwQ0l3WjVYU3FhMU9OWU1HOGRQRWpzS0IybHpjM1ZsTFRFUUFrb3VDZ2x6WldOd01qVTJhekVTSVFQRGNPbm9BV25YODBhZnA2aVVEZUl6ZUViMXMySFVPUEo5TEpRRTd1RzdYeEk3Q2dkdFlYTjBaWEl3RUFGS0xnb0pjMlZqY0RJMU5tc3hFaUVDc3luYTRsbkw3anhfSnctTXUtUjd3UUppSnhCNGpnMWUwODN1Q252amNhSSIsInN1YiI6ImRpZDpwcmlzbTozZjBiNDQ5NjI3NmI3NGEzMTU3ZmRiOTEwODU5MDExYjhjZWQwNjU1ZGYyNWU3ZjgwNTAyZjE0OGU2NmM1NGU4OkN0OEJDdHdCRW5RS0gyRjFkR2hsYm5ScFkyRjBhVzl1WVhWMGFHVnVkR2xqWVhScGIyNUxaWGtRQkVKUENnbHpaV053TWpVMmF6RVNJS0ZpZjRlcnNMOFF2SFF2VmxXUEFNaHFPNmwzbXZSbUp5ZlRFRTYzZzI2MEdpRG9PNS1KRzR3Z1JkZk1LcXlqZnp2ek9sSXRsNDNsdDQ0Z21TMWxtaFpKZUJKa0NnOXRZWE4wWlhKdFlYTjBaWEpMWlhrUUFVSlBDZ2x6WldOd01qVTJhekVTSUtGaWY0ZXJzTDhRdkhRdlZsV1BBTWhxTzZsM212Um1KeWZURUU2M2cyNjBHaURvTzUtSkc0d2dSZGZNS3F5amZ6dnpPbEl0bDQzbHQ0NGdtUzFsbWhaSmVBIiwibmJmIjoxNzE1MDA2OTY4LCJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6eyJlbWFpbEFkZHJlc3MiOiJjb3Jwb3JhdGVAZG9tYWluLmNvbSIsImRyaXZpbmdDbGFzcyI6MSwiZHJpdmluZ0xpY2Vuc2VJRCI6IkVTLTEyMzQ1Njc4OTAiLCJpZCI6ImRpZDpwcmlzbTozZjBiNDQ5NjI3NmI3NGEzMTU3ZmRiOTEwODU5MDExYjhjZWQwNjU1ZGYyNWU3ZjgwNTAyZjE0OGU2NmM1NGU4OkN0OEJDdHdCRW5RS0gyRjFkR2hsYm5ScFkyRjBhVzl1WVhWMGFHVnVkR2xqWVhScGIyNUxaWGtRQkVKUENnbHpaV053TWpVMmF6RVNJS0ZpZjRlcnNMOFF2SFF2VmxXUEFNaHFPNmwzbXZSbUp5ZlRFRTYzZzI2MEdpRG9PNS1KRzR3Z1JkZk1LcXlqZnp2ek9sSXRsNDNsdDQ0Z21TMWxtaFpKZUJKa0NnOXRZWE4wWlhKdFlYTjBaWEpMWlhrUUFVSlBDZ2x6WldOd01qVTJhekVTSUtGaWY0ZXJzTDhRdkhRdlZsV1BBTWhxTzZsM212Um1KeWZURUU2M2cyNjBHaURvTzUtSkc0d2dSZGZNS3F5amZ6dnpPbEl0bDQzbHQ0NGdtUzFsbWhaSmVBIiwiZGF0ZU9mSXNzdWFuY2UiOiIyMDIzLTAxLTAxVDAyOjAyOjAyWiJ9LCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIl0sIkBjb250ZXh0IjpbImh0dHBzOlwvXC93d3cudzMub3JnXC8yMDE4XC9jcmVkZW50aWFsc1wvdjEiXSwiY3JlZGVudGlhbFN0YXR1cyI6eyJzdGF0dXNQdXJwb3NlIjoiUmV2b2NhdGlvbiIsInN0YXR1c0xpc3RJbmRleCI6MSwiaWQiOiJodHRwOlwvXC8xOTIuMTY4LjE1NC4yMDU6ODAwMFwvcHJpc20tYWdlbnRcL2NyZWRlbnRpYWwtc3RhdHVzXC8xYzE1Yjk2My1kYzRkLTQ3NjUtYjc1Mi01M2EzZmQxZjE4MzMjMSIsInR5cGUiOiJTdGF0dXNMaXN0MjAyMUVudHJ5Iiwic3RhdHVzTGlzdENyZWRlbnRpYWwiOiJodHRwOlwvXC8xOTIuMTY4LjE1NC4yMDU6ODAwMFwvcHJpc20tYWdlbnRcL2NyZWRlbnRpYWwtc3RhdHVzXC8xYzE1Yjk2My1kYzRkLTQ3NjUtYjc1Mi01M2EzZmQxZjE4MzMifX19.NxuJoiEgSnGs7suM5cxDq3tZ6ZYVDAscnKBuAXghW0KD9MhSr1vBUo9F6y0YkjhHBY4Y_gTGnIMBwgLYjcNVKw`;



(axios.request as any).mockResolvedValue({
data: {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://w3id.org/vc/status-list/2021/v1"
],
"type": [
"VerifiableCredential",
"StatusList2021Credential"
],
"issuer": "did:prism:195e1bb3b7bd885afbc717e8248f49ddeaf363cb164f744b5ff44b71d88d3c4f",
"id": "http://192.168.1.44:8000/prism-agent/credential-status/eb1e5358-90a8-4891-bc14-b25598efcb3f",
"issuanceDate": 1714044272,
"credentialSubject": {
"id": "",
"type": "StatusList2021",
"statusPurpose": "Revocation",
"encodedList": "H4sIAAAAAAAA_-3BMQEAAADCoPVPbQwfoAAAAAAAAAAAAAAAAAAAAIC3AYbSVKsAQAAA"
},
"proof": {
"type": "DataIntegrityProof",
"proofPurpose": "assertionMethod",
"verificationMethod": "data:application/json;base64,eyJAY29udGV4dCI6WyJodHRwczovL3czaWQub3JnL3NlY3VyaXR5L211bHRpa2V5L3YxIl0sInR5cGUiOiJNdWx0aWtleSIsInB1YmxpY0tleU11bHRpYmFzZSI6InVNRll3RUFZSEtvWkl6ajBDQVFZRks0RUVBQW9EUWdBRXJhU2JoT08yZUs4WnNGS3FnQjU3bGpfdndobDJHMG1ScXMyb1lQa2xSNHhycG5VT1JRVm83RVdMNE5fR01IZEhUcEJmNVgwcThocUZnaFRUVUc2eTRRPT0ifQ==",
"created": "2024-04-25T11:24:32.206466379Z",
"proofValue": "z381yXYoaicLEPfb1XmvcsabdNgUSQe1dvGKxa1PaexcdbEmUtzRKsD4VmQH3GtBH2D99TTDgZFnCu3yznXVFrXaMN83wqRgx",
"cryptoSuite": "eddsa-jcs-2022"
}
}, status: 200
});


const credential = JWTCredential.fromJWS(revocableJWTCredential)
const revoked = await pollux.isCredentialRevoked(credential)
debugger;






})
})




});

0 comments on commit 442bba4

Please sign in to comment.