ADD cipher.stringify and ciper.parse

pull/15/head
pubkey 7 years ago
parent 5497c33e5c
commit 28ef384bfe
  1. 30
      README.md
  2. 41
      src/cipher.js
  3. 10
      src/decrypt-with-private-key.js
  4. 3
      src/index.js
  5. 5
      test/tutorials/encrypted-message.test.js
  6. 66
      test/unit.test.js
  7. 12
      tutorials/encrypted-message.md
  8. 6
      typings/index.d.ts

@ -52,6 +52,8 @@ const EthCrypto = require('eth-crypto');
- [recoverPublicKey()](#recoverpublickey)
- [encryptWithPublicKey()](#encryptwithpublickey)
- [decryptWithPrivateKey()](#decryptwithprivatekey)
- [cipher.stringify()](#cipherstringify)
- [cipher.parse()](#cipherparse)
- [signTransaction()](#signtransaction)
- [txDataByCompiled()](#txdatabycompiled)
- [calculateContractAddress()](#calculatecontractaddress)
@ -185,6 +187,34 @@ Decrypts the encrypted data with the privateKey. Returns (async) the message as
// 'foobar'
```
### cipher.stringify()
Transforms the object with the encrypted data into a smaller string-representation.
```javascript
const str = EthCrypto.cipher.stringify({
iv: '02aeac54cb45283b427bd1a5028552c1',
ephemPublicKey: '044acf39ed83c304f19f41ea66615d7a6c0068d5fc48ee181f2fb1091...',
ciphertext: '5fbbcc1a44ee19f7499dbc39cfc4ce96',
mac: '96490b293763f49a371d3a2040a2d2cb57f246ee88958009fe3c7ef2a38264a1'
});
// > '59ab06532fc965b0107977f43e69e5a4038db32099dab281c8f5aece2852...'
```
### cipher.parse()
Parses the string-representation back into the encrypted object.
```javascript
const str = EthCrypto.cipher.parse('59ab06532fc965b0107977f43e69e5a4038db32099dab281c8f5aece2852...');
/* > {
iv: '02aeac54cb45283b427bd1a5028552c1',
ephemPublicKey: '044acf39ed83c304f19f41ea66615d7a6c0068d5fc48ee181f2fb1091...',
ciphertext: '5fbbcc1a44ee19f7499dbc39cfc4ce96',
mac: '96490b293763f49a371d3a2040a2d2cb57f246ee88958009fe3c7ef2a38264a1'
} */
```
### signTransaction()
Signs a raw transaction with the privateKey. Returns a serialized tx which can be submitted to the node.

@ -0,0 +1,41 @@
import {
compress,
decompress
} from './public-key';
export function stringify(cipher) {
if (typeof cipher === 'string') return cipher;
// use compressed key because it's smaller
const compressedKey = compress(cipher.ephemPublicKey);
const ret = Buffer.concat([
new Buffer(cipher.iv, 'hex'), // 16bit
new Buffer(compressedKey, 'hex'), // 33bit
new Buffer(cipher.mac, 'hex'), // 32bit
new Buffer(cipher.ciphertext, 'hex') // var bit
]);
return ret.toString('hex');
}
export function parse(str) {
if (typeof str !== 'string')
return str;
const buf = new Buffer(str, 'hex');
const ret = {
iv: buf.toString('hex', 0, 16),
ephemPublicKey: buf.toString('hex', 16, 49),
mac: buf.toString('hex', 49, 81),
ciphertext: buf.toString('hex', 81, buf.length)
};
// decompress publicKey
ret.ephemPublicKey = '04' + decompress(ret.ephemPublicKey);
return ret;
}

@ -1,9 +1,17 @@
import eccrypto from 'eccrypto';
import {
parse
} from './cipher';
import {
removeTrailing0x
} from './util';
export default async function decryptWithPrivateKey(privateKey, encrypted) {
encrypted = parse(encrypted);
// remove trailing '0x' from privateKey
const twoStripped = privateKey.replace(/^.{2}/g, '');
const twoStripped = removeTrailing0x(privateKey);
const encryptedBuffer = {
iv: new Buffer(encrypted.iv, 'hex'),

@ -3,6 +3,7 @@ import createIdentity from './create-identity';
import * as publicKey from './public-key';
import decryptWithPrivateKey from './decrypt-with-private-key';
import encryptWithPublicKey from './encrypt-with-public-key';
import * as cipher from './cipher';
import publicKeyByPrivateKey from './public-key-by-private-key';
import recover from './recover';
import recoverPublicKey from './recover-public-key';
@ -20,6 +21,7 @@ export {
publicKey,
decryptWithPrivateKey,
encryptWithPublicKey,
cipher,
publicKeyByPrivateKey,
recover,
recoverPublicKey,
@ -38,6 +40,7 @@ export default {
publicKey,
decryptWithPrivateKey,
encryptWithPublicKey,
cipher,
publicKeyByPrivateKey,
recover,
recoverPublicKey,

@ -27,10 +27,13 @@ describe('encrypted-message.md', () => {
// console.log('encrypted:');
// console.dir(encrypted);
const encryptedString = EthCrypto.cipher.stringify(encrypted);
// decrypt
const encryptedObject = EthCrypto.cipher.parse(encryptedString);
const decrypted = await EthCrypto.decryptWithPrivateKey(
bob.privateKey,
encrypted
encryptedObject
);
const decryptedPayload = JSON.parse(decrypted);

@ -149,9 +149,75 @@ describe('unit.test.js', () => {
);
assert.equal(decrypted, message);
});
it('should also decrypt with stringified data', async()=>{
const message = AsyncTestUtil.randomString(12);
const encrypted = await EthCrypto.encryptWithPublicKey(
TEST_DATA.publicKey,
message
);
const encryptedString = EthCrypto.cipher.stringify(encrypted);
const decrypted = await EthCrypto.decryptWithPrivateKey(
TEST_DATA.privateKey,
encryptedString
);
assert.equal(decrypted, message);
});
});
describe('negative', () => {});
});
describe('.cipher', () => {
describe('.stringify()', () => {
it('should stringify the cipher', async () => {
const ident = EthCrypto.createIdentity();
const message = AsyncTestUtil.randomString(12);
const cipher = await EthCrypto.encryptWithPublicKey(
ident.publicKey,
message
);
const str = EthCrypto.cipher.stringify(cipher);
assert.equal(typeof str, 'string');
});
it('should not stringify the string', async () => {
const ident = EthCrypto.createIdentity();
const message = AsyncTestUtil.randomString(12);
const cipher = await EthCrypto.encryptWithPublicKey(
ident.publicKey,
message
);
const str = EthCrypto.cipher.stringify(cipher);
const str2 = EthCrypto.cipher.stringify(str);
assert.equal(str, str2);
});
});
describe('.parse()', () => {
it('should parse the equal object', async () => {
const ident = EthCrypto.createIdentity();
const message = AsyncTestUtil.randomString(12);
const cipher = await EthCrypto.encryptWithPublicKey(
ident.publicKey,
message
);
const str = EthCrypto.cipher.stringify(cipher);
const cipher2 = EthCrypto.cipher.parse(str);
assert.deepEqual(cipher, cipher2);
});
it('should also work with different message-length', async () => {
const ident = EthCrypto.createIdentity();
const message = AsyncTestUtil.randomString(120);
const cipher = await EthCrypto.encryptWithPublicKey(
ident.publicKey,
message
);
const str = EthCrypto.cipher.stringify(cipher);
const cipher2 = EthCrypto.cipher.parse(str);
assert.deepEqual(cipher, cipher2);
});
});
});
describe('.publicKey', () => {
describe('.compress()', () => {
it('should compress the key', () => {

@ -43,7 +43,11 @@ const encrypted = await EthCrypto.encryptWithPublicKey(
}
*/
// now we send the encrypted object to bob over the internet.. *bieb, bieb, blob*
// we convert the object into a smaller string-representation
const encryptedString = EthCrypto.cipher.stringify(encrypted);
// > '812ee676cf06ba72316862fd3dabe7e403c7395bda62243b7b0eea5eb..'
// now we send the encrypted string to bob over the internet.. *bieb, bieb, blob*
```
## Decrypt and verify the payload
@ -51,9 +55,13 @@ const encrypted = await EthCrypto.encryptWithPublicKey(
When bob receives the message, he starts with decrypting it with his privateKey and then verifies the signature.
```javascript
// we parse the string into the object again
const encryptedObject = EthCrypto.cipher.parse(encryptedString);
const decrypted = await EthCrypto.decryptWithPrivateKey(
bob.privateKey,
encrypted
encryptedObject
);
const decryptedPayload = JSON.parse(decrypted);

@ -49,6 +49,11 @@ export type vrs = {
export function encryptWithPublicKey(publicKey: string, message: string): Promise<Encrypted>;
export function decryptWithPrivateKey(privateKey: string, encrypted: Encrypted): Promise<string>;
export type cipher = {
stringify(encrypted: Encrypted): string;
parse(encrypted: string): Encrypted;
};
export function signTransaction(
rawTx: RawTx,
privateKey: string
@ -93,6 +98,7 @@ declare const _default: {
publicKey,
decryptWithPrivateKey,
encryptWithPublicKey,
cipher,
publicKeyByPrivateKey,
recover,
recoverPublicKey,

Loading…
Cancel
Save