Envío de un mensaje cifrado

Envía un mensaje cifrado que solo puede ser leído por la cuenta destinataria.

Use case

Imagine que Alice desea registrar la marca de tiempo de un mensaje confidencial para enviarlo a una cuenta que representa su certificado académico.

Alice sabe que enviar una TransferTransaction con un mensaje plano a la red pública hará que el contenido del mensaje esté disponible públicamente.

Por lo tanto, Alice envía un mensaje cifrado que solo puede ser leído por ella misma y por aquellos que tienen acceso al certificado académico.

prerrequisitos

  • Completa la sección de inicio rápido.

  • Completa la guía de envío de tokens y mensajes entre dos cuentas.

  • Crea cuentas para Alice y el certificado.

  • Carga la cuenta de Alice con suficientes bitxor para pagar las tarifas de transacción.

Configuración del caso de uso

Crea dos cuentas: una para Alice y otra para el certificado usando la herramienta CLI.

Ingrese la URL del nodo para acceder a la red.

bitxor-cli account generate --save

Ingresa el tipo de red (MAIN_NET, TEST_NET): TEST_NET
¿Deseas guardarla? [s/n]: s
Ingresa la URL del nodo de Bitxor (Ejemplo: http://localhost:3000): <URL_DEL_NODO>
bitxor-cli account generate --save

Ingresa el tipo de red (MAIN_NET, TEST_NET): TEST_NET
¿Deseas guardarla? [s/n]: s
Ingresa la URL del nodo de Bitxor (Ejemplo: http://localhost:3000): <URL_DEL_NODO>

Método #01: Usando el SDK

Cifrar el mensaje

  1. Crea un mensaje cifrado para el certificado, firmándolo con la cuenta de Alice.

  const networkType = await repositoryFactory.getNetworkType().toPromise();
  // 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,
  );
  const networkType = await repositoryFactory.getNetworkType().toPromise();
  // replace with alice private key
  const alicePrivateKey =
    '1111111111111111111111111111111111111111111111111111111111111111';
  const aliceAccount = bitxor_sdk_1.Account.createFromPrivateKey(
    alicePrivateKey,
    networkType,
  );
  // replace with certificate public key
  const certificatePublicKey =
    '3A537D5A1AF51158C42F80A199BB58351DBF3253C4A6A1B7BD1014682FB595EA';
  const certificatePublicAccount = bitxor_sdk_1.PublicAccount.createFromPublicKey(
    certificatePublicKey,
    networkType,
  );
  const encryptedMessage = aliceAccount.encryptMessage(
    'This message is secret',
    certificatePublicAccount,
  );
  1. Adjunta el mensaje cifrado a una TransferTransaction, estableciendo la dirección del certificado como destinatario.

  const transferTransaction = TransferTransaction.create(
    Deadline.create(epochAdjustment),
    certificatePublicAccount.address,
    [],
    encryptedMessage,
    networkType,
    UInt64.fromUint(2000000),
  );
  const transferTransaction = bitxor_sdk_1.TransferTransaction.create(
    bitxor_sdk_1.Deadline.create(epochAdjustment),
    certificatePublicAccount.address,
    [],
    encryptedMessage,
    networkType,
    bitxor_sdk_1.UInt64.fromUint(2000000),
  );
  1. Firma la transacción con la cuenta de Alice.

Note

Para que la transacción sea válida solo para tu red, incluye la generación del hash de la red. Abre la pestaña del navegador con la URL del nodo /node/info y copia el valor meta.networkGenerationHash.

  const networkGenerationHash = await repositoryFactory
    .getGenerationHash()
    .toPromise();
  const signedTransaction = aliceAccount.sign(
    transferTransaction,
    networkGenerationHash,
  );
  console.log(signedTransaction.hash);
  const networkGenerationHash = await repositoryFactory
    .getGenerationHash()
    .toPromise();
  const signedTransaction = aliceAccount.sign(
    transferTransaction,
    networkGenerationHash,
  );
  console.log(signedTransaction.hash);
  1. Una vez firmada, anuncia la transacción a la red.

  const transactionRepository = repositoryFactory.createTransactionRepository();

  const response = await transactionRepository
    .announce(signedTransaction)
    .toPromise();
  console.log(response);
  const transactionRepository = repositoryFactory.createTransactionRepository();
  const response = await transactionRepository
    .announce(signedTransaction)
    .toPromise();
  console.log(response);

Descifrar el mensaje

Después de que la transacción se confirme, obténla usando el hash de la transacción obtenido en el paso (3). Ahora puedes descifrar el mensaje usando la cuenta del certificado o la dirección de la cuenta.

// 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 = 'NODE_URL';
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 = bitxor_sdk_1.NetworkType.TEST_NET;
// replace with certificate private key
const certificatePrivateKey =
  'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const certificateAccount = bitxor_sdk_1.Account.createFromPrivateKey(
  certificatePrivateKey,
  networkType,
);
// replace with alice public key
const alicePublicKey =
  'D04AB232742BB4AB3A1368BD4615E4E6D0224AB71A016BAF8520A332C9778737';
const alicePublicAccount = bitxor_sdk_1.PublicAccount.createFromPublicKey(
  alicePublicKey,
  networkType,
);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new bitxor_sdk_1.RepositoryFactoryHttp(nodeUrl);
const transactionHttp = repositoryFactory.createTransactionRepository();
// replace with transaction hash
const transactionHash =
  '0000000000000000000000000000000000000000000000000000000000000000';
transactionHttp
  .getTransaction(transactionHash, bitxor_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),
  );

Si lograste leer el mensaje, intenta descifrarlo usando otra cuenta no relacionada para asegurarte de que solo los participantes definidos puedan leer el contenido cifrado.