@hiveio/dhive 1.2.5 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dhive.d.ts +9 -34
- package/dist/dhive.js +1 -1
- package/dist/dhive.js.gz +0 -0
- package/dist/dhive.js.map +1 -1
- package/lib/chain/deserializer.d.ts +1 -2
- package/lib/chain/serializer.d.ts +2 -2
- package/lib/chain/serializer.js +42 -8
- package/lib/client.d.ts +1 -1
- package/lib/crypto.js +1 -1
- package/lib/helpers/aes.d.ts +3 -25
- package/lib/helpers/aes.js +29 -63
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/memo.d.ts +2 -17
- package/lib/memo.js +50 -23
- package/lib/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
/**
|
|
3
2
|
* @file Hive protocol serialization.
|
|
4
3
|
* @author Johan Nordberg <code@johan-nordberg.com>
|
|
@@ -33,6 +32,7 @@
|
|
|
33
32
|
* You acknowledge that this software is not designed, licensed or intended for use
|
|
34
33
|
* in the design, construction, operation or maintenance of any military facility.
|
|
35
34
|
*/
|
|
35
|
+
/// <reference types="node" />
|
|
36
36
|
import * as ByteBuffer from 'bytebuffer';
|
|
37
37
|
import { PublicKey } from '../crypto';
|
|
38
38
|
import { Asset } from './asset';
|
|
@@ -74,5 +74,5 @@ export declare const Types: {
|
|
|
74
74
|
UInt32: (buffer: ByteBuffer, data: number) => void;
|
|
75
75
|
UInt64: (buffer: ByteBuffer, data: number) => void;
|
|
76
76
|
UInt8: (buffer: ByteBuffer, data: number) => void;
|
|
77
|
-
Void: () => never;
|
|
77
|
+
Void: (buffer: ByteBuffer) => never;
|
|
78
78
|
};
|
package/lib/chain/serializer.js
CHANGED
|
@@ -1,9 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file Hive protocol serialization.
|
|
4
|
+
* @author Johan Nordberg <code@johan-nordberg.com>
|
|
5
|
+
* @license
|
|
6
|
+
* Copyright (c) 2017 Johan Nordberg. All Rights Reserved.
|
|
7
|
+
*
|
|
8
|
+
* Redistribution and use in source and binary forms, with or without modification,
|
|
9
|
+
* are permitted provided that the following conditions are met:
|
|
10
|
+
*
|
|
11
|
+
* 1. Redistribution of source code must retain the above copyright notice, this
|
|
12
|
+
* list of conditions and the following disclaimer.
|
|
13
|
+
*
|
|
14
|
+
* 2. Redistribution in binary form must reproduce the above copyright notice,
|
|
15
|
+
* this list of conditions and the following disclaimer in the documentation
|
|
16
|
+
* and/or other materials provided with the distribution.
|
|
17
|
+
*
|
|
18
|
+
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
19
|
+
* may be used to endorse or promote products derived from this software without
|
|
20
|
+
* specific prior written permission.
|
|
21
|
+
*
|
|
22
|
+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
23
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
24
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
25
|
+
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
26
|
+
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
27
|
+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
28
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
29
|
+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
30
|
+
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
31
|
+
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
|
+
*
|
|
33
|
+
* You acknowledge that this software is not designed, licensed or intended for use
|
|
34
|
+
* in the design, construction, operation or maintenance of any military facility.
|
|
35
|
+
*/
|
|
2
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
37
|
const crypto_1 = require("../crypto");
|
|
4
38
|
const asset_1 = require("./asset");
|
|
5
39
|
const misc_1 = require("./misc");
|
|
6
|
-
const VoidSerializer = () => {
|
|
40
|
+
const VoidSerializer = (buffer) => {
|
|
7
41
|
throw new Error('Void can not be serialized');
|
|
8
42
|
};
|
|
9
43
|
const StringSerializer = (buffer, data) => {
|
|
@@ -144,13 +178,6 @@ const ChainPropertiesSerializer = ObjectSerializer([
|
|
|
144
178
|
['maximum_block_size', UInt32Serializer],
|
|
145
179
|
['hbd_interest_rate', UInt16Serializer]
|
|
146
180
|
]);
|
|
147
|
-
const EncryptedMemoSerializer = ObjectSerializer([
|
|
148
|
-
['from', PublicKeySerializer],
|
|
149
|
-
['to', PublicKeySerializer],
|
|
150
|
-
['nonce', UInt64Serializer],
|
|
151
|
-
['check', UInt32Serializer],
|
|
152
|
-
['encrypted', BinarySerializer()]
|
|
153
|
-
]);
|
|
154
181
|
const OperationDataSerializer = (operationId, definitions) => {
|
|
155
182
|
const objectSerializer = ObjectSerializer(definitions);
|
|
156
183
|
return (buffer, data) => {
|
|
@@ -503,6 +530,13 @@ const TransactionSerializer = ObjectSerializer([
|
|
|
503
530
|
['operations', ArraySerializer(OperationSerializer)],
|
|
504
531
|
['extensions', ArraySerializer(StringSerializer)]
|
|
505
532
|
]);
|
|
533
|
+
const EncryptedMemoSerializer = ObjectSerializer([
|
|
534
|
+
['from', PublicKeySerializer],
|
|
535
|
+
['to', PublicKeySerializer],
|
|
536
|
+
['nonce', UInt64Serializer],
|
|
537
|
+
['check', UInt32Serializer],
|
|
538
|
+
['encrypted', BinarySerializer()]
|
|
539
|
+
]);
|
|
506
540
|
exports.Types = {
|
|
507
541
|
Array: ArraySerializer,
|
|
508
542
|
Asset: AssetSerializer,
|
package/lib/client.d.ts
CHANGED
|
@@ -154,11 +154,11 @@ export declare class Client {
|
|
|
154
154
|
* Address prefix for current network.
|
|
155
155
|
*/
|
|
156
156
|
readonly addressPrefix: string;
|
|
157
|
-
currentAddress: string;
|
|
158
157
|
private timeout;
|
|
159
158
|
private backoff;
|
|
160
159
|
private failoverThreshold;
|
|
161
160
|
private consoleOnFailover;
|
|
161
|
+
currentAddress: string;
|
|
162
162
|
/**
|
|
163
163
|
* @param address The address to the Hive RPC server,
|
|
164
164
|
* e.g. `https://api.hive.blog`. or [`https://api.hive.blog`, `https://another.api.com`]
|
package/lib/crypto.js
CHANGED
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
*/
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
const assert = require("assert");
|
|
38
|
+
const crypto_1 = require("crypto");
|
|
38
39
|
const bigInteger = require("bigi");
|
|
39
40
|
const bs58 = require("bs58");
|
|
40
41
|
const ByteBuffer = require("bytebuffer");
|
|
41
|
-
const crypto_1 = require("crypto");
|
|
42
42
|
const ecurve = require("ecurve");
|
|
43
43
|
const Ripemd160 = require("ripemd160");
|
|
44
44
|
const secp256k1 = require("secp256k1");
|
package/lib/helpers/aes.d.ts
CHANGED
|
@@ -1,26 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { PrivateKey, PublicKey } from '../crypto';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* @throws {Error|TypeError} - "Invalid Key, ..."
|
|
5
|
-
* @param {PrivateKey} private_key - required and used for decryption
|
|
6
|
-
* @param {PublicKey} public_key - required and used to calcualte the shared secret
|
|
7
|
-
* @param message - message to be encrypted
|
|
8
|
-
* @param {string} [nonce = uniqueNonce()] - assigned a random unique uint64
|
|
9
|
-
*
|
|
10
|
-
* @return {object}
|
|
11
|
-
* @property {string} nonce - random or unique uint64, provides entropy when re-using the same private/public keys.
|
|
12
|
-
* @property {Buffer} message - Plain text message
|
|
13
|
-
* @property {number} checksum - shared secret checksum
|
|
14
|
-
*/
|
|
15
|
-
export declare function encrypt(private_key: PrivateKey, public_key: PublicKey, message: any, nonce: any): any;
|
|
16
|
-
/**
|
|
17
|
-
* Spec: http://peakd.com/steem/@dantheman/how-to-encrypt-a-memo-when-transferring-steem
|
|
18
|
-
* @arg {PrivateKey} private_key - required and used for decryption
|
|
19
|
-
* @arg {PublicKey} public_key - required and used to calcualte the shared secret
|
|
20
|
-
* @arg {string} nonce - random or unique uint64, provides entropy when re-using the same private/public keys.
|
|
21
|
-
* @arg {Buffer} message - Encrypted or plain text message
|
|
22
|
-
* @arg {number} checksum - shared secret checksum
|
|
23
|
-
* @throws {Error|TypeError} - "Invalid Key, ..."
|
|
24
|
-
* @return {Buffer} - message
|
|
25
|
-
*/
|
|
26
|
-
export declare function decrypt(private_key: PrivateKey, public_key: PublicKey, nonce: any, message: any, checksum: number): string;
|
|
3
|
+
export declare const encrypt: (private_key: PrivateKey, public_key: PublicKey, message: Buffer, nonce?: string) => any;
|
|
4
|
+
export declare const decrypt: (private_key: PrivateKey, public_key: PublicKey, nonce: any, message: any, checksum: number) => any;
|
package/lib/helpers/aes.js
CHANGED
|
@@ -4,113 +4,79 @@ const assert = require("assert");
|
|
|
4
4
|
const crypto_1 = require("crypto");
|
|
5
5
|
const ByteBuffer = require('bytebuffer');
|
|
6
6
|
const Long = ByteBuffer.Long;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* @throws {Error|TypeError} - "Invalid Key, ..."
|
|
10
|
-
* @param {PrivateKey} private_key - required and used for decryption
|
|
11
|
-
* @param {PublicKey} public_key - required and used to calcualte the shared secret
|
|
12
|
-
* @param message - message to be encrypted
|
|
13
|
-
* @param {string} [nonce = uniqueNonce()] - assigned a random unique uint64
|
|
14
|
-
*
|
|
15
|
-
* @return {object}
|
|
16
|
-
* @property {string} nonce - random or unique uint64, provides entropy when re-using the same private/public keys.
|
|
17
|
-
* @property {Buffer} message - Plain text message
|
|
18
|
-
* @property {number} checksum - shared secret checksum
|
|
19
|
-
*/
|
|
20
|
-
function encrypt(private_key, public_key, message, nonce) {
|
|
21
|
-
// Change message to varint32 prefixed encoded string
|
|
22
|
-
const mbuf = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
23
|
-
mbuf.writeVString(message);
|
|
24
|
-
message = Buffer.from(mbuf.flip().toBinary());
|
|
25
|
-
return crypt(private_key, public_key, uniqueNonce(), message);
|
|
26
|
-
}
|
|
27
|
-
exports.encrypt = encrypt;
|
|
28
|
-
/**
|
|
29
|
-
* Spec: http://peakd.com/steem/@dantheman/how-to-encrypt-a-memo-when-transferring-steem
|
|
30
|
-
* @arg {PrivateKey} private_key - required and used for decryption
|
|
31
|
-
* @arg {PublicKey} public_key - required and used to calcualte the shared secret
|
|
32
|
-
* @arg {string} nonce - random or unique uint64, provides entropy when re-using the same private/public keys.
|
|
33
|
-
* @arg {Buffer} message - Encrypted or plain text message
|
|
34
|
-
* @arg {number} checksum - shared secret checksum
|
|
35
|
-
* @throws {Error|TypeError} - "Invalid Key, ..."
|
|
36
|
-
* @return {Buffer} - message
|
|
37
|
-
*/
|
|
38
|
-
function decrypt(private_key, public_key, nonce, message, checksum) {
|
|
39
|
-
return crypt(private_key, public_key, nonce, message, checksum).message;
|
|
40
|
-
}
|
|
41
|
-
exports.decrypt = decrypt;
|
|
7
|
+
exports.encrypt = (private_key, public_key, message, nonce = uniqueNonce()) => crypt(private_key, public_key, nonce, message);
|
|
8
|
+
exports.decrypt = (private_key, public_key, nonce, message, checksum) => crypt(private_key, public_key, nonce, message, checksum).message;
|
|
42
9
|
/**
|
|
43
10
|
* @arg {Buffer} message - Encrypted or plain text message (see checksum)
|
|
44
11
|
* @arg {number} checksum - shared secret checksum (null to encrypt, non-null to decrypt)
|
|
45
12
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
//
|
|
13
|
+
const crypt = (private_key, public_key, nonce, message, checksum) => {
|
|
14
|
+
const nonceL = toLongObj(nonce);
|
|
15
|
+
// const bufferMessage = Buffer.from(messageString, 'binary')
|
|
49
16
|
const S = private_key.get_shared_secret(public_key);
|
|
50
17
|
let ebuf = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
51
|
-
ebuf.writeUint64(
|
|
18
|
+
ebuf.writeUint64(nonceL);
|
|
52
19
|
ebuf.append(S.toString('binary'), 'binary');
|
|
53
20
|
ebuf = Buffer.from(ebuf.copy(0, ebuf.offset).toBinary(), 'binary');
|
|
54
21
|
const encryption_key = crypto_1.createHash('sha512').update(ebuf).digest();
|
|
55
22
|
const iv = encryption_key.slice(32, 48);
|
|
56
23
|
const tag = encryption_key.slice(0, 32);
|
|
57
24
|
// check if first 64 bit of sha256 hash treated as uint64_t truncated to 32 bits.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
25
|
+
const check = crypto_1.createHash('sha256').update(encryption_key).digest().slice(0, 4);
|
|
26
|
+
const cbuf = ByteBuffer.fromBinary(check.toString('binary'), ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
27
|
+
ByteBuffer.fromBinary(check.toString('binary'), ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
28
|
+
const check32 = cbuf.readUint32();
|
|
62
29
|
if (checksum) {
|
|
63
|
-
if (
|
|
64
|
-
throw new Error('Invalid
|
|
30
|
+
if (check32 !== checksum) {
|
|
31
|
+
throw new Error('Invalid key');
|
|
65
32
|
}
|
|
66
33
|
message = cryptoJsDecrypt(message, tag, iv);
|
|
67
34
|
}
|
|
68
35
|
else {
|
|
69
36
|
message = cryptoJsEncrypt(message, tag, iv);
|
|
70
37
|
}
|
|
71
|
-
return { nonce, message, checksum:
|
|
72
|
-
}
|
|
38
|
+
return { nonce: nonceL, message, checksum: check32 };
|
|
39
|
+
};
|
|
73
40
|
/**
|
|
74
41
|
* This method does not use a checksum, the returned data must be validated some other way.
|
|
75
42
|
* @arg {string|Buffer} ciphertext - binary format
|
|
76
43
|
* @return {Buffer} the decrypted message
|
|
77
44
|
*/
|
|
78
|
-
|
|
45
|
+
const cryptoJsDecrypt = (message, tag, iv) => {
|
|
79
46
|
assert(message, 'Missing cipher text');
|
|
80
|
-
|
|
47
|
+
let messageBuffer = message;
|
|
81
48
|
const decipher = crypto_1.createDecipheriv('aes-256-cbc', tag, iv);
|
|
82
|
-
|
|
83
|
-
return
|
|
84
|
-
}
|
|
49
|
+
messageBuffer = Buffer.concat([decipher.update(messageBuffer), decipher.final()]);
|
|
50
|
+
return messageBuffer;
|
|
51
|
+
};
|
|
85
52
|
/**
|
|
86
53
|
* This method does not use a checksum, the returned data must be validated some other way.
|
|
87
54
|
* @arg {string|Buffer} plaintext - binary format
|
|
88
55
|
* @return {Buffer} binary
|
|
89
56
|
*/
|
|
90
|
-
|
|
57
|
+
const cryptoJsEncrypt = (message, tag, iv) => {
|
|
91
58
|
assert(message, 'Missing plain text');
|
|
92
|
-
|
|
59
|
+
let messageBuffer = message;
|
|
93
60
|
const cipher = crypto_1.createCipheriv('aes-256-cbc', tag, iv);
|
|
94
|
-
|
|
95
|
-
return
|
|
96
|
-
}
|
|
61
|
+
messageBuffer = Buffer.concat([cipher.update(messageBuffer), cipher.final()]);
|
|
62
|
+
return messageBuffer;
|
|
63
|
+
};
|
|
97
64
|
/** @return {string} unique 64 bit unsigned number string. Being time based,
|
|
98
65
|
* this is careful to never choose the same nonce twice. This value could
|
|
99
66
|
* clsbe recorded in the blockchain for a long time.
|
|
100
67
|
*/
|
|
101
68
|
let unique_nonce_entropy = null;
|
|
102
|
-
|
|
69
|
+
const uniqueNonce = () => {
|
|
103
70
|
if (unique_nonce_entropy === null) {
|
|
104
71
|
const uint8randomArr = new Uint8Array(2);
|
|
105
72
|
for (let i = 0; i < 2; ++i) {
|
|
106
73
|
uint8randomArr[i] = crypto_1.randomBytes(2).readUInt8(i);
|
|
107
74
|
}
|
|
108
|
-
unique_nonce_entropy = uint8randomArr[0] << 8 | uint8randomArr[1];
|
|
75
|
+
unique_nonce_entropy = Math.round((uint8randomArr[0] << 8) | uint8randomArr[1]);
|
|
109
76
|
}
|
|
110
77
|
let long = Long.fromNumber(Date.now());
|
|
111
|
-
const entropy = ++unique_nonce_entropy %
|
|
78
|
+
const entropy = ++unique_nonce_entropy % 0xffff;
|
|
112
79
|
long = long.shiftLeft(16).or(Long.fromNumber(entropy));
|
|
113
80
|
return long.toString();
|
|
114
|
-
}
|
|
115
|
-
const toLongObj = o => (o ? Long.isLong(o) ? o : Long.fromString(o) : o);
|
|
116
|
-
const toBinaryBuffer = o => (o ? Buffer.isBuffer(o) ? o : Buffer.from(o, 'binary') : o);
|
|
81
|
+
};
|
|
82
|
+
const toLongObj = (o) => (o ? (Long.isLong(o) ? o : Long.fromString(o)) : o);
|
package/lib/index.d.ts
CHANGED
|
@@ -46,7 +46,6 @@ export * from './chain/comment';
|
|
|
46
46
|
export * from './chain/misc';
|
|
47
47
|
export * from './chain/operation';
|
|
48
48
|
export * from './chain/serializer';
|
|
49
|
-
export * from './chain/deserializer';
|
|
50
49
|
export * from './chain/transaction';
|
|
51
50
|
export * from './chain/hivemind';
|
|
52
51
|
export * from './client';
|
package/lib/index.js
CHANGED
|
@@ -48,7 +48,6 @@ __export(require("./chain/account"));
|
|
|
48
48
|
__export(require("./chain/asset"));
|
|
49
49
|
__export(require("./chain/misc"));
|
|
50
50
|
__export(require("./chain/serializer"));
|
|
51
|
-
__export(require("./chain/deserializer"));
|
|
52
51
|
__export(require("./client"));
|
|
53
52
|
__export(require("./crypto"));
|
|
54
53
|
__export(require("./memo"));
|
package/lib/memo.d.ts
CHANGED
|
@@ -1,20 +1,5 @@
|
|
|
1
1
|
import { PrivateKey, PublicKey } from './crypto';
|
|
2
|
-
/**
|
|
3
|
-
* Memo/Any message encoding using AES (aes-cbc algorithm)
|
|
4
|
-
* @param {Buffer|String} private_key Privatekey of sender
|
|
5
|
-
* @param {Buffer|String}public_key publickey of recipient
|
|
6
|
-
* @param {String}memo message to be encrypted
|
|
7
|
-
* @param {Number}testNonce nonce with high entropy
|
|
8
|
-
*/
|
|
9
|
-
declare function encode(private_key: PrivateKey | string, public_key: PublicKey | string, memo: string, testNonce?: number): string;
|
|
10
|
-
/**
|
|
11
|
-
* Encrypted memo/message decryption
|
|
12
|
-
* @param {Buffer|string}private_key Privatekey of recipient
|
|
13
|
-
* @param {any}memo Encrypted message/memo
|
|
14
|
-
*/
|
|
15
|
-
declare function decode(private_key: PrivateKey | string, memo: any): any;
|
|
16
2
|
export declare const Memo: {
|
|
17
|
-
decode:
|
|
18
|
-
encode:
|
|
3
|
+
decode: (private_key: string | PrivateKey, memo: string) => string;
|
|
4
|
+
encode: (private_key: string | PrivateKey, public_key: string | PublicKey, memo: string, testNonce?: string | undefined) => string;
|
|
19
5
|
};
|
|
20
|
-
export {};
|
package/lib/memo.js
CHANGED
|
@@ -8,51 +8,56 @@ const crypto_1 = require("./crypto");
|
|
|
8
8
|
const Aes = require("./helpers/aes");
|
|
9
9
|
/**
|
|
10
10
|
* Memo/Any message encoding using AES (aes-cbc algorithm)
|
|
11
|
-
* @param {Buffer|
|
|
12
|
-
* @param {Buffer|
|
|
13
|
-
* @param {
|
|
14
|
-
* @param {
|
|
11
|
+
* @param {Buffer|string} private_key Private memo key of sender
|
|
12
|
+
* @param {Buffer|string} public_key public memo key of recipient
|
|
13
|
+
* @param {string} memo message to be encrypted
|
|
14
|
+
* @param {number} testNonce nonce with high entropy
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
const encode = (private_key, public_key, memo, testNonce) => {
|
|
17
17
|
if (!memo.startsWith('#')) {
|
|
18
18
|
return memo;
|
|
19
19
|
}
|
|
20
20
|
memo = memo.substring(1);
|
|
21
|
+
checkEncryption();
|
|
21
22
|
private_key = toPrivateObj(private_key);
|
|
22
23
|
public_key = toPublicObj(public_key);
|
|
23
|
-
const { nonce, message, checksum } = Aes.encrypt(private_key, public_key, memo, testNonce);
|
|
24
24
|
const mbuf = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
25
|
-
|
|
25
|
+
mbuf.writeVString(memo);
|
|
26
|
+
const memoBuffer = Buffer.from(mbuf.copy(0, mbuf.offset).toBinary(), 'binary');
|
|
27
|
+
const { nonce, message, checksum } = Aes.encrypt(private_key, public_key, memoBuffer, testNonce);
|
|
28
|
+
const mbuf2 = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN);
|
|
29
|
+
serializer_1.Types.EncryptedMemo(mbuf2, {
|
|
26
30
|
check: checksum,
|
|
27
31
|
encrypted: message,
|
|
28
32
|
from: private_key.createPublic(),
|
|
29
33
|
nonce,
|
|
30
34
|
to: public_key
|
|
31
35
|
});
|
|
32
|
-
|
|
33
|
-
const data = Buffer.from(
|
|
36
|
+
mbuf2.flip();
|
|
37
|
+
const data = Buffer.from(mbuf2.toBuffer());
|
|
34
38
|
return '#' + bs58.encode(data);
|
|
35
|
-
}
|
|
39
|
+
};
|
|
36
40
|
/**
|
|
37
41
|
* Encrypted memo/message decryption
|
|
38
|
-
* @param {
|
|
39
|
-
* @param {
|
|
42
|
+
* @param {PrivateKey|string} private_key Private memo key of recipient
|
|
43
|
+
* @param {string}memo Encrypted message/memo
|
|
40
44
|
*/
|
|
41
|
-
|
|
45
|
+
const decode = (private_key, memo) => {
|
|
42
46
|
if (!memo.startsWith('#')) {
|
|
43
47
|
return memo;
|
|
44
48
|
}
|
|
45
49
|
memo = memo.substring(1);
|
|
46
|
-
|
|
50
|
+
checkEncryption();
|
|
47
51
|
private_key = toPrivateObj(private_key);
|
|
48
52
|
memo = bs58.decode(memo);
|
|
49
|
-
|
|
50
|
-
const { from, to, nonce, check, encrypted } =
|
|
53
|
+
let memoBuffer = deserializer_1.types.EncryptedMemoD(Buffer.from(memo, 'binary'));
|
|
54
|
+
const { from, to, nonce, check, encrypted } = memoBuffer;
|
|
51
55
|
const pubkey = private_key.createPublic().toString();
|
|
52
|
-
const otherpub = pubkey === new crypto_1.PublicKey(from.key).toString()
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
const otherpub = pubkey === new crypto_1.PublicKey(from.key).toString()
|
|
57
|
+
? new crypto_1.PublicKey(to.key)
|
|
58
|
+
: new crypto_1.PublicKey(from.key);
|
|
59
|
+
memoBuffer = Aes.decrypt(private_key, otherpub, nonce, encrypted, check);
|
|
60
|
+
const mbuf = ByteBuffer.fromBinary(memoBuffer.toString('binary'), ByteBuffer.LITTLE_ENDIAN);
|
|
56
61
|
try {
|
|
57
62
|
mbuf.mark();
|
|
58
63
|
return '#' + mbuf.readVString();
|
|
@@ -63,9 +68,31 @@ function decode(private_key, memo) {
|
|
|
63
68
|
memo = Buffer.from(mbuf.toString('binary'), 'binary').toString('utf-8');
|
|
64
69
|
return '#' + memo;
|
|
65
70
|
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const
|
|
71
|
+
};
|
|
72
|
+
let encodeTest;
|
|
73
|
+
const checkEncryption = () => {
|
|
74
|
+
if (encodeTest === undefined) {
|
|
75
|
+
let plaintext;
|
|
76
|
+
encodeTest = true; // prevent infinate looping
|
|
77
|
+
try {
|
|
78
|
+
const wif = '5JdeC9P7Pbd1uGdFVEsJ41EkEnADbbHGq6p1BwFxm6txNBsQnsw';
|
|
79
|
+
const pubkey = 'STM8m5UgaFAAYQRuaNejYdS8FVLVp9Ss3K1qAVk5de6F8s3HnVbvA';
|
|
80
|
+
const cyphertext = encode(wif, pubkey, '#memo爱');
|
|
81
|
+
plaintext = decode(wif, cyphertext);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
throw new Error(e);
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
encodeTest = plaintext === '#memo爱';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (encodeTest === false) {
|
|
91
|
+
throw new Error('This environment does not support encryption.');
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const toPrivateObj = (o) => o ? (o.key ? o : crypto_1.PrivateKey.fromString(o)) : o; /* null or undefined*/
|
|
95
|
+
const toPublicObj = (o) => o ? (o.key ? o : crypto_1.PublicKey.fromString(o)) : o; /* null or undefined*/
|
|
69
96
|
exports.Memo = {
|
|
70
97
|
decode,
|
|
71
98
|
encode
|
package/lib/version.js
CHANGED