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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 3x 3x 1x 2x 1x | /**
* Copyright (c) Benjamin Ansbach - all rights reserved.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
const BC = require('@pascalcoin-sbx/common').BC;
const mipherAES = require('mipher/dist/aes');
const mipherRandom = require('mipher/dist/random');
const KDF = require('./KDF');
const ECDH = require('./ECDH');
/**
* A class that can en-/decrypt payloads.
*/
class Payload {
/**
* Encrypts the given payload with the given password the PascalCoin way.
*
* @param {Buffer|Uint8Array|BC|String} payload
* @param {Buffer|Uint8Array|BC|String} password
*
* @return {BC}
*/
static encryptUsingPassword(payload, password) {
payload = BC.from(payload, 'string');
password = BC.from(password, 'string');
let aes = new mipherAES.AES_CBC_PKCS7();
const randomGenerator = new mipherRandom.Random();
const salt = new BC(Buffer.from(randomGenerator.get(8)));
// mocha sees an open setinterval and won't exit without this change
randomGenerator.stop();
const keyInfo = KDF.PascalCoin(password, salt);
return BC.concat(
BC.fromString('Salted__'),
salt,
new BC(aes.encrypt(keyInfo.key.buffer, payload.buffer, keyInfo.iv.buffer))
);
}
/**
* Decrypts the given encrypted payload with the given password the
* PascalCoin way.
*
* @param {Buffer|Uint8Array|BC|String} encrypted
* @param {Buffer|Uint8Array|BC|String} password
*
* @return {BC}
*/
static decryptUsingPassword(encrypted, password) {
encrypted = BC.from(encrypted);
password = BC.from(password, 'string');
let aes = new mipherAES.AES_CBC_PKCS7();
const salt = encrypted.slice(8, 16);
const rest = encrypted.slice(16);
const keyInfo = KDF.PascalCoin(password, salt);
let result = aes.decrypt(keyInfo.key.buffer, rest.buffer, keyInfo.iv.buffer);
if (result.length === 0) {
return false;
}
return new BC(result);
}
/**
* Decrypts the given encrypted payload using the given key.
*
* @param {Buffer|Uint8Array|BC|String} payload
* @param {KeyPair} keyPair
*/
static decryptUsingPrivateKey(payload, keyPair) {
payload = BC.from(payload);
// extract data
const publicKeyLength = payload.slice(0, 1).toInt();
const macLength = payload.slice(1, 2).toInt();
const origMsgLength = payload.slice(2, 4).switchEndian().toInt();
const messageLength = payload.slice(4, 6).switchEndian().toInt();
let start = 6;
let end = start + publicKeyLength;
const ecdhPubKey = payload.slice(start, end);
start = end + macLength;
end = start + messageLength + 1;
// const ecdhMessage = payload.slice(6 + publicKeyLength + macLength,
// 6 + publicKeyLength + macLength + messageLength + 1).buffer;
const ecdhMessage = payload.slice(start, end);
const encryptedMessage = payload.slice(payload.length - messageLength, payload.length);
const macMessage = payload.slice(6 + publicKeyLength, 6 + publicKeyLength + macLength);
const dec = ECDH.decrypt(
keyPair.privateKey,
ecdhPubKey,
ecdhMessage, origMsgLength
);
const hmac = require('crypto').createHmac('md5', dec.key.buffer);
const m2 = BC.fromHex(hmac.update(encryptedMessage.buffer).digest('hex'));
if (new BC(macMessage).equals(new BC(m2))) {
return dec.data;
}
return false;
}
/**
* encrypts the goven payload using the given public key.
*
* @param {Buffer|Uint8Array|BC|String} payload
* @param {PublicKey} publicKey
*/
static encryptUsingPublicKey(payload, publicKey) {
payload = BC.from(payload, 'string');
const enc = ECDH.encrypt(
publicKey,
payload
);
const hmac = require('crypto').createHmac('md5', enc.key.buffer);
const m2 = BC.fromHex(hmac.update(enc.data.buffer).digest('hex'));
const messageToEncryptSize = payload.length;
const messageToEncryptPadSize = (messageToEncryptSize % 16) === 0 ?
0 : 16 - (messageToEncryptSize % 16);
return BC.concat(
BC.fromInt(enc.publicKey.length), // key
BC.fromInt(m2.length), // mac
BC.fromInt(messageToEncryptSize, 2).switchEndian(), // orig
BC.fromInt(messageToEncryptSize + messageToEncryptPadSize, 2).switchEndian(), // body
enc.publicKey, // key itself
m2,
enc.data
);
}
}
module.exports = Payload;
|