Skip to content

Commit

Permalink
Merge pull request #174 from martinthomson/wrap-vectors
Browse files Browse the repository at this point in the history
Make the test vectors present more neatly
  • Loading branch information
bifurcation authored Dec 5, 2023
2 parents 72767bc + f8597fe commit d990bb5
Show file tree
Hide file tree
Showing 5 changed files with 404 additions and 321 deletions.
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

0 comments on commit d990bb5

Please sign in to comment.