Skip to content

Commit 9e3f83f

Browse files
authored
Merge pull request #254 from rg911/task/g253_signSchema_refactoring
JAV-18 [Github #253] Signature Schema Refactoring
2 parents 40fa287 + ad5f02f commit 9e3f83f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+464
-547
lines changed

src/core/crypto/Crypto.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
import { WalletAlgorithm } from '../../model/wallet/WalletAlgorithm';
1818
import { Convert as convert } from '../format/Convert';
1919
import { KeyPair } from './KeyPair';
20-
import * as utility from './Utilities';
2120
import { SignSchema } from './SignSchema';
21+
import * as utility from './Utilities';
22+
// tslint:disable-next-line: no-var-requires
2223
const CryptoJS = require('crypto-js');
2324
export class Crypto {
2425
/**
@@ -219,10 +220,10 @@ export class Crypto {
219220
* @param {string} msg - A text message
220221
* @param {Uint8Array} iv - An initialization vector
221222
* @param {Uint8Array} salt - A salt
222-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
223+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
223224
* @return {string} - The encoded message
224225
*/
225-
public static _encode = (senderPriv, recipientPub, msg, iv, salt, signSchema: SignSchema = SignSchema.SHA3) => {
226+
public static _encode = (senderPriv, recipientPub, msg, iv, salt, signSchema: SignSchema) => {
226227
// Errors
227228
if (!senderPriv || !recipientPub || !msg || !iv || !salt) { throw new Error('Missing argument !'); }
228229
// Processing
@@ -244,10 +245,10 @@ export class Crypto {
244245
* @param {string} senderPriv - A sender private key
245246
* @param {string} recipientPub - A recipient public key
246247
* @param {string} msg - A text message
247-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
248+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
248249
* @return {string} - The encoded message
249250
*/
250-
public static encode = (senderPriv, recipientPub, msg, signSchema: SignSchema = SignSchema.SHA3) => {
251+
public static encode = (senderPriv, recipientPub, msg, signSchema: SignSchema) => {
251252
// Errors
252253
if (!senderPriv || !recipientPub || !msg) { throw new Error('Missing argument !'); }
253254
// Processing
@@ -264,10 +265,10 @@ export class Crypto {
264265
* @param {string} recipientPrivate - A recipient private key
265266
* @param {string} senderPublic - A sender public key
266267
* @param {Uint8Array} _payload - An encrypted message payload in bytes
267-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
268+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
268269
* @return {string} - The decoded payload as hex
269270
*/
270-
public static _decode = (recipientPrivate, senderPublic, payload, iv, salt, signSchema: SignSchema = SignSchema.SHA3) => {
271+
public static _decode = (recipientPrivate, senderPublic, payload, iv, salt, signSchema: SignSchema) => {
271272
// Error
272273
if (!recipientPrivate || !senderPublic || !payload) { throw new Error('Missing argument !'); }
273274
// Processing
@@ -290,19 +291,19 @@ export class Crypto {
290291
*
291292
* @param {string} recipientPrivate - A recipient private key
292293
* @param {string} senderPublic - A sender public key
293-
* @param {string} _payload - An encrypted message payload
294-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
294+
* @param {string} payload - An encrypted message payload
295+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
295296
* @return {string} - The decoded payload as hex
296297
*/
297-
public static decode = (recipientPrivate, senderPublic, _payload, signSchema: SignSchema = SignSchema.SHA3) => {
298+
public static decode = (recipientPrivate, senderPublic, payload, signSchema: SignSchema) => {
298299
// Error
299-
if (!recipientPrivate || !senderPublic || !_payload) { throw new Error('Missing argument !'); }
300+
if (!recipientPrivate || !senderPublic || !payload) { throw new Error('Missing argument !'); }
300301
// Processing
301-
const binPayload = convert.hexToUint8(_payload);
302-
const payload = new Uint8Array(binPayload.buffer, 48);
302+
const binPayload = convert.hexToUint8(payload);
303+
const payloadBuffer = new Uint8Array(binPayload.buffer, 48);
303304
const salt = new Uint8Array(binPayload.buffer, 0, 32);
304305
const iv = new Uint8Array(binPayload.buffer, 32, 16);
305-
const decoded = Crypto._decode(recipientPrivate, senderPublic, payload, iv, salt, signSchema);
306+
const decoded = Crypto._decode(recipientPrivate, senderPublic, payloadBuffer, iv, salt, signSchema);
306307
return decoded;
307308
}
308309

src/core/crypto/KeyPair.ts

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
import { NetworkType } from '../../model/blockchain/NetworkType';
1617
import { Convert as convert } from '../format';
1718
import { SignSchema } from './SignSchema';
1819
import * as Utility from './Utilities';
@@ -21,18 +22,15 @@ export class KeyPair {
2122
/**
2223
* Creates a key pair from a private key string.
2324
* @param {string} privateKeyString A hex encoded private key string.
24-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
25+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
2526
* @returns {module:crypto/keyPair~KeyPair} The key pair.
2627
*/
27-
public static createKeyPairFromPrivateKeyString = (privateKeyString, signSchema = SignSchema.SHA3) => {
28+
public static createKeyPairFromPrivateKeyString = (privateKeyString: string, signSchema: SignSchema) => {
2829
const privateKey = convert.hexToUint8(privateKeyString);
29-
30-
// KECCAK_REVERSED_KEY uses reversed private key.
31-
const secretKey = signSchema === SignSchema.SHA3 ? privateKey : convert.hexToUint8Reverse(privateKeyString);
3230
if (Utility.Key_Size !== privateKey.length) {
3331
throw Error(`private key has unexpected size: ${privateKey.length}`);
3432
}
35-
const publicKey = Utility.catapult_crypto.extractPublicKey(secretKey, Utility.catapult_hash.func, signSchema);
33+
const publicKey = Utility.catapult_crypto.extractPublicKey(privateKey, Utility.catapult_hash.func, signSchema);
3634
return {
3735
privateKey,
3836
publicKey,
@@ -43,16 +41,11 @@ export class KeyPair {
4341
* Signs a data buffer with a key pair.
4442
* @param {module:crypto/keyPair~KeyPair} keyPair The key pair to use for signing.
4543
* @param {Uint8Array} data The data to sign.
46-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
44+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
4745
* @returns {Uint8Array} The signature.
4846
*/
49-
public static sign = (keyPair, data, signSchema = SignSchema.SHA3) => {
50-
let secretKey = keyPair.privateKey;
51-
// KECCAK_REVERSED_KEY uses reversed private key.
52-
if (signSchema === SignSchema.KECCAK_REVERSED_KEY) {
53-
secretKey = convert.hexToUint8Reverse(convert.uint8ToHex(secretKey));
54-
}
55-
return Utility.catapult_crypto.sign(data, keyPair.publicKey, secretKey,
47+
public static sign = (keyPair, data: Uint8Array, signSchema: SignSchema) => {
48+
return Utility.catapult_crypto.sign(data, keyPair.publicKey, keyPair.privateKey,
5649
Utility.catapult_hash.createHasher(64, signSchema));
5750
}
5851

@@ -61,10 +54,10 @@ export class KeyPair {
6154
* @param {module:crypto/keyPair~PublicKey} publicKey The public key to use for verification.
6255
* @param {Uint8Array} data The data to verify.
6356
* @param {Uint8Array} signature The signature to verify.
64-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
57+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
6558
* @returns {boolean} true if the signature is verifiable, false otherwise.
6659
*/
67-
public static verify = (publicKey, data, signature, signSchema = SignSchema.SHA3) => {
60+
public static verify = (publicKey, data: Uint8Array, signature: Uint8Array, signSchema: SignSchema) => {
6861
return Utility.catapult_crypto.verify(publicKey, data, signature, Utility.catapult_hash.createHasher(64, signSchema));
6962
}
7063

@@ -74,21 +67,16 @@ export class KeyPair {
7467
* @param {module:crypto/keyPair~KeyPair} keyPair The key pair for which to create the shared key.
7568
* @param {Uint8Array} publicKey The public key for which to create the shared key.
7669
* @param {Uint8Array} salt A salt that should be applied to the shared key.
77-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
70+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
7871
* @returns {Uint8Array} The shared key.
7972
*/
80-
public static deriveSharedKey = (keyPair, publicKey, salt, signSchema = SignSchema.SHA3) => {
73+
public static deriveSharedKey = (keyPair, publicKey: Uint8Array, salt: Uint8Array, signSchema: SignSchema) => {
8174
if (Utility.Key_Size !== salt.length) {
8275
throw Error(`salt has unexpected size: ${salt.length}`);
8376
}
8477
if (Utility.Key_Size !== publicKey.length) {
8578
throw Error(`public key has unexpected size: ${salt.length}`);
8679
}
87-
let secretKey = keyPair.privateKey;
88-
// KECCAK_REVERSED_KEY uses reversed private key.
89-
if (signSchema === SignSchema.KECCAK_REVERSED_KEY) {
90-
secretKey = convert.hexToUint8Reverse(convert.uint8ToHex(secretKey));
91-
}
92-
return Utility.catapult_crypto.deriveSharedKey(salt, secretKey, publicKey, Utility.catapult_hash.func, signSchema);
80+
return Utility.catapult_crypto.deriveSharedKey(salt, keyPair.privateKey, publicKey, Utility.catapult_hash.func, signSchema);
9381
}
9482
}

src/core/crypto/SHA3Hasher.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
import { keccak256, keccak512, sha3_256, sha3_512 } from 'js-sha3';
18+
import { NetworkType } from '../../model/blockchain/NetworkType';
1819
import { Convert as convert, RawArray as array } from '../format';
1920
import { SignSchema } from './SignSchema';
2021

@@ -24,9 +25,9 @@ export class SHA3Hasher {
2425
* @param {Uint8Array} dest The computed hash destination.
2526
* @param {Uint8Array} data The data to hash.
2627
* @param {numeric} length The hash length in bytes.
27-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
28+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
2829
*/
29-
public static func = (dest, data, length, signSchema = SignSchema.SHA3) => {
30+
public static func = (dest, data, length, signSchema: SignSchema) => {
3031
const hasher = SHA3Hasher.getHasher(length, signSchema);
3132
const hash = hasher.arrayBuffer(data);
3233
array.copy(dest, array.uint8View(hash));
@@ -35,10 +36,10 @@ export class SHA3Hasher {
3536
/**
3637
* Creates a hasher object.
3738
* @param {numeric} length The hash length in bytes.
38-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
39+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
3940
* @returns {object} The hasher.
4041
*/
41-
public static createHasher = (length = 64, signSchema = SignSchema.SHA3) => {
42+
public static createHasher = (length = 64, signSchema: SignSchema) => {
4243
let hash;
4344
return {
4445
reset: () => {
@@ -62,13 +63,27 @@ export class SHA3Hasher {
6263
/**
6364
* Get a hasher instance.
6465
* @param {numeric} length The hash length in bytes.
65-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
66+
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
6667
* @returns {object} The hasher.
6768
*/
68-
public static getHasher = (length = 64, signSchema = SignSchema.SHA3) => {
69+
public static getHasher = (length = 64, signSchema: SignSchema) => {
6970
return {
7071
32: signSchema === SignSchema.SHA3 ? sha3_256 : keccak256,
7172
64: signSchema === SignSchema.SHA3 ? sha3_512 : keccak512 ,
7273
} [length];
7374
}
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+
}
7489
}

src/core/crypto/SignSchema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
*/
1616

1717
/**
18-
* [KECCAK_REVERSED_KEY]: Keccak hash algorithm with reversed private keys.
18+
* [KECCAK]: Keccak hash algorithm.
1919
* [SHA3]: SHA3 hash algorithm without key reversal
2020
*/
2121
export enum SignSchema {
22-
KECCAK_REVERSED_KEY = 1,
22+
KECCAK = 1,
2323
SHA3 = 2,
2424
}

src/core/crypto/Utilities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
1617
import { RawArray as array } from '../format';
1718
import * as nacl from './nacl_catapult';
1819
import { SHA3Hasher as sha3Hasher } from './SHA3Hasher';

src/core/format/RawAddress.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
import { keccak256, sha3_256 } from 'js-sha3';
1818
import RIPEMD160 = require('ripemd160');
19-
import { SignSchema } from '../crypto';
19+
import { NetworkType } from '../../model/blockchain/NetworkType';
20+
import { SignSchema} from '../crypto';
21+
import { SHA3Hasher } from '../crypto/SHA3Hasher';
2022
import { Base32 } from './Base32';
2123
import { Convert } from './Convert';
2224
import { RawArray } from './RawArray';
@@ -74,28 +76,28 @@ export class RawAddress {
7476
/**
7577
* Converts a public key to a decoded address for a specific network.
7678
* @param {Uint8Array} publicKey The public key.
77-
* @param {number} networkIdentifier The network identifier.
78-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
79+
* @param {NetworkType} networkType The network identifier.
7980
* @returns {Uint8Array} The decoded address corresponding to the inputs.
8081
*/
8182
public static publicKeyToAddress = (publicKey: Uint8Array,
82-
networkIdentifier: number,
83-
signSchema: SignSchema = SignSchema.SHA3): Uint8Array => {
83+
networkType: NetworkType): Uint8Array => {
8484
// step 1: sha3 hash of the public key
85+
const signSchema = SHA3Hasher.resolveSignSchema(networkType);
8586
const publicKeyHash = signSchema === SignSchema.SHA3 ? sha3_256.arrayBuffer(publicKey) : keccak256.arrayBuffer(publicKey);
8687

8788
// step 2: ripemd160 hash of (1)
8889
const ripemdHash = new RIPEMD160().update(new Buffer(publicKeyHash)).digest();
8990

9091
// step 3: add network identifier byte in front of (2)
9192
const decodedAddress = new Uint8Array(RawAddress.constants.sizes.addressDecoded);
92-
decodedAddress[0] = networkIdentifier;
93+
decodedAddress[0] = networkType;
9394
RawArray.copy(decodedAddress, ripemdHash, RawAddress.constants.sizes.ripemd160, 1);
9495

9596
// step 4: concatenate (3) and the checksum of (3)
9697
const hash = signSchema === SignSchema.SHA3 ?
9798
sha3_256.arrayBuffer(decodedAddress.subarray(0, RawAddress.constants.sizes.ripemd160 + 1)) :
9899
keccak256.arrayBuffer(decodedAddress.subarray(0, RawAddress.constants.sizes.ripemd160 + 1));
100+
99101
RawArray.copy(decodedAddress, RawArray.uint8View(hash),
100102
RawAddress.constants.sizes.checksum, RawAddress.constants.sizes.ripemd160 + 1);
101103

@@ -105,10 +107,11 @@ export class RawAddress {
105107
/**
106108
* Determines the validity of a decoded address.
107109
* @param {Uint8Array} decoded The decoded address.
108-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
110+
* @param {NetworkType} networkType The network identifier.
109111
* @returns {boolean} true if the decoded address is valid, false otherwise.
110112
*/
111-
public static isValidAddress = (decoded: Uint8Array, signSchema: SignSchema = SignSchema.SHA3): boolean => {
113+
public static isValidAddress = (decoded: Uint8Array, networkType: NetworkType): boolean => {
114+
const signSchema = SHA3Hasher.resolveSignSchema(networkType);
112115
const hash = signSchema === SignSchema.SHA3 ? sha3_256.create() : keccak256.create();
113116
const checksumBegin = RawAddress.constants.sizes.addressDecoded - RawAddress.constants.sizes.checksum;
114117
hash.update(decoded.subarray(0, checksumBegin));
@@ -120,16 +123,17 @@ export class RawAddress {
120123
/**
121124
* Determines the validity of an encoded address string.
122125
* @param {string} encoded The encoded address string.
126+
* @param {NetworkType} networkType The network identifier.
123127
* @returns {boolean} true if the encoded address string is valid, false otherwise.
124128
*/
125-
public static isValidEncodedAddress = (encoded: string): boolean => {
129+
public static isValidEncodedAddress = (encoded: string, networkType: NetworkType): boolean => {
126130
if (RawAddress.constants.sizes.addressEncoded !== encoded.length) {
127131
return false;
128132
}
129133

130134
try {
131135
const decoded = RawAddress.stringToAddress(encoded);
132-
return RawAddress.isValidAddress(decoded);
136+
return RawAddress.isValidAddress(decoded, networkType);
133137
} catch (err) {
134138
return false;
135139
}

src/core/utils/TransactionMapping.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,10 @@ export class TransactionMapping {
3535
* Create transaction class from payload binary.
3636
* @param {string} payload The transaction binary payload
3737
* @param {Boolean} isEmbedded Is embedded transaction (Default: false)
38-
* @param {SignSchema} signSchema The Sign Schema. (KECCAK_REVERSED_KEY / SHA3)
3938
* @returns {Transaction | InnerTransaction} The transaction class.
4039
*/
4140
public static createFromPayload(payload: string,
42-
isEmbedded = false,
43-
signSchema = SignSchema.SHA3): Transaction | InnerTransaction {
44-
return CreateTransactionFromPayload(payload, isEmbedded, signSchema);
41+
isEmbedded = false): Transaction | InnerTransaction {
42+
return CreateTransactionFromPayload(payload, isEmbedded);
4543
}
4644
}

0 commit comments

Comments
 (0)