Transform encryption allows for proxy encryption. It basically uses three keys: one to encrypt the data for the recipient, the second to encrypt it for another recipient, and the third to decrypt the ciphertext.
Transform Encryption in Rust |
Method
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, Bpub), and who are owned by Alice and Bob, respectively. Normally if Alice sends encrypted data to Bob, he will use her public key to encrypt the data, and then Alice would use her private key to decrypt it.
But could we encrypt with Alice’s public key (Apub) and then to be decrypted with Bob’s private key (Bpriv)? This is known as transform enryption, and where we have a special transform key (Apub -> Bpub) using Alice’s private key (Apriv) and Bob’s public key (Bpub). Bob will not be able to discover Alice’s private key from the decryption process.
Now, let’s say that Alice wants to send a secret message to a group (Bob, Carol and Dave), but doesn’t want Eve to read the message. Now:
- Alice takes her public key and encrypts the data and sends it to Trent to store.
- Alice generates a transform key for the group, and desposits this with Trent.
- Bob then asks Trent for the encrypted data, and Trent uses the transform to convert it into a ciphertext for Bob.
- Bob then takes the ciphertext and decrypt it with the group’s private key.
In this way Trent is the proxy for the encrypted data, but Trent cannot read the message that Alice is sending, and Alice cannot see who is requesting the enrypted data.
Code
First we create the with:
cargo new transform
We then go into the transform folder, and add the following to the cargo.toml file:
[package] name = "pr" 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())); }
Finally we simply build with:
cargo build
A sample run is:
Input string: Hello Signing key: c56c504099f144f04a983ae7d2d63371f4dafc8d81692cf495027620a830d36782c92cd95e9b4cbe1f3bcfbd0503d5cc7cec4017c69f7291482e219baac62bb3 Initial Private key: 142eaf727c19dc3f5739872c58b2497f325e72ecfca595b2b0e522a6686122e5 Initial Public key: 705c10bc00660834d4158d8e12f3454b40e71842f9005588cfe2b31452e937b7,679bc54986c77f3bae8e8b9a25f076d251474c0657f5a2f9ce5f75a4f3777e96 Target Private key: 41417931a29d6facc9a8ca912c706d4d02f649fbe4fd1c5e076960981df45b04 Target Public key: 64269f853892b302f8645ac51a8fda719d464b59a889d104c11e927d6175237f,59dabe12de1f8f347903a0737b83e766fe78fe00f51a832a148647e5a716ba0d Decrypted: Hello