Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sdk): Allows skipping verification #371

Merged
merged 4 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 4 additions & 49 deletions cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 43 additions & 6 deletions cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import {
} from '@opentdf/client';
import { CLIError, Level, log } from './logger.js';
import { webcrypto } from 'crypto';
import * as assertions from '@opentdf/client/assertions';
import { attributeFQNsAsValues } from '@opentdf/client/nano';
import { base64 } from '@opentdf/client/encodings';

type AuthToProcess = {
auth?: string;
Expand All @@ -37,8 +39,9 @@ const bindingTypes = ['ecdsa', 'gmac'];
const containerTypes = ['tdf3', 'nano', 'dataset', 'ztdf'];

const parseJwt = (jwt: string, field = 1) => {
return JSON.parse(Buffer.from(jwt.split('.')[field], 'base64').toString());
return JSON.parse(base64.decode(jwt.split('.')[field]));
};

const parseJwtComplete = (jwt: string) => {
return { header: parseJwt(jwt, 0), payload: parseJwt(jwt) };
};
Expand Down Expand Up @@ -113,12 +116,33 @@ function addParams(client: AnyNanoClient, argv: Partial<mainArgs>) {

async function tdf3DecryptParamsFor(argv: Partial<mainArgs>): Promise<DecryptParams> {
const c = new DecryptParamsBuilder();
if (argv.noVerifyAssertions) {
c.withNoVerifyAssertions(true);
}
c.setFileSource(await openAsBlob(argv.file as string));
return c.build();
}

function parseAssertionConfig(s: string): assertions.AssertionConfig[] {
const u = JSON.parse(s);
// if u is null or empty, return an empty array
if (!u) {
return [];
}
const a = Array.isArray(u) ? u : [u];
for (const assertion of a) {
if (!assertions.isAssertionConfig(assertion)) {
throw new CLIError('CRITICAL', `invalid assertion config ${JSON.stringify(assertion)}`);
}
}
return a;
}

async function tdf3EncryptParamsFor(argv: Partial<mainArgs>): Promise<EncryptParams> {
const c = new EncryptParamsBuilder();
if (argv.assertions?.length) {
c.withAssertions(parseAssertionConfig(argv.assertions));
}
if (argv.attributes?.length) {
c.setAttributes(argv.attributes.split(','));
}
Expand Down Expand Up @@ -201,13 +225,19 @@ export const handleArgs = (args: string[]) => {
group: 'Security:',
desc: 'allowed KAS origins, comma separated; defaults to [kasEndpoint]',
type: 'string',
validate: (attributes: string) => attributes.split(','),
validate: (uris: string) => uris.split(','),
})
.option('ignoreAllowList', {
group: 'Security:',
desc: 'disable KAS allowlist feature for decrypt',
type: 'boolean',
})
.option('noVerifyAssertions', {
alias: 'no-verify-assertions',
group: 'Security',
desc: 'Do not verify assertions',
type: 'boolean',
})
.option('auth', {
group: 'OAuth and OIDC:',
type: 'string',
Expand Down Expand Up @@ -252,6 +282,13 @@ export const handleArgs = (args: string[]) => {

// Policy, encryption, and container options
.options({
assertions: {
group: 'Encrypt Options:',
desc: 'ZTDF assertion config objects',
type: 'string',
default: '',
validate: parseAssertionConfig,
},
attributes: {
group: 'Encrypt Options:',
desc: 'Data attributes for the policy',
Expand Down Expand Up @@ -413,9 +450,9 @@ export const handleArgs = (args: string[]) => {

log('DEBUG', 'Handle output.');
if (argv.output) {
await writeFile(argv.output, Buffer.from(plaintext));
await writeFile(argv.output, new Uint8Array(plaintext));
} else {
console.log(Buffer.from(plaintext).toString('utf8'));
console.log(new TextDecoder().decode(plaintext));
}
}
const lastRequest = authProvider.requestLog[authProvider.requestLog.length - 1];
Expand Down Expand Up @@ -503,9 +540,9 @@ export const handleArgs = (args: string[]) => {

log('DEBUG', `Handle cyphertext output ${JSON.stringify(cyphertext)}`);
if (argv.output) {
await writeFile(argv.output, Buffer.from(cyphertext));
await writeFile(argv.output, new Uint8Array(cyphertext));
} else {
console.log(Buffer.from(cyphertext).toString('base64'));
console.log(base64.encodeArrayBuffer(cyphertext));
}
}
}
Expand Down
24 changes: 1 addition & 23 deletions lib/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
"require": "./dist/cjs/tdf3/index.js",
"import": "./dist/web/tdf3/index.js"
},
"./assertions": {
"default": {
"types": "./dist/types/tdf3/src/assertions.d.ts",
"require": "./dist/cjs/tdf3/src/assertions.js",
"import": "./dist/web/tdf3/src/assertions.js"
}
},
"./encodings": {
"default": {
"types": "./dist/types/src/encodings/index.d.ts",
Expand Down Expand Up @@ -64,7 +71,6 @@
"axios-retry": "^3.9.0",
"base64-js": "^1.5.1",
"browser-fs-access": "^0.34.1",
"buffer": "^6.0.3",
"buffer-crc32": "^0.2.13",
"dpop": "^1.2.0",
"eventemitter3": "^5.0.1",
Expand Down
20 changes: 10 additions & 10 deletions lib/src/nanotdf/models/Header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,28 +232,28 @@ export default class Header {
/**
* Copy the contents of the header to buffer
*/
copyToBuffer(buffer: Uint8Array): void {
if (this.length > buffer.length) {
copyToBuffer(target: Uint8Array): void {
if (this.length > target.length) {
throw new InvalidFileError('invalid buffer size to copy tdf header');
}

let offset = 0;

// Write Magic number and version
buffer.set(this.magicNumberVersion, 0);
target.set(this.magicNumberVersion, 0);
offset += this.magicNumberVersion.length;

// Write kas resource locator
const kasResourceLocatorBuf = this.kas.toBuffer();
buffer.set(kasResourceLocatorBuf, offset);
target.set(kasResourceLocatorBuf, offset);
offset += kasResourceLocatorBuf.length;

// Write ECC & Binding Mode
const ecdsaBinding = this.useECDSABinding ? 1 : 0;
const eccBingingMode = (ecdsaBinding << 7) | this.ephemeralCurveName;
const eccBingingModeAsByte = new Uint8Array(1);
eccBingingModeAsByte[0] = eccBingingMode;
buffer.set(eccBingingModeAsByte, offset);
target.set(eccBingingModeAsByte, offset);
offset += eccBingingModeAsByte.length;

// Write symmetric & payload config
Expand All @@ -262,16 +262,16 @@ export default class Header {
(isSignatureEnable << 7) | this.signatureCurveName | this.symmetricCipher;
const symmetricPayloadConfigAsByte = new Uint8Array(1);
symmetricPayloadConfigAsByte[0] = symmetricPayloadConfig;
buffer.set(symmetricPayloadConfigAsByte, offset);
target.set(symmetricPayloadConfigAsByte, offset);
offset += symmetricPayloadConfigAsByte.length;

// Write the policy
const policyBuffer = this.policy.toBuffer();
buffer.set(policyBuffer, offset);
target.set(policyBuffer, offset);
offset += policyBuffer.length;

// Write the ephemeral public key
buffer.set(this.ephemeralPublicKey, offset);
target.set(this.ephemeralPublicKey, offset);
}

/**
Expand Down Expand Up @@ -304,8 +304,8 @@ export default class Header {
*/
toBuffer(): ArrayBuffer {
const arrayBuffer = new ArrayBuffer(this.length);
const buffer = new Uint8Array(arrayBuffer);
this.copyToBuffer(buffer);
const target = new Uint8Array(arrayBuffer);
this.copyToBuffer(target);
return arrayBuffer;
}

Expand Down
12 changes: 6 additions & 6 deletions lib/src/nanotdf/models/Payload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ export default class Payload {
/**
* Copy the contents of the signature to buffer
*/
copyToBuffer(buffer: Uint8Array): void {
if (this.length > buffer.length) {
copyToBuffer(target: Uint8Array): void {
if (this.length > target.length) {
throw new Error('internal: invalid buffer size to copy payload');
}

Expand All @@ -188,9 +188,9 @@ export default class Payload {
payloadSizeAsBg[1] = lengthAsUint24[1];
payloadSizeAsBg[2] = lengthAsUint24[0];

buffer.set(payloadSizeAsBg, 0);
buffer.set(this.iv, payloadSizeAsBg.length);
buffer.set(this.ciphertext, payloadSizeAsBg.length + this.iv.length);
buffer.set(this.authTag, payloadSizeAsBg.length + this.iv.length + this.ciphertext.length);
target.set(payloadSizeAsBg, 0);
target.set(this.iv, payloadSizeAsBg.length);
target.set(this.ciphertext, payloadSizeAsBg.length + this.iv.length);
target.set(this.authTag, payloadSizeAsBg.length + this.iv.length + this.ciphertext.length);
}
}
12 changes: 6 additions & 6 deletions lib/src/nanotdf/models/Policy/EmbeddedPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ class EmbeddedPolicy extends AbstractPolicy implements EmbeddedPolicyInterface {
* Return the content of the policy
*/
override toBuffer(): Uint8Array {
const buffer = new Uint8Array(this.getLength());
const target = new Uint8Array(this.getLength());

if (this.content.length > EmbeddedPolicy.MAX_POLICY_SIZE) {
throw new ConfigurationError("TDF Policy can't be more that 2^16");
}

buffer.set([this.type], 0);
target.set([this.type], 0);

// Write the policy length, assuming the host system is little endian
// TODO: There should be better way to convert to big endian
Expand All @@ -86,15 +86,15 @@ class EmbeddedPolicy extends AbstractPolicy implements EmbeddedPolicyInterface {
const policyContentSizeAsBg = new Uint8Array(2);
policyContentSizeAsBg[0] = temp[1];
policyContentSizeAsBg[1] = temp[0];
buffer.set(policyContentSizeAsBg, 1);
target.set(policyContentSizeAsBg, 1);

// Write the policy content
buffer.set(this.content, policyContentSizeAsBg.length + 1);
target.set(this.content, policyContentSizeAsBg.length + 1);

// Write the binding.
buffer.set(this.binding, this.content.length + policyContentSizeAsBg.length + 1);
target.set(this.binding, this.content.length + policyContentSizeAsBg.length + 1);

return buffer;
return target;
}
}

Expand Down
Loading
Loading