Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions setup1-cli-tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,21 @@ edition = "2018"
name = "public-key-extractor"
path = "src/public_key_extractor.rs"

[[bin]]
name = "decrypt_text"
path = "src/decrypt_text.rs"

[[bin]]
name = "encrypt_text"
path = "src/encrypt_text.rs"

[[bin]]
name = "view-key"
path = "src/view_key.rs"

[dependencies]
snarkvm-dpc = { git = "https://github.com/AleoHQ/snarkVM", rev = "fc997c" }
snarkvm-algorithms = { git = "https://github.com/AleoHQ/snarkVM", rev = "fc997c" }

anyhow = "1.0.38"
age = { version = "0.7", features = ["cli-common", "armor", "plugin"] }
Expand Down
14 changes: 14 additions & 0 deletions setup1-cli-tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,17 @@ view-key > view_key.txt
# To produce a public key out of a private key:
public-key-extractor --path keys.json
```

## Encrypt and Decrypt Guide

Encrypt text:

```bash
cargo run --bin encrypt_text -- --address aleo1ekhu99p7m6e8slh5tpjay28vv3jklmxhtrmphg43t7hvva7hyqgqtkq846 --plaintext "foo"
```

Decrypt text (using `keys.json`):

```bash
cargo run --bin decrypt_text -- --path ./keys.json --ciphertext d62da3d3e9732ef58d98a7a1c987aa7fff8046451f4cdcf552b659171d7120057bf9c5485fcd77c5e3f6c56ed2b6d6df487e327c4de04b5ffe7e6d98761ac00a
```
80 changes: 80 additions & 0 deletions setup1-cli-tools/src/decrypt_text.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use hex::ToHex;
use snarkvm_algorithms::EncryptionScheme;
use snarkvm_dpc::{parameters::testnet2::Testnet2Parameters, Parameters, PrivateKey};

use age::Decryptor;
use anyhow::{anyhow, Result};
use core::str;
use secrecy::{ExposeSecret, SecretString, SecretVec};
use serde::Deserialize;
use std::{fs, io::Read, str::FromStr};
use structopt::StructOpt;
use unic_langid::LanguageIdentifier;

#[derive(Debug, StructOpt)]
#[structopt(name = "Decrypt Text")]
struct Options {
#[structopt(long)]
path: String,
#[structopt(short, long)]
ciphertext: String,
}

// Should be the same as the one from setup1-contributor/src/objects.rs
// Copied here to reduce the compile time, which is
// about 50% longer with setup1-contributor included
#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AleoSetupKeys {
pub encrypted_seed: String,
pub encrypted_private_key: String,
}

fn decrypt(passphrase: &SecretString, encrypted: &str) -> Result<SecretVec<u8>> {
let decoded = SecretVec::new(hex::decode(encrypted)?);
let decryptor = Decryptor::new(decoded.expose_secret().as_slice())?;
match decryptor {
Decryptor::Passphrase(decryptor) => {
let mut output = vec![];
let mut reader = decryptor.decrypt(passphrase, None)?;
reader.read_to_end(&mut output)?;
Ok(SecretVec::new(output))
}
Decryptor::Recipients(_) => Err(anyhow!("Wrong age Decryptor, should be Passphrase, but got Recipients")),
}
}

fn read_private_key(keys_path: &str) -> Result<PrivateKey<Testnet2Parameters>> {
let file_contents = fs::read(keys_path)?;
let keys: AleoSetupKeys = serde_json::from_slice(&file_contents)?;
let passphrase = age::cli_common::read_secret("Enter your Aleo setup passphrase", "Passphrase", None)
.map_err(|e| anyhow!("Error reading passphrase: {}", e))?;
let decrypted = decrypt(&passphrase, &keys.encrypted_private_key)?;
PrivateKey::from_str(std::str::from_utf8(decrypted.expose_secret())?).map_err(Into::into)
}

fn main() {
let options = Options::from_args();
let ciphertext = hex::decode(options.ciphertext).expect("Should decode the ciphertext");

let default_language: LanguageIdentifier = "en-US".parse().expect("Should parse a language indentifier");
age::localizer()
.select(&[default_language])
.expect("Should select the default language");

let scheme = Testnet2Parameters::account_encryption_scheme();

let private_key = read_private_key(&options.path).expect("Should read a private key");
let privkey = private_key
.to_decryption_key()
.expect("Should convert to decryption key");

let plaintext = scheme.decrypt(&privkey, &ciphertext).expect("Should decrypt the text");

println!(
"{}",
str::from_utf8(&plaintext)
.map(|s| s.to_owned())
.unwrap_or_else(|_| plaintext.encode_hex::<String>())
);
}
29 changes: 29 additions & 0 deletions setup1-cli-tools/src/encrypt_text.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use hex::ToHex;
use snarkvm_algorithms::EncryptionScheme;
use snarkvm_dpc::{parameters::testnet2::Testnet2Parameters, Address, Parameters};

use structopt::StructOpt;

#[derive(Debug, StructOpt)]
#[structopt(name = "Encrypt Text")]
struct Options {
#[structopt(short, long)]
address: Address<Testnet2Parameters>,
#[structopt(short, long)]
plaintext: String,
}

fn main() {
let options = Options::from_args();

let scheme = Testnet2Parameters::account_encryption_scheme();
let pubkey = options.address.to_encryption_key();
let randomness = scheme
.generate_randomness(pubkey, &mut rand::thread_rng())
.expect("Unable to generate randomness");
let ciphertext = scheme
.encrypt(pubkey, &randomness, options.plaintext.as_bytes())
.expect("Unable to encrypt the text");

println!("{}", ciphertext.encode_hex::<String>());
}