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

chore!(sdk): Remove html wrapper creation #406

Merged
merged 3 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
36 changes: 11 additions & 25 deletions lib/tdf3/src/client/builders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,22 @@ export type EncryptParams = {
scope?: Scope;
metadata?: Metadata;
keypair?: CryptoKeyPair;
// Deprecated: Only offline more is currently supported
offline?: boolean;
windowSize?: number;
asHtml?: boolean;
getPolicyId?: () => Scope['policyId'];
mimeType?: string;
payloadKey?: Binary;
keyMiddleware?: EncryptKeyMiddleware;
splitPlan?: SplitStep[];
streamMiddleware?: EncryptStreamMiddleware;
assertionConfigs?: AssertionConfig[];

// Unsupported
asHtml?: boolean;
// Unsupported
offline?: boolean;
};

// 'Readonly<EncryptParams>': scope, metadata, offline, windowSize, asHtml

// deep copy is expensive, could be faster is Immer used, but to keep SDK work
// stable we can just make this object readonly
function freeze<Type>(obj: Type): Readonly<Type> {
Expand All @@ -75,9 +76,7 @@ class EncryptParamsBuilder {
attributes: [],
},
keypair: undefined,
offline: false,
windowSize: DEFAULT_SEGMENT_SIZE,
asHtml: false,
assertionConfigs: [],
}
) {
Expand Down Expand Up @@ -382,37 +381,24 @@ class EncryptParamsBuilder {
}

/**
* Whether the encrypted data should be formatted using html. This allows authorized users to
* double click and read using the Virtru Secure Reader, at the cost of reduced space efficiency.
* <br/><br/>
* This is enabled by default.
* @return {boolean} true if the encrypted data will be in html format.
* @deprecated This feature is not supported
*/
hasHtmlFormat(): boolean {
return !!this._params.asHtml;
return false;
}

/**
* Specify that the encrypted data should be formatted using html. This allows authorized users to
* double click and read using the Virtru Secure Reader, at the cost of reduced space efficiency.
* <br/><br/>
* This is enabled by default.
* @deprecated This feature is not supported
*/
setHtmlFormat() {
this._params.asHtml = true;
throw new ConfigurationError('HTML format is not supported');
}

/**
* Specify that the encrypted data should be formatted using html. This allows authorized users to
* double click and read using the Virtru Secure Reader, at the cost of reduced space efficiency.
* Returns this object for method chaining.
* <br/><br/>
* This is enabled by default.
* @return {EncryptParamsBuilder} - this object.
* @deprecated This feature is not supported
*/
withHtmlFormat(): EncryptParamsBuilder {
this.setHtmlFormat();
return this;
throw new ConfigurationError('HTML format is not supported');
}

/**
Expand Down
30 changes: 7 additions & 23 deletions lib/tdf3/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ import {
EncryptConfiguration,
fetchKasPublicKey,
loadTDFStream,
unwrapHtml,
validatePolicyObject,
readStream,
wrapHtml,
writeStream,
} from '../tdf.js';
import { unwrapHtml } from '../utils/unwrap.js';
import { OIDCRefreshTokenProvider } from '../../../src/auth/oidc-refreshtoken-provider.js';
import { OIDCExternalJwtProvider } from '../../../src/auth/oidc-externaljwt-provider.js';
import { CryptoService } from '../crypto/declarations.js';
Expand Down Expand Up @@ -52,7 +51,6 @@ import { attributeFQNsAsValues } from '../../../src/policy/api.js';
import { type Value } from '../../../src/policy/attributes.js';

const GLOBAL_BYTE_LIMIT = 64 * 1000 * 1000 * 1000; // 64 GB, see WS-9363.
const HTML_BYTE_LIMIT = 100 * 1000 * 1000; // 100 MB, see WS-9476.

// No default config for now. Delegate to Virtru wrapper for endpoints.
const defaultClientConfig = { oidcOrigin: '', cryptoService: defaultCryptoService };
Expand Down Expand Up @@ -350,7 +348,7 @@ export class Client {
scope = { attributes: [], dissem: [] },
autoconfigure,
source,
asHtml = false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why remove the false default?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need to assert it is === false as that is the default (and I think has been for some time)

asHtml,
metadata,
mimeType,
offline = true,
Expand All @@ -363,6 +361,9 @@ export class Client {
if (!offline) {
throw new ConfigurationError('online mode not supported');
}
if (asHtml) {
throw new ConfigurationError('html mode not supported');
}
const dpopKeys = await this.dpopKeys;

const policyObject = asPolicy(scope);
Expand Down Expand Up @@ -426,7 +427,7 @@ export class Client {

// TODO: Refactor underlying builder to remove some of this unnecessary config.

const byteLimit = asHtml ? HTML_BYTE_LIMIT : GLOBAL_BYTE_LIMIT;
const byteLimit = GLOBAL_BYTE_LIMIT;
const encryptionInformation = new SplitKey(new AesGcmCipher(this.cryptoService));
const splits: SplitStep[] = splitPlan?.length ? splitPlan : [{ kas: this.kasEndpoint }];
encryptionInformation.keyAccess = await Promise.all(
Expand Down Expand Up @@ -465,24 +466,7 @@ export class Client {
assertionConfigs,
};

const stream = await (streamMiddleware as EncryptStreamMiddleware)(await writeStream(ecfg));

if (!asHtml) {
return stream;
}

// Wrap if it's html.
if (!stream.manifest) {
throw new Error('internal: missing manifest in encrypt function');
}
const htmlBuf = wrapHtml(await stream.toBuffer(), stream.manifest, this.readerUrl ?? '');

return new DecoratedReadableStream({
pull(controller: ReadableStreamDefaultController) {
controller.enqueue(htmlBuf);
controller.close();
},
});
return (streamMiddleware as EncryptStreamMiddleware)(await writeStream(ecfg));
}

/**
Expand Down
47 changes: 0 additions & 47 deletions lib/tdf3/src/tdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { base64 } from '../../src/encodings/index.js';
import {
ZipReader,
ZipWriter,
base64ToBuffer,
keyMerge,
buffToString,
concatUint8,
Expand All @@ -40,7 +39,6 @@ import {
UnsupportedFeatureError as UnsupportedError,
} from '../../src/errors.js';
import { type Chunker } from '../../src/seekable.js';
import { htmlWrapperTemplate } from './templates/index.js';

// configurable
// TODO: remove dependencies from ciphers so that we can open-source instead of relying on other Virtru libs
Expand Down Expand Up @@ -180,51 +178,6 @@ export async function fetchKasPublicKey(
return fetchKasPubKeyV2(kas, algorithm || 'rsa:2048');
}

/**
*
* @param payload The TDF content to encode in HTML
* @param manifest A copy of the manifest
* @param transferUrl reader web-service start page
* @return utf-8 encoded HTML data
*/
export function wrapHtml(
payload: Uint8Array,
manifest: Manifest | string,
transferUrl: string
): Uint8Array {
const { origin } = new URL(transferUrl);
const exportManifest: string = typeof manifest === 'string' ? manifest : JSON.stringify(manifest);

const fullHtmlString = htmlWrapperTemplate({
transferUrl,
transferBaseUrl: origin,
manifest: base64.encode(exportManifest),
payload: buffToString(payload, 'base64'),
});

return new TextEncoder().encode(fullHtmlString);
}

export function unwrapHtml(htmlPayload: ArrayBuffer | Uint8Array | Binary | string) {
let html;
if (htmlPayload instanceof ArrayBuffer || ArrayBuffer.isView(htmlPayload)) {
html = new TextDecoder().decode(htmlPayload);
} else {
html = htmlPayload.toString();
}
const payloadRe = /<input id=['"]?data-input['"]?[^>]*?value=['"]?([a-zA-Z0-9+/=]+)['"]?/;
const reResult = payloadRe.exec(html);
if (reResult === null) {
throw new InvalidFileError('Payload is missing');
}
const base64Payload = reResult[1];
try {
return base64ToBuffer(base64Payload);
} catch (e) {
throw new InvalidFileError('There was a problem extracting the TDF3 payload', e);
}
}

export async function extractPemFromKeyString(keyString: string): Promise<string> {
let pem: string = keyString;

Expand Down
105 changes: 0 additions & 105 deletions lib/tdf3/src/templates/default.html.ts

This file was deleted.

10 changes: 0 additions & 10 deletions lib/tdf3/src/templates/escaper.ts

This file was deleted.

2 changes: 0 additions & 2 deletions lib/tdf3/src/templates/index.ts

This file was deleted.

4 changes: 0 additions & 4 deletions lib/tdf3/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ const hexSliceLookupTable = (() => {
return table;
})();

export function base64ToBuffer(b64: string): Uint8Array {
return Uint8Array.from(atob(b64).split(''), (c) => c.charCodeAt(0));
}

export function concatUint8(uint8Arrays: Uint8Array[]): Uint8Array {
const newLength = uint8Arrays.reduce(
(accumulator, currentValue) => accumulator + currentValue.length,
Expand Down
17 changes: 17 additions & 0 deletions lib/tdf3/src/utils/unwrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { decodeArrayBuffer } from '../../../src/encodings/base64.js';
import { InvalidFileError } from '../../../src/errors.js';

export function unwrapHtml(htmlPayload: Uint8Array): Uint8Array {
const html = new TextDecoder().decode(htmlPayload);
const payloadRe = /<input id=['"]?data-input['"]?[^>]*?value=['"]?([a-zA-Z0-9+/=]+)['"]?/;
const reResult = payloadRe.exec(html);
if (!reResult) {
throw new InvalidFileError('Payload is missing');
}
const base64Payload = reResult[1];
try {
return new Uint8Array(decodeArrayBuffer(base64Payload));
} catch (e) {
throw new InvalidFileError('There was a problem extracting the TDF3 payload', e);
}
}
1 change: 0 additions & 1 deletion lib/tests/mocha/unit/crypto-di.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ describe('CryptoService DI', () => {
});
try {
await c.encrypt({
asHtml: false,
source: new ReadableStream({
pull(controller) {
controller.enqueue(new TextEncoder().encode('hello world'));
Expand Down
Loading
Loading