Skip to content

Commit 568f948

Browse files
committed
Fixed #441
- Changed key derivation using sha512 - Removed signSchema - Updated tests
1 parent c76f413 commit 568f948

40 files changed

+274
-946
lines changed

package-lock.json

Lines changed: 24 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"js-joda": "^1.6.2",
6565
"js-sha256": "^0.9.0",
6666
"js-sha3": "^0.8.0",
67+
"js-sha512": "^0.8.0",
6768
"long": "^4.0.0",
6869
"merkletreejs": "^0.1.7",
6970
"nem2-sdk-openapi-typescript-node-client": "0.8.2",
@@ -72,6 +73,7 @@
7273
"ripemd160": "^2.0.2",
7374
"rxjs": "^6.5.3",
7475
"rxjs-compat": "^6.5.3",
76+
"tweetnacl": "^1.0.3",
7577
"utf8": "^2.1.2",
7678
"ws": "^5.2.0"
7779
},

src/core/crypto/Crypto.ts

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import { WalletAlgorithm } from '../../model/wallet/WalletAlgorithm';
1818
import { Convert as convert } from '../format/Convert';
1919
import { KeyPair } from './KeyPair';
20-
import { SignSchema } from './SignSchema';
2120
import * as utility from './Utilities';
2221

2322
// tslint:disable-next-line: no-var-requires
@@ -221,20 +220,18 @@ export class Crypto {
221220
* @param {string} msg - A text message
222221
* @param {Uint8Array} iv - An initialization vector
223222
* @param {Uint8Array} salt - A salt
224-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
225223
* @return {string} - The encoded message
226224
*/
227225
public static _encode = (senderPriv: string,
228226
recipientPub: string,
229227
msg: string,
230-
iv: Uint8Array,
231-
signSchema: SignSchema): string => {
228+
iv: Uint8Array): string => {
232229
// Errors
233230
if (!senderPriv || !recipientPub || !msg || !iv) { throw new Error('Missing argument !'); }
234231
// Processing
235-
const keyPair = KeyPair.createKeyPairFromPrivateKeyString(senderPriv, signSchema);
232+
const keyPair = KeyPair.createKeyPairFromPrivateKeyString(senderPriv);
236233
const pk = convert.hexToUint8(recipientPub);
237-
const encKey = utility.ua2words(KeyPair.deriveSharedKey(keyPair, pk, signSchema), 32);
234+
const encKey = utility.ua2words(utility.catapult_crypto.deriveSharedKey(keyPair.privateKey, pk), 32);
238235
const encIv = {
239236
iv: utility.ua2words(iv, 16),
240237
};
@@ -250,20 +247,18 @@ export class Crypto {
250247
* @param {string} senderPriv - A sender private key
251248
* @param {string} recipientPub - A recipient public key
252249
* @param {string} msg - A text message
253-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
254250
* @param {boolean} isHexString - Is payload string a hexadecimal string (default = false)
255251
* @return {string} - The encoded message
256252
*/
257253
public static encode = (senderPriv: string,
258254
recipientPub: string,
259255
msg: string,
260-
signSchema: SignSchema,
261256
isHexString: boolean = false): string => {
262257
// Errors
263258
if (!senderPriv || !recipientPub || !msg) { throw new Error('Missing argument !'); }
264259
// Processing
265260
const iv = Crypto.randomBytes(16);
266-
const encoded = Crypto._encode(senderPriv, recipientPub, isHexString ? msg : convert.utf8ToHex(msg), iv, signSchema);
261+
const encoded = Crypto._encode(senderPriv, recipientPub, isHexString ? msg : convert.utf8ToHex(msg), iv);
267262
// Result
268263
return encoded;
269264
}
@@ -275,20 +270,18 @@ export class Crypto {
275270
* @param {string} senderPublic - A sender public key
276271
* @param {Uint8Array} payload - An encrypted message payload in bytes
277272
* @param {Uint8Array} iv - 16-byte AES initialization vector
278-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
279273
* @return {string} - The decoded payload as hex
280274
*/
281275
public static _decode = (recipientPrivate: string,
282276
senderPublic: string,
283277
payload: Uint8Array,
284-
iv: Uint8Array,
285-
signSchema: SignSchema): string => {
278+
iv: Uint8Array): string => {
286279
// Error
287280
if (!recipientPrivate || !senderPublic || !payload) { throw new Error('Missing argument !'); }
288281
// Processing
289-
const keyPair = KeyPair.createKeyPairFromPrivateKeyString(recipientPrivate, signSchema);
282+
const keyPair = KeyPair.createKeyPairFromPrivateKeyString(recipientPrivate);
290283
const pk = convert.hexToUint8(senderPublic);
291-
const encKey = utility.ua2words(KeyPair.deriveSharedKey(keyPair, pk, signSchema), 32);
284+
const encKey = utility.ua2words(utility.catapult_crypto.deriveSharedKey(keyPair.privateKey, pk), 32);
292285
const encIv = {
293286
iv: utility.ua2words(iv, 16),
294287
};
@@ -306,20 +299,18 @@ export class Crypto {
306299
* @param {string} recipientPrivate - A recipient private key
307300
* @param {string} senderPublic - A sender public key
308301
* @param {string} payload - An encrypted message payload
309-
* @param {SignSchema} signSchema - The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
310302
* @return {string} - The decoded payload as hex
311303
*/
312304
public static decode = (recipientPrivate: string,
313305
senderPublic: string,
314-
payload: string,
315-
signSchema: SignSchema): string => {
306+
payload: string): string => {
316307
// Error
317308
if (!recipientPrivate || !senderPublic || !payload) { throw new Error('Missing argument !'); }
318309
// Processing
319310
const binPayload = convert.hexToUint8(payload);
320311
const payloadBuffer = new Uint8Array(binPayload.buffer, 16);
321312
const iv = new Uint8Array(binPayload.buffer, 0, 16);
322-
const decoded = Crypto._decode(recipientPrivate, senderPublic, payloadBuffer, iv, signSchema);
313+
const decoded = Crypto._decode(recipientPrivate, senderPublic, payloadBuffer, iv);
323314
return decoded.toUpperCase();
324315
}
325316

src/core/crypto/KeyPair.ts

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,65 +13,49 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
import * as nacl from 'tweetnacl';
1617
import { Convert as convert } from '../format';
17-
import { SignSchema } from './SignSchema';
1818
import * as Utility from './Utilities';
1919

2020
export class KeyPair {
2121
/**
2222
* Creates a key pair from a private key string.
2323
* @param {string} privateKeyString A hex encoded private key string.
24-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
2524
* @returns {module:crypto/keyPair~KeyPair} The key pair.
2625
*/
27-
public static createKeyPairFromPrivateKeyString = (privateKeyString: string, signSchema: SignSchema) => {
26+
public static createKeyPairFromPrivateKeyString(privateKeyString: string) {
2827
const privateKey = convert.hexToUint8(privateKeyString);
2928
if (Utility.Key_Size !== privateKey.length) {
3029
throw Error(`private key has unexpected size: ${privateKey.length}`);
3130
}
32-
const publicKey = Utility.catapult_crypto.extractPublicKey(privateKey, Utility.catapult_hash.func, signSchema);
31+
const keyPair = nacl.sign.keyPair.fromSeed(privateKey);
3332
return {
3433
privateKey,
35-
publicKey,
34+
publicKey: keyPair.publicKey,
3635
};
3736
}
3837

3938
/**
4039
* Signs a data buffer with a key pair.
4140
* @param {module:crypto/keyPair~KeyPair} keyPair The key pair to use for signing.
4241
* @param {Uint8Array} data The data to sign.
43-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
4442
* @returns {Uint8Array} The signature.
4543
*/
46-
public static sign = (keyPair, data: Uint8Array, signSchema: SignSchema): Uint8Array => {
47-
return Utility.catapult_crypto.sign(data, keyPair.publicKey, keyPair.privateKey,
48-
Utility.catapult_hash.createHasher(64, signSchema));
44+
public static sign(keyPair, data: Uint8Array): Uint8Array {
45+
const secretKey = new Uint8Array(64);
46+
secretKey.set(keyPair.privateKey);
47+
secretKey.set(keyPair.publicKey, 32);
48+
return nacl.sign.detached(data, secretKey);
4949
}
5050

5151
/**
5252
* Verifies a signature.
5353
* @param {Uint8Array} publicKey The public key to use for verification.
5454
* @param {Uint8Array} data The data to verify.
5555
* @param {Uint8Array} signature The signature to verify.
56-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
5756
* @returns {boolean} true if the signature is verifiable, false otherwise.
5857
*/
59-
public static verify = (publicKey: Uint8Array, data: Uint8Array, signature: Uint8Array, signSchema: SignSchema): boolean => {
60-
return Utility.catapult_crypto.verify(publicKey, data, signature, Utility.catapult_hash.createHasher(64, signSchema));
61-
}
62-
63-
/**
64-
* Creates a shared key given a key pair and an arbitrary public key.
65-
* The shared key can be used for encrypted message passing between the two.
66-
* @param {module:crypto/keyPair~KeyPair} keyPair The key pair for which to create the shared key.
67-
* @param {Uint8Array} publicKey The public key for which to create the shared key.
68-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
69-
* @returns {Uint8Array} The shared key.
70-
*/
71-
public static deriveSharedKey = (keyPair, publicKey: Uint8Array, signSchema: SignSchema) => {
72-
if (Utility.Key_Size !== publicKey.length) {
73-
throw Error(`public key has unexpected size: ${publicKey.length}`);
74-
}
75-
return Utility.catapult_crypto.deriveSharedKey(keyPair.privateKey, publicKey, Utility.catapult_hash.func, signSchema);
58+
public static verify(publicKey: Uint8Array, data: Uint8Array, signature: Uint8Array): boolean {
59+
return nacl.sign.detached.verify(data, signature, publicKey);
7660
}
7761
}

src/core/crypto/MerkleHashBuilder.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
* limitations under the License.
1515
*/
1616
import { SHA3Hasher } from './SHA3Hasher';
17-
import { SignSchema } from './SignSchema';
1817

1918
export class MerkleHashBuilder {
2019

@@ -27,21 +26,14 @@ export class MerkleHashBuilder {
2726

2827
/**
2928
* Constructor
30-
* @param signSchema Sign schema
3129
* @param length Hash size
3230
*/
3331
constructor(/**
3432
* Length of produced merkle hash in bytes.
3533
*
3634
* @var {number}
3735
*/
38-
public readonly length: number,
39-
/**
40-
* Signature schema used (hash algorithm diff)
41-
*
42-
* @var {SignSchema}
43-
*/
44-
public readonly signSchema: SignSchema) {
36+
public readonly length: number) {
4537
}
4638

4739
/**
@@ -52,7 +44,7 @@ export class MerkleHashBuilder {
5244
* @return {Uint8Array}
5345
*/
5446
protected hash(hashes: Uint8Array[]): Uint8Array {
55-
const hasher = SHA3Hasher.createHasher(this.length, this.signSchema);
47+
const hasher = SHA3Hasher.createHasher(this.length);
5648
hasher.reset();
5749

5850
hashes.forEach((hashVal: Uint8Array) => {

src/core/crypto/SHA3Hasher.ts

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,32 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { keccak256, keccak512, sha3_256, sha3_512 } from 'js-sha3';
18-
import { NetworkType } from '../../model/blockchain/NetworkType';
17+
import { sha3_256, sha3_512 } from 'js-sha3';
1918
import { Convert as convert, RawArray as array } from '../format';
20-
import { SignSchema } from './SignSchema';
2119

2220
export class SHA3Hasher {
2321
/**
2422
* Calculates the hash of data.
2523
* @param {Uint8Array} dest The computed hash destination.
2624
* @param {Uint8Array} data The data to hash.
2725
* @param {numeric} length The hash length in bytes.
28-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
2926
*/
30-
public static func = (dest, data, length, signSchema: SignSchema) => {
31-
const hasher = SHA3Hasher.getHasher(length, signSchema);
27+
public static func = (dest, data, length) => {
28+
const hasher = SHA3Hasher.getHasher(length);
3229
const hash = hasher.arrayBuffer(data);
3330
array.copy(dest, array.uint8View(hash));
3431
}
3532

3633
/**
3734
* Creates a hasher object.
3835
* @param {numeric} length The hash length in bytes.
39-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
4036
* @returns {object} The hasher.
4137
*/
42-
public static createHasher = (length = 64, signSchema: SignSchema) => {
38+
public static createHasher = (length = 64) => {
4339
let hash;
4440
return {
4541
reset: () => {
46-
hash = SHA3Hasher.getHasher(length, signSchema).create();
42+
hash = SHA3Hasher.getHasher(length).create();
4743
},
4844
update: (data: any) => {
4945
if (data instanceof Uint8Array) {
@@ -63,27 +59,12 @@ export class SHA3Hasher {
6359
/**
6460
* Get a hasher instance.
6561
* @param {numeric} length The hash length in bytes.
66-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
6762
* @returns {object} The hasher.
6863
*/
69-
public static getHasher = (length = 64, signSchema: SignSchema) => {
64+
public static getHasher = (length = 64) => {
7065
return {
71-
32: signSchema === SignSchema.SHA3 ? sha3_256 : keccak256,
72-
64: signSchema === SignSchema.SHA3 ? sha3_512 : keccak512 ,
66+
32: sha3_256,
67+
64: sha3_512,
7368
} [length];
7469
}
75-
76-
/**
77-
* Resolve signature schema from given network type
78-
*
79-
* @param {NetworkType} networkType - Network type
80-
*
81-
* @return {SignSchema}
82-
*/
83-
public static resolveSignSchema(networkType: NetworkType): SignSchema {
84-
if (networkType === NetworkType.MAIN_NET || networkType === NetworkType.TEST_NET) {
85-
return SignSchema.KECCAK;
86-
}
87-
return SignSchema.SHA3;
88-
}
8970
}

src/core/crypto/SignSchema.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)