Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions e2e/infrastructure/BlockHttp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { Deadline } from '../../src/model/transaction/Deadline';
import { TransactionInfo } from '../../src/model/transaction/TransactionInfo';
import { TransferTransaction } from '../../src/model/transaction/TransferTransaction';
import { IntegrationTestHelper } from './IntegrationTestHelper';
import { UInt64 } from '../../src/model/UInt64';

describe('BlockHttp', () => {
const helper = new IntegrationTestHelper();
Expand Down Expand Up @@ -87,7 +88,7 @@ describe('BlockHttp', () => {

describe('getBlockByHeight', () => {
it('should return block info given height', (done) => {
blockRepository.getBlockByHeight('1')
blockRepository.getBlockByHeight(UInt64.fromUint(1))
.subscribe((blockInfo) => {
blockReceiptHash = blockInfo.blockReceiptsHash;
blockTransactionHash = blockInfo.blockTransactionsHash;
Expand All @@ -105,7 +106,7 @@ describe('BlockHttp', () => {
let firstId: string;

it('should return block transactions data given height', (done) => {
blockRepository.getBlockTransactions('1')
blockRepository.getBlockTransactions(UInt64.fromUint(1))
.subscribe((transactions) => {
nextId = transactions[0].transactionInfo!.id;
firstId = transactions[1].transactionInfo!.id;
Expand All @@ -115,7 +116,7 @@ describe('BlockHttp', () => {
});

it('should return block transactions data given height with paginated transactionId', (done) => {
blockRepository.getBlockTransactions('1', new QueryParams(10, nextId))
blockRepository.getBlockTransactions(UInt64.fromUint(1), new QueryParams(10, nextId))
.subscribe((transactions) => {
expect(transactions[0].transactionInfo!.id).to.be.equal(firstId);
expect(transactions.length).to.be.greaterThan(0);
Expand Down
1 change: 0 additions & 1 deletion e2e/service/MosaicRestrictionTransactionService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ describe('MosaicRestrictionTransactionService', () => {
UInt64.fromUint(1000),
networkType, helper.maxFee,
);
console.log(mosaicId.toHex());
const signedTransaction = mosaicDefinitionTransaction.signWith(account, generationHash);
return helper.announce(signedTransaction);
});
Expand Down
1 change: 0 additions & 1 deletion e2e/service/MosaicService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ describe('MosaicService', () => {
const views = amountViews.map((v) => {
return {mosaicId: v.fullName(), amount: v.relativeAmount()};
});
console.log(views);
done();
});
});
Expand Down
17 changes: 11 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,15 @@
},
"dependencies": {
"bluebird": "^3.5.5",
"catbuffer": "0.0.7",
"nem2-sdk-openapi-typescript-node-client": "0.7.20-beta.6",
"catbuffer": "0.0.11",
"crypto-js": "^3.1.9-1",
"futoin-hkdf": "^1.3.1",
"js-joda": "^1.6.2",
"js-sha256": "^0.9.0",
"js-sha3": "^0.8.0",
"long": "^4.0.0",
"merkletreejs": "^0.1.7",
"nem2-sdk-openapi-typescript-node-client": "0.7.20-alpha.7",
"request": "^2.88.0",
"request-promise-native": "^1.0.5",
"ripemd160": "^2.0.2",
Expand Down
21 changes: 8 additions & 13 deletions src/core/crypto/Crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,20 +228,19 @@ export class Crypto {
recipientPub: string,
msg: string,
iv: Uint8Array,
salt: Uint8Array,
signSchema: SignSchema): string => {
// Errors
if (!senderPriv || !recipientPub || !msg || !iv || !salt) { throw new Error('Missing argument !'); }
if (!senderPriv || !recipientPub || !msg || !iv) { throw new Error('Missing argument !'); }
// Processing
const keyPair = KeyPair.createKeyPairFromPrivateKeyString(senderPriv, signSchema);
const pk = convert.hexToUint8(recipientPub);
const encKey = utility.ua2words(KeyPair.deriveSharedKey(keyPair, pk, salt, signSchema), 32);
const encKey = utility.ua2words(KeyPair.deriveSharedKey(keyPair, pk, signSchema), 32);
const encIv = {
iv: utility.ua2words(iv, 16),
};
const encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Hex.parse(msg), encKey, encIv);
// Result
const result = convert.uint8ToHex(salt) + convert.uint8ToHex(iv) + CryptoJS.enc.Hex.stringify(encrypted.ciphertext);
const result = convert.uint8ToHex(iv) + CryptoJS.enc.Hex.stringify(encrypted.ciphertext);
return result;
}

Expand All @@ -264,8 +263,7 @@ export class Crypto {
if (!senderPriv || !recipientPub || !msg) { throw new Error('Missing argument !'); }
// Processing
const iv = Crypto.randomBytes(16);
const salt = Crypto.randomBytes(32);
const encoded = Crypto._encode(senderPriv, recipientPub, isHexString ? msg : convert.utf8ToHex(msg), iv, salt, signSchema);
const encoded = Crypto._encode(senderPriv, recipientPub, isHexString ? msg : convert.utf8ToHex(msg), iv, signSchema);
// Result
return encoded;
}
Expand All @@ -277,22 +275,20 @@ export class Crypto {
* @param {string} senderPublic - A sender public key
* @param {Uint8Array} payload - An encrypted message payload in bytes
* @param {Uint8Array} iv - 16-byte AES initialization vector
* @param {Uint8Array} salt - 32-byte salt
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
* @return {string} - The decoded payload as hex
*/
public static _decode = (recipientPrivate: string,
senderPublic: string,
payload: Uint8Array,
iv: Uint8Array,
salt: Uint8Array,
signSchema: SignSchema): string => {
// Error
if (!recipientPrivate || !senderPublic || !payload) { throw new Error('Missing argument !'); }
// Processing
const keyPair = KeyPair.createKeyPairFromPrivateKeyString(recipientPrivate, signSchema);
const pk = convert.hexToUint8(senderPublic);
const encKey = utility.ua2words(KeyPair.deriveSharedKey(keyPair, pk, salt, signSchema), 32);
const encKey = utility.ua2words(KeyPair.deriveSharedKey(keyPair, pk, signSchema), 32);
const encIv = {
iv: utility.ua2words(iv, 16),
};
Expand Down Expand Up @@ -321,10 +317,9 @@ export class Crypto {
if (!recipientPrivate || !senderPublic || !payload) { throw new Error('Missing argument !'); }
// Processing
const binPayload = convert.hexToUint8(payload);
const payloadBuffer = new Uint8Array(binPayload.buffer, 48);
const salt = new Uint8Array(binPayload.buffer, 0, 32);
const iv = new Uint8Array(binPayload.buffer, 32, 16);
const decoded = Crypto._decode(recipientPrivate, senderPublic, payloadBuffer, iv, salt, signSchema);
const payloadBuffer = new Uint8Array(binPayload.buffer, 16);
const iv = new Uint8Array(binPayload.buffer, 0, 16);
const decoded = Crypto._decode(recipientPrivate, senderPublic, payloadBuffer, iv, signSchema);
return decoded.toUpperCase();
}

Expand Down
17 changes: 6 additions & 11 deletions src/core/crypto/KeyPair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { NetworkType } from '../../model/blockchain/NetworkType';
import { Convert as convert } from '../format';
import { SignSchema } from './SignSchema';
import * as Utility from './Utilities';
Expand Down Expand Up @@ -44,20 +43,20 @@ export class KeyPair {
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
* @returns {Uint8Array} The signature.
*/
public static sign = (keyPair, data: Uint8Array, signSchema: SignSchema) => {
public static sign = (keyPair, data: Uint8Array, signSchema: SignSchema): Uint8Array => {
return Utility.catapult_crypto.sign(data, keyPair.publicKey, keyPair.privateKey,
Utility.catapult_hash.createHasher(64, signSchema));
}

/**
* Verifies a signature.
* @param {module:crypto/keyPair~PublicKey} publicKey The public key to use for verification.
* @param {Uint8Array} publicKey The public key to use for verification.
* @param {Uint8Array} data The data to verify.
* @param {Uint8Array} signature The signature to verify.
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
* @returns {boolean} true if the signature is verifiable, false otherwise.
*/
public static verify = (publicKey, data: Uint8Array, signature: Uint8Array, signSchema: SignSchema) => {
public static verify = (publicKey: Uint8Array, data: Uint8Array, signature: Uint8Array, signSchema: SignSchema): boolean => {
return Utility.catapult_crypto.verify(publicKey, data, signature, Utility.catapult_hash.createHasher(64, signSchema));
}

Expand All @@ -66,17 +65,13 @@ export class KeyPair {
* The shared key can be used for encrypted message passing between the two.
* @param {module:crypto/keyPair~KeyPair} keyPair The key pair for which to create the shared key.
* @param {Uint8Array} publicKey The public key for which to create the shared key.
* @param {Uint8Array} salt A salt that should be applied to the shared key.
* @param {SignSchema} signSchema The Sign Schema. (KECCAK(NIS1) / SHA3(Catapult))
* @returns {Uint8Array} The shared key.
*/
public static deriveSharedKey = (keyPair, publicKey: Uint8Array, salt: Uint8Array, signSchema: SignSchema) => {
if (Utility.Key_Size !== salt.length) {
throw Error(`salt has unexpected size: ${salt.length}`);
}
public static deriveSharedKey = (keyPair, publicKey: Uint8Array, signSchema: SignSchema) => {
if (Utility.Key_Size !== publicKey.length) {
throw Error(`public key has unexpected size: ${salt.length}`);
throw Error(`public key has unexpected size: ${publicKey.length}`);
}
return Utility.catapult_crypto.deriveSharedKey(salt, keyPair.privateKey, publicKey, Utility.catapult_hash.func, signSchema);
return Utility.catapult_crypto.deriveSharedKey(keyPair.privateKey, publicKey, Utility.catapult_hash.func, signSchema);
}
}
35 changes: 19 additions & 16 deletions src/core/crypto/Utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ import { RawArray as array } from '../format';
import * as nacl from './nacl_catapult';
import { SHA3Hasher as sha3Hasher } from './SHA3Hasher';
import { SignSchema } from './SignSchema';

export const CryptoJS = require('crypto-js');
export const Key_Size = 32;
export const Signature_Size = 64;
export const Half_Signature_Size = Signature_Size / 2;
export const Hash_Size = 64;
export const Half_Hash_Size = Hash_Size / 2;
export const hkdf = require('futoin-hkdf');

/**
* Convert an Uint8Array to WordArray
Expand Down Expand Up @@ -68,7 +70,7 @@ export const catapult_hash = {
};

// custom catapult crypto functions
export const catapult_crypto = (function() {
export const catapult_crypto = (() => {
function clamp(d) {
d[0] &= 248;
d[31] &= 127;
Expand All @@ -82,7 +84,7 @@ export const catapult_crypto = (function() {
return d;
}

const encodedSChecker = (function() {
const encodedSChecker = (() => {
const Is_Reduced = 1;
const Is_Zero = 2;

Expand Down Expand Up @@ -202,25 +204,26 @@ export const catapult_crypto = (function() {
return 0 === c.crypto_verify_32(signature, 0, t, 0);
},

deriveSharedKey: (salt, sk, pk, hashfunc, signSchema: SignSchema) => {
deriveSharedKey: (privateKey: Uint8Array, publicKey: Uint8Array, hashfunc, signSchema: SignSchema): Uint8Array => {
const sharedSecret = catapult_crypto.deriveSharedSecret(privateKey, publicKey, hashfunc, signSchema);
const info = 'catapult';
const hash = 'SHA-256';
return hkdf(sharedSecret, 32, {salt: new Uint8Array(32), info, hash});
},

deriveSharedSecret: (privateKey: Uint8Array, publicKey: Uint8Array, hashfunc, signSchema: SignSchema): Uint8Array => {
const c = nacl;
const d = prepareForScalarMult(sk, hashfunc, signSchema);
const d = prepareForScalarMult(privateKey, hashfunc, signSchema);

// sharedKey = pack(p = d (derived from sk) * q (derived from pk))
// sharedKey = pack(p = d (derived from privateKey) * q (derived from publicKey))
const q = [c.gf(), c.gf(), c.gf(), c.gf()];
const p = [c.gf(), c.gf(), c.gf(), c.gf()];
const sharedKey = new Uint8Array(Key_Size);
c.unpack(q, pk);
const sharedSecret = new Uint8Array(Key_Size);

c.unpack(q, publicKey);
c.scalarmult(p, q, d);
c.pack(sharedKey, p);
// salt the shared key
for (let i = 0; i < Key_Size; ++i) {
sharedKey[i] ^= salt[i];
}
// return the hash of the result
const sharedKeyHash = new Uint8Array(Key_Size);
hashfunc(sharedKeyHash, sharedKey, Key_Size, signSchema);
return sharedKeyHash;
c.pack(sharedSecret, p);
return sharedSecret;
},
};
})();
2 changes: 1 addition & 1 deletion src/core/format/Convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export class Convert {
* @param {Uint8Array} input A uint8 array.
* @returns {string} A hex encoded string corresponding to the input.
*/
public static uint8ToHex = (input) => {
public static uint8ToHex = (input): string => {
let s = '';
for (const byte of input) {
s += utilities.Nibble_To_Char_Map[byte >> 4];
Expand Down
16 changes: 8 additions & 8 deletions src/infrastructure/BlockHttp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ export class BlockHttp extends Http implements BlockRepository {
* @param height - Block height
* @returns Observable<BlockInfo>
*/
public getBlockByHeight(height: string): Observable<BlockInfo> {
return observableFrom(this.blockRoutesApi.getBlockByHeight(height)).pipe(
public getBlockByHeight(height: UInt64): Observable<BlockInfo> {
return observableFrom(this.blockRoutesApi.getBlockByHeight(height.toString())).pipe(
map(({body}) => this.toBlockInfo(body)),
catchError((error) => throwError(this.errorHandling(error))),
);
Expand All @@ -67,10 +67,10 @@ export class BlockHttp extends Http implements BlockRepository {
* @param queryParams - (Optional) Query params
* @returns Observable<Transaction[]>
*/
public getBlockTransactions(height: string,
public getBlockTransactions(height: UInt64,
queryParams?: QueryParams): Observable<Transaction[]> {
return observableFrom(
this.blockRoutesApi.getBlockTransactions(height,
this.blockRoutesApi.getBlockTransactions(height.toString(),
this.queryParams(queryParams).pageSize,
this.queryParams(queryParams).id,
this.queryParams(queryParams).order))
Expand All @@ -87,9 +87,9 @@ export class BlockHttp extends Http implements BlockRepository {
* @param limit - Number of blocks returned.
* @returns Observable<BlockInfo[]>
*/
public getBlocksByHeightWithLimit(height: string, limit: number): Observable<BlockInfo[]> {
public getBlocksByHeightWithLimit(height: UInt64, limit: number): Observable<BlockInfo[]> {
return observableFrom(
this.blockRoutesApi.getBlocksByHeightWithLimit(height, limit)).pipe(
this.blockRoutesApi.getBlocksByHeightWithLimit(height.toString(), limit)).pipe(
map(({body}) => body.map((blockDTO) => this.toBlockInfo(blockDTO))),
catchError((error) => throwError(this.errorHandling(error))),
);
Expand Down Expand Up @@ -136,9 +136,9 @@ export class BlockHttp extends Http implements BlockRepository {
* @param hash The hash of the transaction.
* @return Observable<MerkleProofInfo>
*/
public getMerkleTransaction(height: string, hash: string): Observable<MerkleProofInfo> {
public getMerkleTransaction(height: UInt64, hash: string): Observable<MerkleProofInfo> {
return observableFrom(
this.blockRoutesApi.getMerkleTransaction(height, hash)).pipe(
this.blockRoutesApi.getMerkleTransaction(height.toString(), hash)).pipe(
map(({body}) => new MerkleProofInfo(
body.merklePath!.map((payload) => new MerklePathItem(payload.position, payload.hash)),
)),
Expand Down
Loading