Send an encrypted message that only can be read by the recipient account.
Imagine that Alice wants to timestamp a sensitive message to send to an account representing her academic certificate.
Alice knows that sending a TransferTransaction with a plain message to the public network will make the content of the message publicly available.
Thus, Alice sends an encrypted message that is only readable by herself and those with access to the academic certificate.
symbol.xym
to pay for transaction fees.Create two accounts: one for Alice and another for the certificate with the CLI tool.
symbol-cli account generate --save
Enter network type (MIJIN_TEST, MIJIN, MAIN_NET, TEST_NET): TEST_NET
Do you want to save it? [y/n]: y
Enter a Symbol Node URL. (Example: http://localhost:3000): http://api-01.us-east-1.096x.symboldev.network:3000/
Insert profile name: alice
symbol-cli account generate --save
Enter network type (MIJIN_TEST, MIJIN, MAIN_NET, TEST_NET): TEST_NET
Do you want to save it? [y/n]: y
Enter a Symbol Node URL. (Example: http://localhost:3000): http://api-01.us-east-1.096x.symboldev.network:3000/
Insert profile name: certificate
// replace with network type
const networkType = NetworkType.TEST_NET;
// replace with alice private key
const alicePrivateKey = '1111111111111111111111111111111111111111111111111111111111111111';
const aliceAccount = Account.createFromPrivateKey(alicePrivateKey, networkType);
// replace with certificate public key
const certificatePublicKey = '3A537D5A1AF51158C42F80A199BB58351DBF3253C4A6A1B7BD1014682FB595EA';
const certificatePublicAccount = PublicAccount.createFromPublicKey(certificatePublicKey, networkType);
const encryptedMessage = aliceAccount
.encryptMessage('This message is secret',
certificatePublicAccount);
// replace with network type
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
// replace with alice private key
const alicePrivateKey = '1111111111111111111111111111111111111111111111111111111111111111';
const aliceAccount = symbol_sdk_1.Account.createFromPrivateKey(alicePrivateKey, networkType);
// replace with certificate public key
const certificatePublicKey = '3A537D5A1AF51158C42F80A199BB58351DBF3253C4A6A1B7BD1014682FB595EA';
const certificatePublicAccount = symbol_sdk_1.PublicAccount.createFromPublicKey(certificatePublicKey, networkType);
const encryptedMessage = aliceAccount
.encryptMessage('This message is secret', certificatePublicAccount);
const transferTransaction = TransferTransaction.create(
Deadline.create(),
certificatePublicAccount.address,
[],
encryptedMessage,
networkType,
UInt64.fromUint(2000000));
const transferTransaction = symbol_sdk_1.TransferTransaction.create(symbol_sdk_1.Deadline.create(), certificatePublicAccount.address, [], encryptedMessage, networkType, symbol_sdk_1.UInt64.fromUint(2000000));
Note
To make the transaction only valid for your network, include the network generation hash. Open nodeUrl + '/node/info'
in a new browser tab and copy the meta.networkGenerationHash
value.
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash = '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = aliceAccount.sign(transferTransaction, networkGenerationHash);
console.log(signedTransaction.hash);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash = '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = aliceAccount.sign(transferTransaction, networkGenerationHash);
console.log(signedTransaction.hash);
const nodeUrl = 'http://api-01.us-east-1.096x.symboldev.network:3000';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp
.announce(signedTransaction)
.subscribe((x) => console.log(x), (err) => console.error(err));
const nodeUrl = 'http://api-01.us-east-1.096x.symboldev.network:3000';
const repositoryFactory = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
transactionHttp
.announce(signedTransaction)
.subscribe((x) => console.log(x), (err) => console.error(err));
After the transaction gets confirmed, fetch it using the transaction hash output from (3). You can now decrypt the message using either the certificate account or address account.
// replace with network type
const networkType = NetworkType.TEST_NET;
// replace with certificate private key
const certificatePrivateKey = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const certificateAccount = Account.createFromPrivateKey(certificatePrivateKey, networkType);
// replace with alice public key
const alicePublicKey = 'D04AB232742BB4AB3A1368BD4615E4E6D0224AB71A016BAF8520A332C9778737';
const alicePublicAccount = PublicAccount.createFromPublicKey(alicePublicKey, networkType);
// replace with node endpoint
const nodeUrl = 'http://api-01.us-east-1.096x.symboldev.network:3000';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
// replace with transaction hash
const transactionHash = '0000000000000000000000000000000000000000000000000000000000000000';
transactionHttp
.getTransaction(transactionHash, TransactionGroup.Confirmed)
.pipe(
map( (x) => x as TransferTransaction ),
)
.subscribe((transaction) => {
console.log('Raw message: ', transaction.message.payload);
console.log('Message: ', certificateAccount.decryptMessage(
transaction.message,
alicePublicAccount).payload);
}, ((err) => console.log(err)));
// replace with network type
const networkType = symbol_sdk_1.NetworkType.TEST_NET;
// replace with certificate private key
const certificatePrivateKey = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const certificateAccount = symbol_sdk_1.Account.createFromPrivateKey(certificatePrivateKey, networkType);
// replace with alice public key
const alicePublicKey = 'D04AB232742BB4AB3A1368BD4615E4E6D0224AB71A016BAF8520A332C9778737';
const alicePublicAccount = symbol_sdk_1.PublicAccount.createFromPublicKey(alicePublicKey, networkType);
// replace with node endpoint
const nodeUrl = 'http://api-01.us-east-1.096x.symboldev.network:3000';
const repositoryFactory = new symbol_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
// replace with transaction hash
const transactionHash = '0000000000000000000000000000000000000000000000000000000000000000';
transactionHttp
.getTransaction(transactionHash, symbol_sdk_1.TransactionGroup.Confirmed)
.pipe(operators_1.map((x) => x))
.subscribe((transaction) => {
console.log('Raw message: ', transaction.message.payload);
console.log('Message: ', certificateAccount.decryptMessage(transaction.message, alicePublicAccount).payload);
}, ((err) => console.log(err)));
If you managed to read the message, try to decrypt it using another unrelated account to ensure that only the defined participants can read the encrypted content.
Did you find what you were looking for? Give us your feedback.