nucypher / taco-web

🌮 A TypeScript client for TACo (Threshold Access Control)
https://docs.threshold.network/app-development/threshold-access-control-tac
GNU General Public License v3.0
14 stars 22 forks source link

Allow re-encryption using public key on decrypt request #565

Open joeljablonski opened 1 month ago

joeljablonski commented 1 month ago

Is it possible to pass in a public key as a customParameter when decrypting, and for the decrypted message to be re-encrypted using the public key before being received?

I have a particular use case, where I have a typescript function running on a public node where all communication in and out is insecure (decentralised compute). Therefore I can only send/receive encrypted data. I generate a new public/private key pair at runtime and then I should be able to be able to pass in a public key with my decrypt request, where the result is re-encrypted using the public key.

Example code to decrypt:

config();

import {
  ThresholdMessageKit,
  decrypt,
  domains,
  getPorterUri,
  initialize as initializeTaco,
} from "@nucypher/taco";

import { generateKeyPairSync, privateDecrypt } from "crypto";
import { ethers } from "hardhat";

async function decryptMessageOnInsecureChannel(encryptedBytes: Uint8Array) {
  const polygonProvider = new ethers.providers.JsonRpcProvider(
    "https://polygon-amoy.drpc.org",
    80002
  );

  const DOMAIN = domains.TESTNET;

  await initializeTaco();

  const { publicKey, privateKey } = generateKeyPairSync("rsa", {
    modulusLength: 2048,
    publicKeyEncoding: {
      type: "spki",
      format: "pem",
    },
    privateKeyEncoding: {
      type: "pkcs8",
      format: "pem",
    },
  });

  const messageKit = ThresholdMessageKit.fromBytes(encryptedBytes);

  const customParameters = {
    publicKey: publicKey,
  };

  const reencrypted = await decrypt(
    polygonProvider,
    DOMAIN,
    messageKit,
    getPorterUri(DOMAIN),
    undefined,
    customParameters
  );

  const messageBuffer = privateDecrypt(privateKey, reencrypted);

  const message = new TextDecoder().decode(messageBuffer);
}

I feel like this shouldn't actually be that difficult to achieve. On a "privateDecrypt" request on the client-side, a new public/private key pair could be generated, then the public key is provided with the request. The TACo nodes check the access conditions and then re-encrypt the fragments using the public key before sending them. Then where the fragments are collected client-side, they could each be decrypted using the private key previously generated before constructing the final decrypted message.