Skip to content

Commit

Permalink
feat(cli): Adds --policyBinding ecdsa option (#352)
Browse files Browse the repository at this point in the history
Only effective with `-t nano`, this enables the ECDSA binding type to verify the policy is attached to the key is as expected.
  • Loading branch information
dmihalcik-virtru committed Sep 17, 2024
1 parent 031bbb7 commit 4e54c0d
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 83 deletions.
60 changes: 42 additions & 18 deletions cli/package-lock.json

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

61 changes: 34 additions & 27 deletions cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ type LoggedAuthProvider = AuthProvider & {
requestLog: HttpRequest[];
};

const containerTypes = ['tdf3', 'nano', 'dataset'] as const;
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());
Expand Down Expand Up @@ -219,48 +221,52 @@ export const handleArgs = (args: string[]) => {
})
.implies('exchangeToken', 'clientId')

.option('containerType', {
group: 'TDF Settings',
alias: 't',
choices: containerTypes,
description: 'Container format',
default: 'nano',
})

.option('userId', {
group: 'TDF Settings',
type: 'string',
description: 'Owner email address',
})

// Examples
.example('$0 --auth ClientID123:Cli3nt$ecret', '# OIDC client credentials')

.example('$0 --clientId ClientID123 --clientSecret Cli3nt$ecret', '# OIDC client credentials')

// POLICY
// Policy, encryption, and container options
.options({
usersWithAccess: {
alias: 'users-with-access',
group: 'Encrypt Options',
desc: 'Add users to the policy',
type: 'string',
default: '',
validate: (users: string) => users.split(','),
},
attributes: {
group: 'Encrypt Options',
desc: 'Data attributes for the policy',
type: 'string',
default: '',
validate: (attributes: string) => attributes.split(','),
},
containerType: {
group: 'Encrypt Options',
alias: 't',
choices: containerTypes,
description: 'Container format',
default: 'nano',
},
policyBinding: {
group: 'Encrypt Options',
choices: bindingTypes,
description: 'Policy Binding Type (nano only)',
default: 'gmac',
},
mimeType: {
group: 'Encrypt Options',
desc: 'Mime type for the plain text file (only supported for ztdf)',
type: 'string',
default: '',
},
userId: {
group: 'Encrypt Options',
type: 'string',
description: 'Owner email address',
},
usersWithAccess: {
alias: 'users-with-access',
group: 'Encrypt Options',
desc: 'Add users to the policy',
type: 'string',
default: '',
validate: (users: string) => users.split(','),
},
})

// COMMANDS
Expand Down Expand Up @@ -299,7 +305,7 @@ export const handleArgs = (args: string[]) => {
log('DEBUG', `Initialized auth provider ${JSON.stringify(authProvider)}`);

const kasEndpoint = argv.kasEndpoint;
if (argv.containerType === 'tdf3') {
if (argv.containerType === 'tdf3' || argv.containerType == 'ztdf') {
log('DEBUG', `TDF3 Client`);
const client = new TDF3Client({
allowedKases,
Expand Down Expand Up @@ -389,7 +395,7 @@ export const handleArgs = (args: string[]) => {
const ignoreAllowList = !!argv.ignoreAllowList;
const allowedKases = argv.allowList?.split(',');

if ('tdf3' === argv.containerType) {
if ('tdf3' === argv.containerType || 'ztdf' === argv.containerType) {
log('DEBUG', `TDF3 Client`);
const client = new TDF3Client({
allowedKases,
Expand All @@ -411,6 +417,7 @@ export const handleArgs = (args: string[]) => {
}
} else {
const dpopEnabled = !!argv.dpop;
const ecdsaBinding = argv.policyBinding.toLowerCase() == 'ecdsa';
const client =
argv.containerType === 'nano'
? new NanoTDFClient({ allowedKases, authProvider, dpopEnabled, kasEndpoint })
Expand All @@ -425,7 +432,7 @@ export const handleArgs = (args: string[]) => {
addParams(client, argv);

const buffer = await processDataIn(argv.file as string);
const cyphertext = await client.encrypt(buffer);
const cyphertext = await client.encrypt(buffer, { ecdsaBinding });

log('DEBUG', `Handle cyphertext output ${JSON.stringify(cyphertext)}`);
if (argv.output) {
Expand Down
11 changes: 9 additions & 2 deletions lib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export class NanoTDFDatasetClient extends Client {
private unwrappedKey?: CryptoKey;
private symmetricKey?: CryptoKey;
private cachedHeader?: Header;
private ecdsaBinding: boolean;

/**
* Create new NanoTDF Dataset Client
Expand Down Expand Up @@ -256,9 +257,14 @@ export class NanoTDFDatasetClient extends Client {
*
* @param data to decrypt
*/
async encrypt(data: string | TypedArray | ArrayBuffer): Promise<ArrayBuffer> {
async encrypt(
data: string | TypedArray | ArrayBuffer,
options?: EncryptOptions
): Promise<ArrayBuffer> {
// Intial encrypt
if (this.keyIterationCount == 0) {
const mergedOptions: EncryptOptions = { ...defaultOptions, ...options };
this.ecdsaBinding = mergedOptions.ecdsaBinding;
// For encrypt always generate the client ephemeralKeyPair
const ephemeralKeyPair = await this.ephemeralKeyPair;

Expand Down Expand Up @@ -298,7 +304,8 @@ export class NanoTDFDatasetClient extends Client {
this.kasPubKey,
ephemeralKeyPair,
ivVector,
data
data,
this.ecdsaBinding
);

// Cache the header and increment the key iteration
Expand Down
Loading

0 comments on commit 4e54c0d

Please sign in to comment.