use crate::Passki;
use aws_lc_rs::rsa::KeySize;
use aws_lc_rs::signature::{KeyPair, RsaKeyPair};
pub fn create_test_attestation_object(algorithm: i32) -> Vec<u8> {
use ciborium::Value;
let mut auth_data = Vec::new();
auth_data.extend_from_slice(&[0u8; 32]); auth_data.push(0x45); auth_data.extend_from_slice(&[0, 0, 0, 0]); auth_data.extend_from_slice(&[0u8; 16]); auth_data.extend_from_slice(&[0, 16]); auth_data.extend_from_slice(&[1u8; 16]);
let mut cose_key = Vec::new();
cose_key.push((Value::Integer(1.into()), Value::Integer(2.into()))); cose_key.push((Value::Integer(3.into()), Value::Integer(algorithm.into())));
if algorithm == -7 {
cose_key.push((Value::Integer((-1).into()), Value::Integer(1.into()))); cose_key.push((Value::Integer((-2).into()), Value::Bytes(vec![2u8; 32]))); cose_key.push((Value::Integer((-3).into()), Value::Bytes(vec![3u8; 32]))); } else if algorithm == -8 {
cose_key.push((Value::Integer((-1).into()), Value::Integer(6.into()))); cose_key.push((Value::Integer((-2).into()), Value::Bytes(vec![4u8; 32]))); }
let mut cose_key_bytes = Vec::new();
ciborium::into_writer(&Value::Map(cose_key), &mut cose_key_bytes).unwrap();
auth_data.extend_from_slice(&cose_key_bytes);
let mut att_obj = Vec::new();
att_obj.push((
Value::Text("fmt".to_string()),
Value::Text("none".to_string()),
));
att_obj.push((Value::Text("authData".to_string()), Value::Bytes(auth_data)));
att_obj.push((Value::Text("attStmt".to_string()), Value::Map(Vec::new())));
let mut result = Vec::new();
ciborium::into_writer(&Value::Map(att_obj), &mut result).unwrap();
result
}
pub fn create_test_client_data_json(challenge: &[u8], origin: &str) -> Vec<u8> {
let client_data = serde_json::json!({
"type": "webauthn.create",
"challenge": Passki::base64_encode(challenge),
"origin": origin,
"crossOrigin": false
});
serde_json::to_vec(&client_data).unwrap()
}
pub fn create_test_authenticator_data(counter: u32) -> Vec<u8> {
let mut auth_data = Vec::new();
auth_data.extend_from_slice(&[0u8; 32]); auth_data.push(0x01); auth_data.extend_from_slice(&counter.to_be_bytes()); auth_data
}
pub fn create_test_auth_client_data_json(challenge: &[u8], origin: &str) -> Vec<u8> {
let client_data = serde_json::json!({
"type": "webauthn.get",
"challenge": Passki::base64_encode(challenge),
"origin": origin,
"crossOrigin": false
});
serde_json::to_vec(&client_data).unwrap()
}
pub fn create_eddsa_cose_key(public_key: &[u8; 32]) -> Vec<u8> {
use ciborium::Value;
let mut cose_key = Vec::new();
cose_key.push((Value::Integer(1.into()), Value::Integer(1.into()))); cose_key.push((Value::Integer(3.into()), Value::Integer((-8).into()))); cose_key.push((Value::Integer((-1).into()), Value::Integer(6.into()))); cose_key.push((
Value::Integer((-2).into()),
Value::Bytes(public_key.to_vec()),
));
let mut result = Vec::new();
ciborium::into_writer(&Value::Map(cose_key), &mut result).unwrap();
result
}
pub fn create_es256_cose_key(x: &[u8], y: &[u8]) -> Vec<u8> {
use ciborium::Value;
let mut cose_key = Vec::new();
cose_key.push((Value::Integer(1.into()), Value::Integer(2.into()))); cose_key.push((Value::Integer(3.into()), Value::Integer((-7).into()))); cose_key.push((Value::Integer((-1).into()), Value::Integer(1.into()))); cose_key.push((Value::Integer((-2).into()), Value::Bytes(x.to_vec()))); cose_key.push((Value::Integer((-3).into()), Value::Bytes(y.to_vec())));
let mut result = Vec::new();
ciborium::into_writer(&Value::Map(cose_key), &mut result).unwrap();
result
}
pub fn create_es384_cose_key(x: &[u8], y: &[u8]) -> Vec<u8> {
use ciborium::Value;
let mut cose_key = Vec::new();
cose_key.push((Value::Integer(1.into()), Value::Integer(2.into()))); cose_key.push((Value::Integer(3.into()), Value::Integer((-35).into()))); cose_key.push((Value::Integer((-1).into()), Value::Integer(2.into()))); cose_key.push((Value::Integer((-2).into()), Value::Bytes(x.to_vec()))); cose_key.push((Value::Integer((-3).into()), Value::Bytes(y.to_vec())));
let mut result = Vec::new();
ciborium::into_writer(&Value::Map(cose_key), &mut result).unwrap();
result
}
pub fn create_rs256_cose_key(n: &[u8], e: &[u8]) -> Vec<u8> {
use ciborium::Value;
let mut cose_key = Vec::new();
cose_key.push((Value::Integer(1.into()), Value::Integer(3.into()))); cose_key.push((Value::Integer(3.into()), Value::Integer((-257).into()))); cose_key.push((Value::Integer((-1).into()), Value::Bytes(n.to_vec()))); cose_key.push((Value::Integer((-2).into()), Value::Bytes(e.to_vec())));
let mut result = Vec::new();
ciborium::into_writer(&Value::Map(cose_key), &mut result).unwrap();
result
}
pub fn create_rs384_cose_key(n: &[u8], e: &[u8]) -> Vec<u8> {
use ciborium::Value;
let mut cose_key = Vec::new();
cose_key.push((Value::Integer(1.into()), Value::Integer(3.into()))); cose_key.push((Value::Integer(3.into()), Value::Integer((-258).into()))); cose_key.push((Value::Integer((-1).into()), Value::Bytes(n.to_vec()))); cose_key.push((Value::Integer((-2).into()), Value::Bytes(e.to_vec())));
let mut result = Vec::new();
ciborium::into_writer(&Value::Map(cose_key), &mut result).unwrap();
result
}
pub fn create_test_rsa_keypair() -> (RsaKeyPair, Vec<u8>, Vec<u8>) {
let key_pair = RsaKeyPair::generate(KeySize::Rsa2048).unwrap();
let pub_key = key_pair.public_key();
let pub_key_bytes = pub_key.as_ref();
let (n, e) = parse_rsa_public_key(pub_key_bytes);
(key_pair, n, e)
}
fn parse_rsa_public_key(pub_key_bytes: &[u8]) -> (Vec<u8>, Vec<u8>) {
let mut pos = 0;
assert_eq!(pub_key_bytes[pos], 0x30);
pos += 1;
let (_, len_bytes) = read_der_length(&pub_key_bytes[pos..]);
pos += len_bytes;
assert_eq!(pub_key_bytes[pos], 0x02);
pos += 1;
let (n_len, len_bytes) = read_der_length(&pub_key_bytes[pos..]);
pos += len_bytes;
let mut n = pub_key_bytes[pos..pos + n_len].to_vec();
if !n.is_empty() && n[0] == 0x00 {
n.remove(0);
}
pos += n_len;
assert_eq!(pub_key_bytes[pos], 0x02);
pos += 1;
let (e_len, len_bytes) = read_der_length(&pub_key_bytes[pos..]);
pos += len_bytes;
let mut e = pub_key_bytes[pos..pos + e_len].to_vec();
if !e.is_empty() && e[0] == 0x00 {
e.remove(0);
}
(n, e)
}
fn read_der_length(data: &[u8]) -> (usize, usize) {
if data[0] < 0x80 {
(data[0] as usize, 1)
} else {
let num_bytes = (data[0] & 0x7F) as usize;
let mut len = 0usize;
for i in 0..num_bytes {
len = (len << 8) | (data[1 + i] as usize);
}
(len, 1 + num_bytes)
}
}