Send Encrypted Message
2 min
Sending an encrypted message to another is account is almost identical to Send Message, but with two very important differences:
- You need to use the agreementPrivateKey
Encrypted messaging uses a Diffie-Hellman-Key-Exchange to guarantee that no secret must be sent over the network. That's why encrypted messages are only readable by the sender and the receiver.
Smart Contracts do not have public keys, so they are not able to process encrypted messages.
const {Address, AddressPrefix} = require("@signumjs/core");
const {generateMasterKeys} = require("@signumjs/crypto");
const LedgerHostUrls = {
TestNet: 'http://localhost:6876',
MainNet: 'https://europe.signum.network',
}
async function sendMessage(args) {
try {
const {ledgerType, recipient, message, feeType, passphrase} = args
// we create our client depending on the parameter
const ledger = LedgerClientFactory.create({
nodeHost: LedgerHostUrls[ledgerType])
}
// we check if incoming account is either a Signum Address, or Numeric Id
// eventually, we convert to Numeric Id, if the value is invalid an error will be thrown
const recipientId = Address.create(recipient).getNumericId()
// now we check if the account exists. If it does not exist the method throws an
// exception and the further flow is interrupted.
// Using exception to assert certain conditions is IMHO more robust than checking returned
// values with if-statements. The code is much cleaner
console.info("Verifying recipient...")
await ledger.account.getAccount({accountId: recipientId})
// before we can send we need to get the private signing key from the user
// the agreementPrivateKey is necessary for encrypting the message
const {publicKey, signPrivateKey, agreementPrivateKey} = generateMasterKeys(passphrase)
// as a next step, we use the systems fee suggestion mechanism to give us the current costs for the chosen
// fee type. In this example we let it flexible, but you can fix the fee costs to a minimum, i.e. 0,00735 SIGNA
const suggestedFees = await ledger.network.getSuggestedFees()
// we assume that the feeType is either ['Minimum', 'Cheap', 'Standard', 'Priority']
const selectedFeePlanck = suggestedFees[feeType.toLowerCase()]
// Now, we execute the transaction
// within the method the local signing flow is being executed, i.e.
// the private key is used only locally for signing, but never sent over the network
// for P2P encrypted messages the agreementPrivateKey and the recipients public key is needed
const {transaction} = await ledger.message.sendEncryptedMessage({
recipientId,
message,
messageIsText: true,
feePlanck: selectedFeePlanck,
senderPrivateKey: signPrivateKey,
senderAgreementKey: agreementPrivateKey,
senderPublicKey: publicKey,
recipientPublicKey
})
// now, some final nice message
const addressPrefix = ledgerType === 'MainNet' ? AddressPrefix.MainNet : AddressPrefix.TestNet
console.info(`Successfully sent the message to ${Address.create(recipientId, addressPrefix).getReedSolomonAddress()} - Transaction Id: ${transaction}`)
} catch (e) {
// If the API returns an exception,
// the return error object is of type HttpError
handleError(e);
}
}
// // Our entry point has to be async, as our subsequent calls are.
// // This pattern keeps your app running until all async calls are executed
(async () => {
await sendSigna({
ledgerType: 'TestNet',
recipient: 'TS-QAJA-QW5Y-SWVP-4RVP4',
message: 'This is a simple message',
feeType: 'cheap',
passphrase: 'YourVerySecretPassphraseWhichCannotBeRevealedHere'
});
})();