All files / src convert.ts

100% Statements 40/40
100% Branches 27/27
100% Functions 6/6
100% Lines 40/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127                                5x 5x 5x   5x   5x   5x 6x     6x 1x     5x     5x 6x 6x         1x         5x     5x 4x   4x 4x   4x     5x   5x   5x     3x 1x   2x                   2x     5x   3x   3x 1x     2x     5x     5x 1x   4x   4x     4x               1x         3x                  
/*
 * Copyright © 2019 Lisk Foundation
 *
 * See the LICENSE file at the top-level directory of this distribution
 * for licensing information.
 *
 * Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation,
 * no part of this software, including this file, may be copied, modified,
 * propagated, or distributed except according to the terms contained in the
 * LICENSE file.
 *
 * Removal or modification of this copyright notice is prohibited.
 *
 */
// Required because first level function export
// tslint:disable-next-line no-require-imports
import reverse = require('buffer-reverse');
import * as ed2curve from 'ed2curve';
import * as querystring from 'querystring';
 
import { bufferToIntAsString } from './buffer';
import { EncryptedPassphraseObject } from './encrypt';
import { hash } from './hash';
 
export const getFirstEightBytesReversed = (input: string | Buffer): Buffer => {
	const BUFFER_SIZE = 8;
	// Union type arguments on overloaded functions do not work in typescript.
	// Relevant discussion: https://github.com/Microsoft/TypeScript/issues/23155
	if (typeof input === 'string') {
		return reverse(Buffer.from(input).slice(0, BUFFER_SIZE));
	}
 
	return reverse(Buffer.from(input).slice(0, BUFFER_SIZE));
};
 
export const toAddress = (buffer: Buffer): string => {
	const BUFFER_SIZE = 8;
	if (
		!Buffer.from(buffer)
			.slice(0, BUFFER_SIZE)
			.equals(buffer)
	) {
		throw new Error(
			'The buffer for Lisk addresses must not have more than 8 bytes',
		);
	}
 
	return `${bufferToIntAsString(buffer)}L`;
};
 
export const getAddressFromPublicKey = (publicKey: string): string => {
	const publicKeyHash = hash(publicKey, 'hex');
 
	const publicKeyTransform = getFirstEightBytesReversed(publicKeyHash);
	const address = toAddress(publicKeyTransform);
 
	return address;
};
 
export const convertPublicKeyEd2Curve = ed2curve.convertPublicKey;
 
export const convertPrivateKeyEd2Curve = ed2curve.convertSecretKey;
 
export const stringifyEncryptedPassphrase = (
	encryptedPassphrase: EncryptedPassphraseObject,
): string => {
	if (typeof encryptedPassphrase !== 'object' || encryptedPassphrase === null) {
		throw new Error('Encrypted passphrase to stringify must be an object.');
	}
	const objectToStringify = encryptedPassphrase.iterations
		? encryptedPassphrase
		: {
				salt: encryptedPassphrase.salt,
				cipherText: encryptedPassphrase.cipherText,
				iv: encryptedPassphrase.iv,
				tag: encryptedPassphrase.tag,
				version: encryptedPassphrase.version,
		  };
 
	return querystring.stringify(objectToStringify);
};
 
const parseIterations = (iterationsString?: string): number | undefined => {
	const iterations =
		iterationsString === undefined ? undefined : parseInt(iterationsString, 10);
 
	if (typeof iterations !== 'undefined' && Number.isNaN(iterations)) {
		throw new Error('Could not parse iterations.');
	}
 
	return iterations;
};
 
export const parseEncryptedPassphrase = (
	encryptedPassphrase: string,
): EncryptedPassphraseObject => {
	if (typeof encryptedPassphrase !== 'string') {
		throw new Error('Encrypted passphrase to parse must be a string.');
	}
	const keyValuePairs = querystring.parse(encryptedPassphrase);
 
	const { iterations, salt, cipherText, iv, tag, version } = keyValuePairs;
 
	// Review, and find a better solution
	if (
		(typeof iterations !== 'string' && typeof iterations !== 'undefined') ||
		typeof salt !== 'string' ||
		typeof cipherText !== 'string' ||
		typeof iv !== 'string' ||
		typeof tag !== 'string' ||
		typeof version !== 'string'
	) {
		throw new Error(
			'Encrypted passphrase to parse must have only one value per key.',
		);
	}
 
	return {
		iterations: parseIterations(iterations),
		salt,
		cipherText,
		iv,
		tag,
		version,
	};
};