diff --git a/src/infrastructure/transaction/CreateTransactionFromDTO.ts b/src/infrastructure/transaction/CreateTransactionFromDTO.ts index 36d10613e7..0c189a2bff 100644 --- a/src/infrastructure/transaction/CreateTransactionFromDTO.ts +++ b/src/infrastructure/transaction/CreateTransactionFromDTO.ts @@ -30,7 +30,9 @@ import {AggregateTransaction} from '../../model/transaction/AggregateTransaction import {AggregateTransactionCosignature} from '../../model/transaction/AggregateTransactionCosignature'; import {AggregateTransactionInfo} from '../../model/transaction/AggregateTransactionInfo'; import {Deadline} from '../../model/transaction/Deadline'; +import { EncryptedMessage } from '../../model/transaction/EncryptedMessage'; import {LockFundsTransaction} from '../../model/transaction/LockFundsTransaction'; +import { MessageType } from '../../model/transaction/MessageType'; import {ModifyAccountPropertyAddressTransaction} from '../../model/transaction/ModifyAccountPropertyAddressTransaction'; import {ModifyAccountPropertyEntityTypeTransaction} from '../../model/transaction/ModifyAccountPropertyEntityTypeTransaction'; import {ModifyAccountPropertyMosaicTransaction} from '../../model/transaction/ModifyAccountPropertyMosaicTransaction'; @@ -126,7 +128,7 @@ const CreateStandaloneTransactionFromDTO = (transactionDTO, transactionInfo): Tr new UInt64(transactionDTO.maxFee || [0, 0]), extractRecipient(transactionDTO.recipient), extractMosaics(transactionDTO.mosaics), - extractMessage(transactionDTO.message !== undefined ? transactionDTO.message.payload : undefined), + extractMessage(transactionDTO.message !== undefined ? transactionDTO.message : undefined), transactionDTO.signature, transactionDTO.signer ? PublicAccount.createFromPublicKey(transactionDTO.signer, extractNetworkType(transactionDTO.version)) : undefined, @@ -426,15 +428,15 @@ export const extractMosaics = (mosaics: any): Mosaic[] => { * @param message - message payload * @return {PlainMessage} */ -const extractMessage = (message: any): PlainMessage => { - let plainMessage = EmptyMessage; - if (message !== undefined && convert.isHexString(message)) { - plainMessage = PlainMessage.createFromPayload(message); - } else { - plainMessage = PlainMessage.create(message); +const extractMessage = (message: any): PlainMessage | EncryptedMessage => { + let msgObj = EmptyMessage; + if (message.type === MessageType.PlainMessage) { + msgObj = convert.isHexString(message) ? PlainMessage.createFromPayload(message.payload) : + PlainMessage.create(message.payload); + } else if (message.type === MessageType.EncryptedMessage) { + msgObj = EncryptedMessage.createFromPayload(message.payload); } - - return plainMessage; + return msgObj; }; /** @@ -454,7 +456,7 @@ const extractMessage = (message: any): PlainMessage => { */ export const extractBeneficiary = ( blockDTO: any, - networkType: NetworkType + networkType: NetworkType, ): PublicAccount | undefined => { let dtoPublicAccount: PublicAccount | undefined; diff --git a/src/infrastructure/transaction/CreateTransactionFromPayload.ts b/src/infrastructure/transaction/CreateTransactionFromPayload.ts index 0144524f42..7371ce1e25 100644 --- a/src/infrastructure/transaction/CreateTransactionFromPayload.ts +++ b/src/infrastructure/transaction/CreateTransactionFromPayload.ts @@ -31,9 +31,11 @@ import { AddressAliasTransaction } from '../../model/transaction/AddressAliasTra import { AggregateTransaction } from '../../model/transaction/AggregateTransaction'; import { AggregateTransactionCosignature } from '../../model/transaction/AggregateTransactionCosignature'; import { Deadline } from '../../model/transaction/Deadline'; +import { EncryptedMessage } from '../../model/transaction/EncryptedMessage'; import { HashType } from '../../model/transaction/HashType'; import { LockFundsTransaction } from '../../model/transaction/LockFundsTransaction'; import { Message } from '../../model/transaction/Message'; +import { MessageType } from '../../model/transaction/MessageType'; import { ModifyAccountPropertyAddressTransaction } from '../../model/transaction/ModifyAccountPropertyAddressTransaction'; import { ModifyAccountPropertyEntityTypeTransaction } from '../../model/transaction/ModifyAccountPropertyEntityTypeTransaction'; import { ModifyAccountPropertyMosaicTransaction } from '../../model/transaction/ModifyAccountPropertyMosaicTransaction'; @@ -267,7 +269,8 @@ const CreateTransaction = (type: number, transactionData: string, networkType: N const transferMessageSize = parseInt(convert.uint8ToHex(convert.hexToUint8(transactionData.substring(50, 54)).reverse()), 16); const transferMessageAndMosaicSubString = transactionData.substring(56); - const transferMessageType = transferMessageAndMosaicSubString.substring(0, 2); + const transferMessageType = parseInt(convert.uint8ToHex(convert.hexToUint8( + transferMessageAndMosaicSubString.substring(0, 2)).reverse()), 16); const transferMessage = transferMessageAndMosaicSubString.substring(2, (transferMessageSize - 1) * 2 + 2); const transferMosaic = transferMessageAndMosaicSubString.substring(transferMessageSize * 2); const transferMosaicArray = transferMosaic.match(/.{1,32}/g); @@ -279,7 +282,7 @@ const CreateTransaction = (type: number, transactionData: string, networkType: N new MosaicId(UInt64.fromHex(reverse(mosaic.substring(0, 16))).toDTO()), UInt64.fromHex(reverse(mosaic.substring(16))), )) : [], - PlainMessage.createFromPayload(transferMessage), + extractMessage(transferMessageType, transferMessage), networkType, ); case TransactionType.SECRET_LOCK: @@ -480,3 +483,20 @@ const decodeHex = (hex: string): string => { return str; } }; + + +/** + * @internal + * @param messageType - Message Type + * @param payload - Message Payload + * @returns {Message} + */ +const extractMessage = (messageType: MessageType, payload: string): Message => { + if (messageType === MessageType.PlainMessage) { + return PlainMessage.createFromPayload(payload); + } else if (messageType === MessageType.EncryptedMessage) { + return EncryptedMessage.createFromPayload(payload); + } else { + throw new Error('Invalid message type'); + } +}; diff --git a/src/model/transaction/EncryptedMessage.ts b/src/model/transaction/EncryptedMessage.ts index 2527f558d7..170378174b 100644 --- a/src/model/transaction/EncryptedMessage.ts +++ b/src/model/transaction/EncryptedMessage.ts @@ -35,9 +35,9 @@ export class EncryptedMessage extends Message { /** * - * @param message - * @param recipientPublicAccount - * @param privateKey + * @param message - Plain message to be encrypted + * @param recipientPublicAccount - Recipient public account + * @param privateKey - Sender private key */ public static create(message: string, recipientPublicAccount: PublicAccount, privateKey) { return new EncryptedMessage( @@ -49,17 +49,17 @@ export class EncryptedMessage extends Message { * * @param payload */ - public static createFromDTO(payload: string): EncryptedMessage { - return new EncryptedMessage(payload); + public static createFromPayload(payload: string): EncryptedMessage { + return new EncryptedMessage(this.decodeHex(payload)); } /** * - * @param encryptMessage - * @param privateKey - * @param recipientPublicAccount + * @param encryptMessage - Encrypted message to be decrypted + * @param privateKey - Recipient private key + * @param recipientPublicAccount - Sender public account */ public static decrypt(encryptMessage: EncryptedMessage, privateKey, recipientPublicAccount: PublicAccount): PlainMessage { - return new PlainMessage(Message.decodeHex(crypto.decode(privateKey, recipientPublicAccount.publicKey, encryptMessage.payload))); + return new PlainMessage(this.decodeHex(crypto.decode(privateKey, recipientPublicAccount.publicKey, encryptMessage.payload))); } } diff --git a/test/core/utils/TransactionMapping.spec.ts b/test/core/utils/TransactionMapping.spec.ts index 5a6a7aa685..0a9e0d27ec 100644 --- a/test/core/utils/TransactionMapping.spec.ts +++ b/test/core/utils/TransactionMapping.spec.ts @@ -25,6 +25,7 @@ import { PropertyModificationType } from '../../../src/model/account/PropertyMod import { PropertyType } from '../../../src/model/account/PropertyType'; import { PublicAccount } from '../../../src/model/account/PublicAccount'; import { NetworkType } from '../../../src/model/blockchain/NetworkType'; +import { EncryptedMessage } from '../../../src/model/model'; import { MosaicId } from '../../../src/model/mosaic/MosaicId'; import { MosaicNonce } from '../../../src/model/mosaic/MosaicNonce'; import { MosaicProperties } from '../../../src/model/mosaic/MosaicProperties'; @@ -42,6 +43,7 @@ import { Deadline } from '../../../src/model/transaction/Deadline'; import { HashType } from '../../../src/model/transaction/HashType'; import { LinkAction } from '../../../src/model/transaction/LinkAction'; import { LockFundsTransaction } from '../../../src/model/transaction/LockFundsTransaction'; +import { MessageType } from '../../../src/model/transaction/MessageType'; import { ModifyAccountPropertyAddressTransaction } from '../../../src/model/transaction/ModifyAccountPropertyAddressTransaction'; import { ModifyAccountPropertyMosaicTransaction } from '../../../src/model/transaction/ModifyAccountPropertyMosaicTransaction'; import { ModifyMultisigAccountTransaction } from '../../../src/model/transaction/ModifyMultisigAccountTransaction'; @@ -573,6 +575,23 @@ describe('TransactionMapping - createFromDTO (Transaction.toJSON() feed)', () => expect(transaction.message.payload).to.be.equal('test-message'); }); + it('should create TransferTransaction - Encrypted Message', () => { + const transferTransaction = TransferTransaction.create( + Deadline.create(), + Address.createFromRawAddress('SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC'), + [ + NetworkCurrencyMosaic.createRelative(100), + ], + new EncryptedMessage('12324556'), + NetworkType.MIJIN_TEST, + ); + + const transaction = TransactionMapping.createFromDTO(transferTransaction.toJSON()) as TransferTransaction; + + expect((transaction.recipient as Address).plain()).to.be.equal('SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC'); + expect(transaction.message.type).to.be.equal(MessageType.EncryptedMessage); + }); + it('should create AccountLinkTransaction', () => { const accountLinkTransaction = AccountLinkTransaction.create( Deadline.create(), diff --git a/test/model/transaction/EncryptedMessage.spec.ts b/test/model/transaction/EncryptedMessage.spec.ts index 1aca799d39..17b3415e20 100644 --- a/test/model/transaction/EncryptedMessage.spec.ts +++ b/test/model/transaction/EncryptedMessage.spec.ts @@ -16,33 +16,48 @@ import {expect} from 'chai'; import {Account} from '../../../src/model/account/Account'; +import { NetworkType } from '../../../src/model/model'; import {EncryptedMessage} from '../../../src/model/transaction/EncryptedMessage'; -import { TestingAccount } from '../../conf/conf.spec'; describe('EncryptedMessage', () => { - let account: Account; + let sender: Account; + let recipient: Account; before(() => { - account = TestingAccount; + // Catapult-server-bootstrap generated account + sender = Account.createFromPrivateKey('2602F4236B199B3DF762B2AAB46FC3B77D8DDB214F0B62538D3827576C46C108', + NetworkType.MIJIN_TEST); + recipient = Account.createFromPrivateKey('B72F2950498111BADF276D6D9D5E345F04E0D5C9B8342DA983C3395B4CF18F08', + NetworkType.MIJIN_TEST); }); it('should create a encrypted message from a DTO', () => { - const encryptedMessage = EncryptedMessage.createFromDTO('test transaction'); - expect(encryptedMessage.payload).to.be.equal('test transaction'); + const encryptedMessage = EncryptedMessage.createFromPayload('test transaction'); + expect(encryptedMessage.payload).not.to.be.equal('test transaction'); // As DTO returns Hexed payload }); - it('should return encrypted message dto', () => {; - const encryptedMessage = account.encryptMessage('test transaction', account.publicAccount); - const plainMessage = account.decryptMessage(encryptedMessage, account.publicAccount); + it('should return encrypted message dto', () => { + const encryptedMessage = sender.encryptMessage('test transaction', recipient.publicAccount); + const plainMessage = recipient.decryptMessage(encryptedMessage, sender.publicAccount); expect(plainMessage.payload).to.be.equal('test transaction'); }); + it('should decrypt message from raw encrypted message payload', () => { + const payload = 'AE044953E4FF05BC3C14AA10B367E8563D8929680C0D75DBC180F9A7B927D335E66C3BA94266408B366F88B1E503EB' + + '4A3730D9B2F16F1FC16E335262A701CC786E6739A38880A6788530A9E8E4D13C7F'; + const plainMessage = recipient.decryptMessage(new EncryptedMessage(payload), sender.publicAccount); + expect(plainMessage.payload).to.be.equal('Testing simple transfer'); + }); + it('should create an encrypted message from a DTO and decrypt it', () => { + // message payload generated from catapult-server const encryptMessage = EncryptedMessage - .createFromDTO('7245170507448c53d808524221b5d157e19b06f574120a044e48f54dd8e0a4dedbf50ded7ae71' + - 'b90b59949bb6acde81d987ee6648aae9f093b94ac7cc3e8dba0bed8fa04ba286df6b32d2d6d21cbdc4e'); - const plainMessage = account.decryptMessage(encryptMessage, account.publicAccount); - expect(plainMessage.payload).to.be.equal('test transaction'); + .createFromPayload('4132343743314236463730363143314331453730434334373744323831464132343731364343443635313334354' + + '33433383842364546413532364139354144463043354431424545463939373044314337384537413837353435363938424' + + '63336413939413631373630313936324238324246453435454241353037303236424144313032394141364636383242343' + + '339334142453843383931343143413938'); + const plainMessage = recipient.decryptMessage(encryptMessage, sender.publicAccount); + expect(plainMessage.payload).to.be.equal('Testing simple transfer'); }); });