Skip to content

Commit

Permalink
Merge pull request #116 from TrustNXT/bugfix/chain-certificate-algori…
Browse files Browse the repository at this point in the history
…thms

Don't check signature algorithm allow list in chain certificates
  • Loading branch information
cyraxx authored Sep 25, 2024
2 parents ce245e5 + dfe157b commit b5f2854
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/quiet-snails-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@trustnxt/c2pa-ts': patch
---

Don't check signature algorithm allow list for chain certificates
2 changes: 2 additions & 0 deletions src/asset/BMFF.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export class BMFF extends BaseAsset implements Asset {
}
if (this.mustBePrecededByFtyp.has(box.type)) return false;
}

return false;
} catch {
return false;
}
Expand Down
5 changes: 5 additions & 0 deletions src/asset/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,8 @@ export interface Asset {
*/
writeManifestJUMBF(jumbf: Uint8Array): Promise<void>;
}

export interface AssetType {
new (data: Uint8Array): Asset;
canRead(data: Uint8Array): boolean;
}
8 changes: 5 additions & 3 deletions src/cose/Signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,11 @@ export class Signature {
const keyUsageError = this.validateCertificateKeyUsage(certificate, isUsedForManifestSigning);
if (keyUsageError) return keyUsageError;

// Check for allowed signature algorithm
const algorithmError = this.validateCertificateAlgorithm(certificate);
if (algorithmError) return algorithmError;
if (isUsedForManifestSigning) {
// Check for allowed signature algorithm
const algorithmError = this.validateCertificateAlgorithm(certificate);
if (algorithmError) return algorithmError;
}

// Check timestamp
if (certificate.notBefore >= validityTimestamp || certificate.notAfter <= validityTimestamp)
Expand Down
132 changes: 88 additions & 44 deletions tests/jpeg-processing.test.ts → tests/asset-reading.test.ts
Original file line number Diff line number Diff line change
@@ -1,159 +1,203 @@
import assert from 'node:assert/strict';
import * as fs from 'node:fs/promises';
import { Asset, JPEG } from '../src/asset';
import { Asset, AssetType, BMFF, JPEG, PNG } from '../src/asset';
import { SuperBox } from '../src/jumbf';
import { ManifestStore, ValidationResult, ValidationStatusCode } from '../src/manifest';
import { BinaryHelper } from '../src/util';

// location of the JPEG images within the checked out test files repo
const baseDir = 'tests/fixtures/public-testfiles/image/jpeg';
const baseDir = 'tests/fixtures';

interface TestExpectations {
/**
* Asset class to read the file
*/
assetType: AssetType;

class TestExpectations {
/**
* whether the file contains a JUMBF with a C2PA Manifest
*/
jumbf = false;
jumbf: boolean;

/**
* whether the file is valid according to the C2PA Manifest
*/
valid: boolean | undefined = undefined;
valid?: boolean;

/**
* status codes expected in the status entries
*/
statusCodes: ValidationStatusCode[] = [];
statusCodes?: ValidationStatusCode[];
}

// test data sets with file names and expected outcomes
const testFiles = {
'adobe-20220124-A.jpg': {
const testFiles: Record<string, TestExpectations> = {
'public-testfiles/image/jpeg/adobe-20220124-A.jpg': {
assetType: JPEG,
jumbf: false,
valid: undefined,
},
'adobe-20220124-C.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-C.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CA.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CACA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CACA.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CACAICAICICA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CACAICAICICA.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CAI.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CAI.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CAICA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CAICA.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CAICAI.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CAICAI.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CAIAIIICAICIICAIICICA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CAIAIIICAICIICAIICICA.jpg': {
assetType: JPEG,
jumbf: true,
valid: false,
statusCodes: [ValidationStatusCode.AssertionActionIngredientMismatch],
},
'adobe-20220124-CI.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CI.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CICA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CICA.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CICACACA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CICACACA.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CIE-sig-CA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CIE-sig-CA.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-CII.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-CII.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},

'adobe-20220124-E-clm-CAICAI.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-E-clm-CAICAI.jpg': {
assetType: JPEG,
jumbf: true,
valid: false,
statusCodes: [
ValidationStatusCode.AssertionHashedURIMismatch,
ValidationStatusCode.AssertionActionIngredientMismatch,
],
},
'adobe-20220124-E-dat-CA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-E-dat-CA.jpg': {
assetType: JPEG,
jumbf: true,
valid: false,
statusCodes: [ValidationStatusCode.AssertionDataHashMismatch],
},
'adobe-20220124-E-sig-CA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-E-sig-CA.jpg': {
assetType: JPEG,
jumbf: true,
valid: false,
statusCodes: [ValidationStatusCode.ClaimSignatureMismatch],
},
'adobe-20220124-E-uri-CA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-E-uri-CA.jpg': {
assetType: JPEG,
jumbf: true,
valid: false,
statusCodes: [ValidationStatusCode.AssertionHashedURIMismatch],
},
'adobe-20220124-E-uri-CIE-sig-CA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-E-uri-CIE-sig-CA.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'adobe-20220124-I.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-I.jpg': {
assetType: JPEG,
jumbf: false,
valid: undefined,
},
'adobe-20220124-XCA.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-XCA.jpg': {
assetType: JPEG,
jumbf: true,
valid: false,
statusCodes: [ValidationStatusCode.AssertionDataHashMismatch],
},
'adobe-20220124-XCI.jpg': {
'public-testfiles/image/jpeg/adobe-20220124-XCI.jpg': {
assetType: JPEG,
jumbf: true,
valid: false,
statusCodes: [ValidationStatusCode.AssertionDataHashMismatch],
},
'adobe-20221004-ukraine_building.jpeg': {
'public-testfiles/image/jpeg/adobe-20221004-ukraine_building.jpeg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'nikon-20221019-building.jpeg': {
'public-testfiles/image/jpeg/nikon-20221019-building.jpeg': {
assetType: JPEG,
jumbf: true,
valid: false,
statusCodes: [ValidationStatusCode.SigningCredentialExpired],
},
'truepic-20230212-camera.jpg': {
'public-testfiles/image/jpeg/truepic-20230212-camera.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'public-testfiles/image/jpeg/truepic-20230212-landscape.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'truepic-20230212-landscape.jpg': {
'public-testfiles/image/jpeg/truepic-20230212-library.jpg': {
assetType: JPEG,
jumbf: true,
valid: true,
},
'truepic-20230212-library.jpg': {
'amazon-titan-g1.png': {
assetType: PNG,
jumbf: true,
valid: true,
},
'trustnxt-icon.jpg': {
assetType: JPEG,
jumbf: false,
},
'trustnxt-icon.png': {
assetType: PNG,
jumbf: false,
},
'trustnxt-icon.heic': {
assetType: BMFF,
jumbf: false,
},
};

describe('Functional JPEG Reading Tests', function () {
describe('Functional Asset Reading Tests', function () {
this.timeout(0);

for (const [filename, test] of Object.entries(testFiles)) {
const data = Object.assign(new TestExpectations(), test);
for (const [filename, data] of Object.entries(testFiles)) {
describe(`test file ${filename}`, () => {
let buf: Buffer | undefined = undefined;
it(`loading test file`, async () => {
Expand All @@ -167,10 +211,10 @@ describe('Functional JPEG Reading Tests', function () {
if (!buf) this.skip();

// ensure it's a JPEG
assert.ok(JPEG.canRead(buf));
assert.ok(data.assetType.canRead(buf));

// construct the asset
asset = new JPEG(buf);
asset = new data.assetType(buf);
});

let jumbf: Uint8Array | undefined = undefined;
Expand Down Expand Up @@ -211,7 +255,7 @@ describe('Functional JPEG Reading Tests', function () {
assert.equal(validationResult.isValid, data.valid);
});

data.statusCodes.forEach(value => {
data.statusCodes?.forEach(value => {
it(`check status code ${value}`, async function () {
if (validationResult === undefined) this.skip();

Expand Down
Binary file added tests/fixtures/amazon-titan-g1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b5f2854

Please sign in to comment.