UNPKG

ethereum-encryption

Version:

Use this to encrypt, decrypt, sign and verify data with an ethereum public- or privateKey

145 lines (108 loc) 4.12 kB
/** * copied from bitcore-ecies * https://github.com/bitpay/bitcore-ecies */ import { util as bitcoreUtil } from 'bitcore-lib'; const $ = bitcoreUtil.preconditions; import errors from './errors'; // Cipher Block Chaining // http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29 const CBC = function CBC(blockcipher, cipherkeybuf, ivbuf) { if (!(this instanceof CBC)) return new CBC(blockcipher, cipherkeybuf, ivbuf); this.blockcipher = blockcipher; this.cipherkeybuf = cipherkeybuf; this.ivbuf = ivbuf; }; CBC.buf2blockbufs = function(buf, blocksize) { const bytesize = blocksize / 8; const blockbufs = []; for (let i = 0; i <= buf.length / bytesize; i++) { let blockbuf = buf.slice(i * bytesize, i * bytesize + bytesize); if (blockbuf.length < blocksize) blockbuf = CBC.pkcs7pad(blockbuf, blocksize); blockbufs.push(blockbuf); } return blockbufs; }; CBC.blockbufs2buf = function(blockbufs) { let last = blockbufs[blockbufs.length - 1]; last = CBC.pkcs7unpad(last); blockbufs[blockbufs.length - 1] = last; const buf = Buffer.concat(blockbufs); return buf; }; CBC.encrypt = function(messagebuf, ivbuf, blockcipher, cipherkeybuf) { const blocksize = ivbuf.length * 8; const blockbufs = CBC.buf2blockbufs(messagebuf, blocksize); const encbufs = CBC.encryptblocks(blockbufs, ivbuf, blockcipher, cipherkeybuf); const encbuf = Buffer.concat(encbufs); return encbuf; }; CBC.decrypt = function(encbuf, ivbuf, blockcipher, cipherkeybuf) { const blocksize = ivbuf.length * 8; const bytesize = ivbuf.length; const encbufs = []; for (let i = 0; i < encbuf.length / bytesize; i++) encbufs.push(encbuf.slice(i * bytesize, i * bytesize + bytesize)); const blockbufs = CBC.decryptblocks(encbufs, ivbuf, blockcipher, cipherkeybuf); const buf = CBC.blockbufs2buf(blockbufs, blocksize); return buf; }; CBC.encryptblock = function(blockbuf, ivbuf, blockcipher, cipherkeybuf) { const xorbuf = CBC.xorbufs(blockbuf, ivbuf); const encbuf = blockcipher.encrypt(xorbuf, cipherkeybuf); return encbuf; }; CBC.decryptblock = function(encbuf, ivbuf, blockcipher, cipherkeybuf) { const xorbuf = blockcipher.decrypt(encbuf, cipherkeybuf); const blockbuf = CBC.xorbufs(xorbuf, ivbuf); return blockbuf; }; CBC.encryptblocks = function(blockbufs, ivbuf, blockcipher, cipherkeybuf) { const encbufs = []; for (let i = 0; i < blockbufs.length; i++) { let blockbuf = blockbufs[i]; let encbuf = CBC.encryptblock(blockbuf, ivbuf, blockcipher, cipherkeybuf); encbufs.push(encbuf); ivbuf = encbuf; } return encbufs; }; CBC.decryptblocks = function(encbufs, ivbuf, blockcipher, cipherkeybuf) { const blockbufs = []; for (let i = 0; i < encbufs.length; i++) { let encbuf = encbufs[i]; let blockbuf = CBC.decryptblock(encbuf, ivbuf, blockcipher, cipherkeybuf); blockbufs.push(blockbuf); ivbuf = encbuf; } return blockbufs; }; CBC.pkcs7pad = function(buf, blocksize) { const bytesize = blocksize / 8; const padbytesize = bytesize - buf.length; const pad = new Buffer(padbytesize); pad.fill(padbytesize); const paddedbuf = Buffer.concat([buf, pad]); return paddedbuf; }; CBC.pkcs7unpad = function(paddedbuf) { const padlength = paddedbuf[paddedbuf.length - 1]; const padbuf = paddedbuf.slice(paddedbuf.length - padlength, paddedbuf.length); const padbuf2 = new Buffer(padlength); padbuf2.fill(padlength); if (padbuf.toString('hex') !== padbuf2.toString('hex')) throw new errors.InvalidPadding(padbuf.toString()); return paddedbuf.slice(0, paddedbuf.length - padlength); }; CBC.xorbufs = function(buf1, buf2) { $.checkArgument(buf1.length === buf2.length, 'bufs must have the same length'); const buf = new Buffer(buf1.length); for (let i = 0; i < buf1.length; i++) buf[i] = buf1[i] ^ buf2[i]; return buf; }; export default CBC;