Skip to content

Commit

Permalink
fixup! Merge pull request google#184 from google/dependabot/cargo/rus…
Browse files Browse the repository at this point in the history
…t/cargo-5c0860a51f

implement gentag and login test
  • Loading branch information
burgerdev committed Dec 14, 2024
1 parent 7678dc6 commit c2b67ea
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 10 deletions.
139 changes: 136 additions & 3 deletions rust/Cargo.lock

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

3 changes: 3 additions & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ clap = { version = "4", features = ["derive"], optional = true}

[dev-dependencies]
# test
hex = "0.4"
hex-literal = "0.3"
tempfile = "3.14.0"
yaml-rust2 = "0.9"

[lib]
name = "glome"
Expand Down
134 changes: 127 additions & 7 deletions rust/src/cli/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,24 +136,144 @@ fn main() -> io::Result<()> {

#[cfg(test)]
mod tests {
use hex_literal::hex;
use std::{fmt::Debug, path::Path};
use io::Write;
use tempfile::NamedTempFile;
use yaml_rust2::{Yaml, YamlLoader};

use super::*;

#[derive(Debug)]
struct Person {
private: [u8; 32],
public: [u8; 32],
public_cli: String,
}

impl From<&Yaml> for Person {
fn from(case: &Yaml) -> Self {
let private: [u8; 32] = hex::decode(case["private-key"]["hex"].as_str().unwrap()).unwrap().try_into().unwrap();
let public: [u8; 32] = hex::decode(case["public-key"]["hex"].as_str().unwrap()).unwrap().try_into().unwrap();
let public_cli = case["public-key"]["glome-cli"].as_str().unwrap().to_string();
Person {
private,
public,
public_cli,
}
}
}

#[derive(Debug)]
struct TestVector {
name: String,
alice: Person,
bob: Person,
message: String,
tag: String,
host_id_type: String,
host_id: String,
action: String,
}

impl From<&Yaml> for TestVector {
fn from(case: &Yaml) -> Self {
TestVector {
name: format!("vector-{:02}", case["vector"].as_i64().unwrap()),
alice: (&case["alice"]).into(),
bob: (&case["bob"]).into(),
message: case["message"].as_str().unwrap().to_string(),
tag: case["tag"].as_str().unwrap().to_string(),
host_id_type: case["host-id-type"].as_str().unwrap().to_string(),
host_id: case["host-id"].as_str().unwrap().to_string(),
action: case["action"].as_str().unwrap().to_string(),
}
}
}

fn test_vectors() -> Vec<TestVector> {
let rust_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR should be set");
let vectors_file = Path::new(&rust_dir).join("../docs/login-v2-test-vectors.yaml");
let content = fs::read_to_string(vectors_file).expect("test vectors should be readable");
let cases = &YamlLoader::load_from_str(&content).unwrap()[0];

let mut vectors: Vec<TestVector> = Vec::new();
for case in cases.as_vec().expect("top level should be a list") {
vectors.push(case.into());
}
vectors
}

#[test]
fn test_genkey() {
let mut stdout = io::Cursor::new(Vec::new());
genkey(&mut stdout).unwrap();
assert_eq!(32, stdout.get_ref().len())
}

fn cursor_to_string(cursor: &io::Cursor<Vec<u8>>) -> String {
std::str::from_utf8(cursor.get_ref().as_slice()).expect("all test vectors are UTF-8").to_string()
}

#[test]
fn test_pubkey() {
// Login test vector 1 - Alice's key.
let mut stdin = io::Cursor::new(hex!("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"));
let mut stdout = io::Cursor::new(Vec::new());
pubkey(&mut stdin, &mut stdout).unwrap();
let expected = "glome-v1 hSDwCYkwp1R0i33ctD73Wg2_Og0mOBr066SpjqqbTmo=\n";
assert_eq!(expected, std::str::from_utf8(stdout.get_ref().as_slice()).unwrap())
for tc in test_vectors() {
for person in vec![tc.alice, tc.bob] {
let mut stdin = io::Cursor::new(person.private);
let mut stdout = io::Cursor::new(Vec::new());
pubkey(&mut stdin, &mut stdout).unwrap();
let expected = format!("{}\n", person.public_cli);
let actual = cursor_to_string(&stdout);
assert_eq!(expected, actual, "vector {}", tc.name)
}
}
}

fn temp_file(content: &[u8]) -> NamedTempFile {
let mut temp_file = NamedTempFile::new().unwrap();
temp_file.write_all(content).expect("temp file should be writable");
temp_file
}

#[test]
fn test_tag() {
for tc in test_vectors() {
let host = if tc.host_id_type == "" {
tc.host_id
} else {
format!("{}:{}", tc.host_id_type, tc.host_id)
};
// Some test messages contain slashes, but we don't want to add a dependency for URL
// escaping, so we just replace the one character that occurs in the test vectors.
let message = format!("{}/{}", host, tc.action.replace("/", "%2F"));
let mut stdin = io::Cursor::new(message.into_bytes());
let mut stdout = io::Cursor::new(Vec::new());
let key_file = temp_file(&tc.bob.private);
let peer_file = temp_file(tc.alice.public_cli.as_bytes());
let args = TagArgs {
key: key_file.path().to_path_buf(),
peer: peer_file.path().to_path_buf(),
counter: None,
};
gentag(&args, &mut stdin, &mut stdout).expect("gentag should work");

let actual = cursor_to_string(&stdout);
assert_eq!(tc.tag, actual, "vector {}", tc.name)
}
}

#[test]
fn test_login() {
for tc in test_vectors() {
let mut stdout = io::Cursor::new(Vec::new());
let key_file = temp_file(&tc.bob.private);
let args = LoginArgs {
key: key_file.path().to_path_buf(),
challenge: tc.message,
};
login(&args, &mut stdout).expect("login should work");

let actual = cursor_to_string(&stdout);
assert_eq!(tc.tag, actual, "vector {}", tc.name)
}
}
}

0 comments on commit c2b67ea

Please sign in to comment.