Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Remove unused function and libraries for encrypt/decrypt with private…
Browse files Browse the repository at this point in the history
… key (#8529)

🐛 Remove unused function and libraries for encrypt/decrypt with
private key
  • Loading branch information
shuse2 authored Jun 6, 2023
1 parent 0ea3844 commit 33449a4
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 369 deletions.
11 changes: 11 additions & 0 deletions commander/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,15 @@ export default abstract class BaseCommand extends Command {
...this.printFlags,
}).call(this, result as StringMap);
}

printJSON(message: Record<string, unknown> | string): void {
if (typeof message === 'string') {
this.log(message);
}
if (this.printFlags.json) {
this.log(JSON.stringify(message, undefined, ' '));
} else {
this.log(JSON.stringify(message));
}
}
}
80 changes: 27 additions & 53 deletions commander/src/commands/message/decrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,90 +13,64 @@
* Removal or modification of this copyright notice is prohibited.
*
*/
import { encrypt, legacy } from '@liskhq/lisk-cryptography';
import { Flags as flagParser } from '@oclif/core';
import { encrypt } from '@liskhq/lisk-cryptography';
import { Command, Flags as flagParser } from '@oclif/core';

import BaseCommand from '../../base';
import { ValidationError } from '../../utils/error';
import { flags as commonFlags } from '../../utils/flags';
import { flags as commonFlags, flagsWithParser } from '../../utils/flags';
import { getPassphraseFromPrompt, isFileSource, readFileSource } from '../../utils/reader';

interface Args {
readonly message?: string;
readonly nonce: string;
readonly senderPublicKey: string;
}

const processInputs = (
nonce: string,
senderPublicKey: string,
passphrase: string,
message?: string,
) => {
if (!message) {
throw new ValidationError('No message was provided.');
}

const keys = legacy.getPrivateAndPublicKeyFromPassphrase(passphrase);

return encrypt.decryptMessageWithPrivateKey(
message,
nonce,
keys.privateKey,
Buffer.from(senderPublicKey, 'hex'),
);
};

