Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the test vectors present more neatly #174

Merged
merged 1 commit into from
Dec 5, 2023
Merged
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
187 changes: 117 additions & 70 deletions reference-implementation/examples/test_vectors.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod header {
use super::Hex;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use sframe_reference::header::*;
Expand All @@ -7,13 +8,13 @@ mod header {
pub struct TestVector {
kid: u64,
ctr: u64,
encoded: String,
encoded: Hex,
}

impl TestVector {
fn new(kid: u64, ctr: u64) -> Self {
let header = Header::new(KeyId(kid), Counter(ctr));
let encoded = hex::encode(header.as_slice());
let encoded = Hex::from(header.as_slice());
Self { kid, ctr, encoded }
}

Expand All @@ -34,12 +35,10 @@ mod header {
}

pub fn verify(&self) -> bool {
let encoded_vec = hex::decode(self.encoded.clone()).unwrap();

let encoded = Header::new(KeyId(self.kid), Counter(self.ctr));
let encode_pass = encoded.as_slice() == encoded_vec;
let encode_pass = self.encoded == encoded.as_slice();

let (decoded, _) = Header::parse(&encoded_vec).unwrap();
let (decoded, _) = Header::parse(&self.encoded).unwrap();
let decode_pass = (decoded.kid.0 == self.kid) && (decoded.ctr.0 == self.ctr);

encode_pass && decode_pass
Expand All @@ -61,26 +60,28 @@ header: {encoded}
}

mod aes_ctr_hmac {
use super::Hex;
use aead::{Aead, Key, KeyInit, KeySizeUser, Nonce, Payload};
use aes::Aes128;
use cipher::consts::{U10, U16, U4, U8};
use cipher::ArrayLength;
use cipher::{
consts::{U10, U16, U4, U8},
ArrayLength,
};
use hex_literal::hex;
use serde::{Deserialize, Serialize};
use sframe_reference::aes_ctr_hmac::*;
use sframe_reference::cipher::CipherSuite;
use sframe_reference::{aes_ctr_hmac::*, cipher::CipherSuite};
use sha2::Sha256;

#[derive(Serialize, Deserialize)]
pub struct TestVector {
cipher_suite: u16,
key: String,
enc_key: String,
auth_key: String,
nonce: String,
aad: String,
pt: String,
ct: String,
key: Hex,
enc_key: Hex,
auth_key: Hex,
nonce: Hex,
aad: Hex,
pt: Hex,
ct: Hex,
}

impl TestVector {
Expand Down Expand Up @@ -111,13 +112,13 @@ mod aes_ctr_hmac {

Self {
cipher_suite: cipher_suite.0,
key: hex::encode(key),
enc_key: hex::encode(cipher.enc_key),
auth_key: hex::encode(cipher.auth_key),
nonce: hex::encode(nonce),
aad: hex::encode(aad),
pt: hex::encode(pt),
ct: hex::encode(ct),
key: Hex::from(key),
enc_key: Hex::from(cipher.enc_key),
auth_key: Hex::from(cipher.auth_key),
nonce: Hex::from(nonce),
aad: Hex::from(aad),
pt: Hex::from(pt),
ct: Hex::from(ct),
}
}

Expand All @@ -136,30 +137,24 @@ mod aes_ctr_hmac {
T: ArrayLength<u8>,
AesCtrHmac<C, D, T>: KeySizeUser + KeyInit,
{
let key = hex::decode(self.key.clone()).unwrap();
let nonce = hex::decode(self.nonce.clone()).unwrap();
let aad = hex::decode(self.aad.clone()).unwrap();
let pt = hex::decode(self.pt.clone()).unwrap();
let ct = hex::decode(self.ct.clone()).unwrap();

let key = Key::<AesCtrHmac<C, D, T>>::from_slice(&key);
let nonce = Nonce::<AesCtrHmac<C, D, T>>::from_slice(&nonce);
let key = Key::<AesCtrHmac<C, D, T>>::from_slice(&self.key);
let nonce = Nonce::<AesCtrHmac<C, D, T>>::from_slice(&self.nonce);

let cipher = AesCtrHmac::<C, D, T>::new(&key);

let payload = Payload {
msg: &pt,
aad: &aad,
msg: &self.pt,
aad: &self.aad,
};
let encrypted = cipher.encrypt(&nonce, payload).unwrap();
let encrypt_pass = encrypted == ct;
let encrypt_pass = self.ct == encrypted;

let payload = Payload {
msg: &ct,
aad: &aad,
msg: &self.ct,
aad: &self.aad,
};
let decrypted = cipher.decrypt(&nonce, payload).unwrap();
let decrypt_pass = decrypted == pt;
let decrypt_pass = self.pt == decrypted;

encrypt_pass && decrypt_pass
}
Expand Down Expand Up @@ -206,6 +201,7 @@ ct: {ct}
}

mod sframe {
use super::Hex;
use hex_literal::hex;
use serde::{Deserialize, Serialize};
use sframe_reference::*;
Expand All @@ -215,17 +211,17 @@ mod sframe {
cipher_suite: u16,
kid: u64,
ctr: u64,
base_key: String,
sframe_key_label: String,
sframe_salt_label: String,
sframe_secret: String,
sframe_key: String,
sframe_salt: String,
metadata: String,
nonce: String,
aad: String,
pt: String,
ct: String,
base_key: Hex,
sframe_key_label: Hex,
sframe_salt_label: Hex,
sframe_secret: Hex,
sframe_key: Hex,
sframe_salt: Hex,
metadata: Hex,
nonce: Hex,
aad: Hex,
pt: Hex,
ct: Hex,
}

impl TestVector {
Expand All @@ -246,17 +242,17 @@ mod sframe {
cipher_suite: cipher_suite.0,
kid: kid.0,
ctr: ctr.0,
base_key: hex::encode(base_key),
sframe_key_label: hex::encode(cipher.sframe_key_label()),
sframe_salt_label: hex::encode(cipher.sframe_salt_label()),
sframe_secret: hex::encode(cipher.sframe_secret()),
sframe_key: hex::encode(cipher.sframe_key()),
sframe_salt: hex::encode(cipher.sframe_salt()),
metadata: hex::encode(metadata),
nonce: hex::encode(vals.nonce),
aad: hex::encode(vals.aad),
pt: hex::encode(pt),
ct: hex::encode(ct),
base_key: Hex::from(base_key),
sframe_key_label: Hex::from(cipher.sframe_key_label()),
sframe_salt_label: Hex::from(cipher.sframe_salt_label()),
sframe_secret: Hex::from(cipher.sframe_secret()),
sframe_key: Hex::from(cipher.sframe_key()),
sframe_salt: Hex::from(cipher.sframe_salt()),
metadata: Hex::from(metadata),
nonce: Hex::from(vals.nonce),
aad: Hex::from(vals.aad),
pt: Hex::from(pt),
ct: Hex::from(ct),
}
}

Expand All @@ -271,20 +267,16 @@ mod sframe {
let cipher_suite = CipherSuite(self.cipher_suite);
let kid = KeyId(self.kid);
let ctr = Counter(self.ctr);
let base_key = hex::decode(self.base_key.clone()).unwrap();
let metadata = hex::decode(self.metadata.clone()).unwrap();
let pt = hex::decode(self.pt.clone()).unwrap();
let ct = hex::decode(self.ct.clone()).unwrap();

let mut ctx = SFrameContext::new(cipher_suite);
ctx.add_send_key(kid, &base_key).unwrap();
let (encrypted, _) = ctx.encrypt_raw(kid, ctr, &metadata, &pt).unwrap();
let encrypt_pass = encrypted == ct;
ctx.add_send_key(kid, &self.base_key).unwrap();
let (encrypted, _) = ctx.encrypt_raw(kid, ctr, &self.metadata, &self.pt).unwrap();
let encrypt_pass = self.ct == encrypted;

let mut ctx = SFrameContext::new(cipher_suite);
ctx.add_recv_key(kid, &base_key).unwrap();
let (decrypted, _) = ctx.decrypt(&metadata, &ct).unwrap();
let decrypt_pass = decrypted == pt;
ctx.add_recv_key(kid, &self.base_key).unwrap();
let (decrypted, _) = ctx.decrypt(&self.metadata, &self.ct).unwrap();
let decrypt_pass = self.pt == decrypted;

encrypt_pass && decrypt_pass
}
Expand Down Expand Up @@ -331,9 +323,64 @@ ct: {ct}
}
}

use std::fmt::Display;

use clap::{Parser, Subcommand, ValueEnum};
use serde::{Deserialize, Serialize};

struct Hex(Vec<u8>);

impl Display for Hex {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for (i, c) in self.0.chunks(8).enumerate() {
if i % 3 == 0 {
if i > 0 {
f.write_str("\n ")?;
}
} else {
f.write_str(" ")?;
}
f.write_str(&hex::encode(c))?;
}
Ok(())
}
}

impl<T: AsRef<[u8]>> From<T> for Hex {
fn from(value: T) -> Self {
Hex(Vec::from(value.as_ref()))
}
}

impl Serialize for Hex {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(&hex::encode(&self.0))
}
}

impl<'de> Deserialize<'de> for Hex {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
Ok(Self(
hex::decode(<String as Deserialize<'de>>::deserialize(deserializer)?)
.expect("invalid hex"),
// TODO: this should map to an error, but we can't instantiation `D::Error`.
))
}
}

impl std::ops::Deref for Hex {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<T: AsRef<[u8]>> PartialEq<T> for Hex {
fn eq(&self, other: &T) -> bool {
&self.0 == other.as_ref()
}
}

#[derive(Copy, Clone, ValueEnum)]
enum TestVectorType {
Header,
Expand Down
8 changes: 5 additions & 3 deletions reference-implementation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ pub mod header;
/// Cipher agility layer
pub mod cipher;

pub use crate::cipher::{new_cipher, Cipher, CipherSuite, SFrameIntermediateValues};
pub use crate::header::{Counter, Header, KeyId};
pub use crate::{
cipher::{new_cipher, Cipher, CipherSuite, SFrameIntermediateValues},
header::{Counter, Header, KeyId},
};
use std::collections::HashMap;

/// Errors that can result from SFrame operations
Expand Down Expand Up @@ -233,7 +235,7 @@ mod test {

#[test]
fn round_trip() {
for cipher_suite in ALL_CIPHER_SUITES.clone().into_iter() {
for &cipher_suite in &ALL_CIPHER_SUITES {
round_trip_one(cipher_suite);
}
}
Expand Down
51 changes: 30 additions & 21 deletions test-vectors/aes-ctr-hmac.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
~~~
cipher_suite: 0x0001
key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f
enc_key: 000102030405060708090a0b0c0d0e0f
auth_key: 101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f
nonce: 101112131415161718191a1b
aad: 4945544620534672616d65205747
pt: 64726166742d696574662d736672616d652d656e63
ct: 6339af04ada1d064688a442b8dc69d5b6bfa40f4bef0583e8081069cc60705
key: 0001020304050607 08090a0b0c0d0e0f 1011121314151617
18191a1b1c1d1e1f 2021222324252627 28292a2b2c2d2e2f
enc_key: 0001020304050607 08090a0b0c0d0e0f
auth_key: 1011121314151617 18191a1b1c1d1e1f 2021222324252627
28292a2b2c2d2e2f
nonce: 1011121314151617 18191a1b
aad: 4945544620534672 616d65205747
pt: 64726166742d6965 74662d736672616d 652d656e63
ct: 6339af04ada1d064 688a442b8dc69d5b 6bfa40f4bef0583e
8081069cc60705
~~~

~~~
cipher_suite: 0x0002
key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f
enc_key: 000102030405060708090a0b0c0d0e0f
auth_key: 101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f
nonce: 101112131415161718191a1b
aad: 4945544620534672616d65205747
pt: 64726166742d696574662d736672616d652d656e63
ct: 6339af04ada1d064688a442b8dc69d5b6bfa40f4be6e93b7da076927bb
key: 0001020304050607 08090a0b0c0d0e0f 1011121314151617
18191a1b1c1d1e1f 2021222324252627 28292a2b2c2d2e2f
enc_key: 0001020304050607 08090a0b0c0d0e0f
auth_key: 1011121314151617 18191a1b1c1d1e1f 2021222324252627
28292a2b2c2d2e2f
nonce: 1011121314151617 18191a1b
aad: 4945544620534672 616d65205747
pt: 64726166742d6965 74662d736672616d 652d656e63
ct: 6339af04ada1d064 688a442b8dc69d5b 6bfa40f4be6e93b7
da076927bb
~~~

~~~
cipher_suite: 0x0003
key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f
enc_key: 000102030405060708090a0b0c0d0e0f
auth_key: 101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f
nonce: 101112131415161718191a1b
aad: 4945544620534672616d65205747
pt: 64726166742d696574662d736672616d652d656e63
ct: 6339af04ada1d064688a442b8dc69d5b6bfa40f4be09480509
key: 0001020304050607 08090a0b0c0d0e0f 1011121314151617
18191a1b1c1d1e1f 2021222324252627 28292a2b2c2d2e2f
enc_key: 0001020304050607 08090a0b0c0d0e0f
auth_key: 1011121314151617 18191a1b1c1d1e1f 2021222324252627
28292a2b2c2d2e2f
nonce: 1011121314151617 18191a1b
aad: 4945544620534672 616d65205747
pt: 64726166742d6965 74662d736672616d 652d656e63
ct: 6339af04ada1d064 688a442b8dc69d5b 6bfa40f4be094805
09
~~~

Loading
Loading