Why Use Two Keys, When You Can Have Three? Meet Transform (Proxy-) Encryption

Now you should know that you can have a public key and a private key. But now let’s say you have two key pairs: (Apriv, Apub) and (Bpriv…

Photo by Jozsef Hocza on Unsplash

Why Use Two Keys, When You Can Have Three? Meet Transform (Proxy-) Encryption

Now you should know that in public key encryption, that you can have a public key and a private key. Normally if Alice sends encrypted data to Bob, he will use his public key to encrypt the data (Bpub), and then Bob would use his private key (Bpriv) to decrypt it.

But now let’s say we have two key pairs: (Apriv, Apub) and (Bpriv, Bpub), and who are owned by Alice and Bob, respectively. Could we encrypt with Alice’s public key (Apub) and then for it to be decrypted with Bob’s private key (Bpriv)? This is known as transform encryption, and where we have a special transform key (Apub -> Bpub) using Alice’s private key (Apriv) and Bob’s public key (Bpub). We then could pass the encrypted data, encrypted with Alice’s public key (Apub) to Trent, and then to also send Trent the transformation key. Trent can then create the required ciphertext for Bob, and which he can only decrypt with his private key (Bpriv).

Now, let’s say that Alice wants to send a secret message to a group (Bob, Carol and Dave), and where the group has its own public key, and where each of the group has the required private key for the group. Now Alice can use Trent as a trusted proxy:

  1. Alice uses her public key (Apub) and encrypts the data, and sends it to Trent to store.
  2. Alice then generates a transform key for the group, and desposits this with Trent.
  3. Bob then asks Trent for the encrypted data, and Trent uses the transform to convert it into a ciphertext.
  4. Bob then takes the ciphertext from Trent, and then decrypts with the group’s private key.

In this way Trent is the proxy for the encrypted data, but Trent cannot read the secret message that Alice is sending, and Alice cannot see who is requesting the enrypted data. We thus preserve the privacy of the request from Bob, but where Trent cannot read the message.

Source code

So let’s implement using Rust. First we create the Rust project with:

cargo new transform

We then go into the transform folder, and add the following to the cargo.toml file:

[package]
name = "transform"
version = "0.1.0"
authors = ["billbuchanan "]
edition = "2018"
[dependencies]
recrypt = "0.11.0"
hex = "0.4.2"
pad = "0.1"

Next we go into the src folder, and edit the main.rs file with:

use recrypt::prelude::*;
use recrypt::api::Plaintext;
use pad::PadStr;
use std::env;

fn main() {

fn unsize
(x: &[T]) -> &[T] { x }
// create a new recrypt
let recrypt = Recrypt::new();

let mut mystr="Hello";


let args: Vec<String> = env::args().collect();

if args.len() >1 { mystr = &args[1];}



let x=Plaintext::new_from_slice(mystr.pad_to_width_with_char(384,' ').as_bytes());

let pt = x.unwrap();

let signing_keypair= recrypt.generate_ed25519_key_pair();



let (initial_priv_key, initial_pub_key) = recrypt.generate_key_pair().unwrap();

let encrypted_val = recrypt.encrypt(&pt, &initial_pub_key, &signing_keypair).unwrap();


let (target_priv_key, target_pub_key) = recrypt.generate_key_pair().unwrap();


let initial_to_target_transform_key = recrypt.generate_transform_key(
&initial_priv_key,
&target_pub_key,
&signing_keypair).unwrap();


let transformed_val = recrypt.transform(
encrypted_val,
initial_to_target_transform_key,
&signing_keypair).unwrap();


let decrypted_val = recrypt.decrypt(transformed_val, &target_priv_key).unwrap();


println!("\nInput string:\t{} ",mystr);
println!("\nSigning key:\t{} ",hex::encode(unsize(signing_keypair.bytes())));
println!("\nInitial Private key:\t{} ",hex::encode(unsize(initial_priv_key.bytes())));
let (x,y)=initial_pub_key.bytes_x_y();
println!("\nInitial Public key:\t{},{} ",hex::encode(unsize(x)),hex::encode(unsize(y)) );
println!("\nTarget Private key:\t{} ",hex::encode(unsize(target_priv_key.bytes())));
let (x,y)=target_pub_key.bytes_x_y();
println!("\nTarget Public key:\t{},{} ",hex::encode(unsize(x)),hex::encode(unsize(y)) );


println!("\nDecrypted:\t{} ",String::from_utf8_lossy(decrypted_val.bytes()));



}

You can run it here:

https://asecuritysite.com/encryption/rust_transform