export default class DecryptCommand extends BaseCommand {
export default class DecryptCommand extends Command {
static args = [
{
name: 'senderPublicKey',
description: 'Public key of the sender of the message.',
required: true,
},
{
name: 'nonce',
description: 'Nonce used during encryption.',
required: true,
},
{
name: 'message',
description: 'Encrypted message.',
},
];

static description = `
Decrypts a previously encrypted message from a given sender public key for a known nonce using your secret passphrase.
Decrypts a previously encrypted message using your the password used to encrypt.
`;

static examples = [
'message:decrypt bba7e2e6a4639c431b68e31115a71ffefcb4e025a4d1656405dfdcd8384719e0 4b800d90d54eda4d093b5e4e6bf9ed203bc90e1560bd628d dcaa605af45a4107a699755237b4c08e1ef75036743d7e4814dea7',
];
static examples = ['message:decrypt '];

static flags = {
...BaseCommand.flags,
passphrase: flagParser.string(commonFlags.passphrase),
password: flagsWithParser.password,
message: flagParser.string(commonFlags.message),
};
async run(): Promise<void> {
const {
args,
flags: { passphrase: passphraseSource, message: messageSource },
flags: { password: passwordSource, message: messageSource },
} = await this.parse(DecryptCommand);

const { senderPublicKey, nonce, message } = args as Args;

if (!message && !messageSource) {
throw new ValidationError('No message was provided.');
}
const { message } = args as Args;

const passphrase = passphraseSource ?? (await getPassphraseFromPrompt('passphrase'));
const password = passwordSource ?? (await getPassphraseFromPrompt('password'));
const dataFromSource =
messageSource && isFileSource(messageSource)
? await readFileSource(messageSource)
: messageSource;

const result = processInputs(nonce, senderPublicKey, passphrase, message ?? dataFromSource);
this.print({ message: result });
if (!message && !dataFromSource) {
this.error('Message must be provided through the argument or the flag ');
}

const encryptedMessage = message ?? (dataFromSource as string);

let parsedMessage;
try {
parsedMessage = JSON.parse(encryptedMessage) as ReturnType<
typeof encrypt.parseEncryptedMessage
>;
} catch (error) {
parsedMessage = encrypt.parseEncryptedMessage(encryptedMessage);
}

const result = await encrypt.decryptMessageWithPassword(parsedMessage, password, 'utf-8');
this.log(result);
}
}
66 changes: 28 additions & 38 deletions commander/src/commands/message/encrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,80 +13,70 @@
* Removal or modification of this copyright notice is prohibited.
*
*/
import { encrypt, legacy } from '@liskhq/lisk-cryptography';
import { Flags as flagParser } from '@oclif/core';
import { encrypt } from '@liskhq/lisk-cryptography';
import { Command, Flags as flagParser } from '@oclif/core';

import BaseCommand from '../../base';
import { ValidationError } from '../../utils/error';
import { flags as commonFlags } from '../../utils/flags';
import { flags as commonFlags, flagsWithParser } from '../../utils/flags';
import { getPassphraseFromPrompt, isFileSource, readFileSource } from '../../utils/reader';

interface Args {
readonly message?: string;
readonly recipientPublicKey: string;
}

const processInputs = (recipientPublicKey: string, passphrase: string, message?: string) => {
if (!message) {
throw new ValidationError('No message was provided.');
}
const keys = legacy.getPrivateAndPublicKeyFromPassphrase(passphrase);

return {
...encrypt.encryptMessageWithPrivateKey(
message,
keys.privateKey,
Buffer.from(recipientPublicKey, 'hex'),
),
recipientPublicKey,
};
};

export default class EncryptCommand extends BaseCommand {
export default class EncryptCommand extends Command {
static args = [
{
name: 'recipientPublicKey',
description: 'Public key of the recipient of the message.',
required: true,
},
{
name: 'message',
description: 'Message to encrypt.',
},
];

static description = `
Encrypts a message for a given recipient public key using your secret passphrase.
Encrypts a message with a password provided.
`;

static examples = [
'message:encrypt bba7e2e6a4639c431b68e31115a71ffefcb4e025a4d1656405dfdcd8384719e0 "Hello world"',
];
static examples = ['message:encrypt "Hello world"'];

static flags = {
...BaseCommand.flags,
passphrase: flagParser.string(commonFlags.passphrase),
password: flagParser.string(commonFlags.password),
message: flagParser.string(commonFlags.message),
pretty: flagsWithParser.pretty,
stringify: flagParser.boolean({
description: 'Display encrypted message in stringified format',
char: 's',
}),
};

async run(): Promise<void> {
const {
args,
flags: { passphrase: passphraseSource, message: messageSource },
flags: { password: passwordSource, message: messageSource, stringify, pretty },
} = await this.parse(EncryptCommand);

const { recipientPublicKey, message } = args as Args;
const { message } = args as Args;

if (!message && !messageSource) {
throw new ValidationError('No message was provided.');
}
const passphrase = passphraseSource ?? (await getPassphraseFromPrompt('passphrase', true));
const password = passwordSource ?? (await getPassphraseFromPrompt('password', true));
const dataFromSource =
messageSource && isFileSource(messageSource)
? await readFileSource(messageSource)
: messageSource;

const result = processInputs(recipientPublicKey, passphrase, message ?? dataFromSource);
this.print(result);
if (!message && !dataFromSource) {
this.error('Message must be provided through the argument or the flag ');
}

const result = await encrypt.encryptMessageWithPassword(
message ?? (dataFromSource as string),
password,
);
if (stringify) {
this.log(encrypt.stringifyEncryptedMessage(result));
return;
}
this.log(!pretty ? JSON.stringify(result) : JSON.stringify(result, undefined, ' '));
}
}
27 changes: 0 additions & 27 deletions commander/src/utils/reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
*
*/
import { Schema } from '@liskhq/lisk-codec';
import * as liskPassphrase from '@liskhq/lisk-passphrase';

import * as path from 'path';
import * as fs from 'fs';
Expand All @@ -23,11 +22,6 @@ import * as readline from 'readline';

import { FileSystemError, ValidationError } from './error';

interface MnemonicError {
readonly code: string;
readonly message: string;
}

interface PropertyValue {
readonly dataType: string;
readonly type: string;
Expand Down Expand Up @@ -92,27 +86,6 @@ export const getPassphraseFromPrompt = async (
throw new ValidationError(getPromptVerificationFailError(displayName));
}

const passphraseErrors = [passphrase]
.filter(Boolean)
.map(pass =>
liskPassphrase.validation
.getPassphraseValidationErrors(pass as string)
.filter((error: MnemonicError) => error.message),
);

passphraseErrors.forEach(errors => {
if (errors.length > 0) {
const passphraseWarning = errors
.filter((error: MnemonicError) => error.code !== 'INVALID_MNEMONIC')
.reduce(
(accumulator: string, error: MnemonicError) =>
accumulator.concat(`${error.message.replace(' Please check the passphrase.', '')} `),
'Warning: ',
);
console.warn(passphraseWarning);
}
});

// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return passphrase;
};
Expand Down
49 changes: 15 additions & 34 deletions commander/test/commands/message/decrypt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
*
*/
import * as inquirer from 'inquirer';
import { encrypt } from '@liskhq/lisk-cryptography';
import { getConfig } from '../../helpers/config';
import DecryptCommand from '../../../src/commands/message/decrypt';
import * as readerUtils from '../../../src/utils/reader';
import { Awaited } from '../../types';

describe('message:decrypt', () => {
const defaultSenderPublicKey = 'fd061b9146691f3c56504be051175d5b76d1b1d0179c5c4370e18534c5882122';
const defaultNonce = 'b3e80b6a6da64c8ab61ca6503b244daacbee59a33c5408c4';
const defaultEncryptedMessage = '0529c0113b93af6f9a851d47062e94cfb77101cc0e';
const result = '{"message":"hello"}\n';
const defaultEncryptedMessage =
'kdf=argon2id&cipher=aes-256-gcm&version=1&ciphertext=023fd9427f&mac=647457ac72dbc5e567e8f9ca173ddd457909ed2f45aa080daac78078a1293e8e&salt=82c1f80fbd9500aa1421f1e491cd46d4&iv=3265e728a4b6015087616385&tag=86e2bf01ba81c0079345ae8eb5ac1704&iterations=1&parallelism=4&memorySize=2024';
const result = 'hello\n';
const defaultInputs =
'tiny decrease photo key change abuse forward penalty twin foot wish expose';

Expand All @@ -37,52 +37,33 @@ describe('message:decrypt', () => {
config = await getConfig();
jest.spyOn(process.stdout, 'write').mockImplementation(val => stdout.push(val as string) > -1);
jest.spyOn(process.stderr, 'write').mockImplementation(val => stderr.push(val as string) > -1);
jest.spyOn(readerUtils, 'readFileSource').mockResolvedValue(defaultEncryptedMessage);
jest
.spyOn(readerUtils, 'readFileSource')
.mockResolvedValue(JSON.stringify(encrypt.parseEncryptedMessage(defaultEncryptedMessage)));
jest
.spyOn(inquirer, 'prompt')
.mockResolvedValue({ passphrase: defaultInputs, passphraseRepeat: defaultInputs });
});

it('should throw an error when arg is not provided', async () => {
await expect(DecryptCommand.run([], config)).rejects.toThrow('Missing 2 required arg');
});

describe('message:decrypt senderPublicKey', () => {
it('should throw an error when arg is not provided', async () => {
await expect(DecryptCommand.run([defaultSenderPublicKey], config)).rejects.toThrow(
'Missing 1 required arg',
);
});
});

describe('message:decrypt senderPublicKey nonce', () => {
describe('message:decrypt', () => {
it('should throw an error when message is not provided', async () => {
await expect(
DecryptCommand.run([defaultSenderPublicKey, defaultNonce], config),
).rejects.toThrow('No message was provided.');
await expect(DecryptCommand.run([], config)).rejects.toThrow(
'Message must be provided through the argument or the flag',
);
});
});

describe('message:decrypt senderPublicKey nonce message', () => {
describe('message:decrypt message', () => {
it('should decrypt the message with the arg', async () => {
await DecryptCommand.run(
[defaultSenderPublicKey, defaultNonce, defaultEncryptedMessage, '-j'],
config,
);
await DecryptCommand.run([defaultEncryptedMessage], config);
expect(process.stdout.write).toHaveBeenCalledWith(result);
});
});

describe('message:decrypt senderPublicKey nonce --message=file:./message.txt', () => {
describe('message:decrypt --message=file:./message.txt', () => {
it('should decrypt the message with the arg and the message flag', async () => {
await DecryptCommand.run(
[
defaultSenderPublicKey,
defaultNonce,
'--message=file:./message.txt',
`--passphrase=${defaultInputs}`,
'-j',
],
['--message=file:./message.txt', `--password=${defaultInputs}`],
config,
);
expect(process.stdout.write).toHaveBeenCalledWith(result);
Expand Down
Loading

0 comments on commit 33449a4

Please sign in to comment.