mirror of
https://gitlab.com/fabinfra/fabaccess/nfc_rs.git
synced 2025-03-12 06:41:46 +01:00
improved card crypto implementation
This commit is contained in:
parent
5667560ce4
commit
32cb8e6639
@ -12,6 +12,9 @@ aes = "0.6.0"
|
||||
block-modes = "0.7.0"
|
||||
simple-error = "0.2.3"
|
||||
hex = "0.4.2"
|
||||
num-traits = "0.2.14"
|
||||
num-derive = "0.3.3"
|
||||
rand = "0.8.3"
|
||||
|
||||
[dev-dependencies]
|
||||
hex-literal = "0.3.1"
|
@ -2,30 +2,37 @@ use aes::Aes128;
|
||||
use block_modes::{BlockMode, Cbc};
|
||||
use block_modes::block_padding::NoPadding;
|
||||
use crate::error::{Result, Error};
|
||||
use super::Cipher;
|
||||
|
||||
type Aes128Cbc = Cbc<Aes128, NoPadding>;
|
||||
|
||||
pub const KEY_LEN: usize = 16;
|
||||
pub struct AES {}
|
||||
|
||||
pub fn encrypt (data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = Aes128Cbc::new_var(&key, &iv)?;
|
||||
impl Cipher for AES {
|
||||
const BLOCK_SIZE: usize = 16;
|
||||
const KEY_SIZE: usize = 16;
|
||||
|
||||
return Ok(cipher.encrypt_vec(data));
|
||||
}
|
||||
fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = Aes128Cbc::new_var(&key, &iv)?;
|
||||
|
||||
pub fn decrypt(data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = Aes128Cbc::new_var(&key, &iv)?;
|
||||
return Ok(cipher.encrypt_vec(data));
|
||||
}
|
||||
|
||||
let result = cipher.decrypt_vec(data);
|
||||
return match result {
|
||||
Ok(data) => {Ok(data)}
|
||||
Err(err) => {Err(Error::BlockModeError(err))}
|
||||
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = Aes128Cbc::new_var(&key, &iv)?;
|
||||
|
||||
let result = cipher.decrypt_vec(data);
|
||||
return match result {
|
||||
Ok(data) => { Ok(data) }
|
||||
Err(err) => { Err(Error::BlockModeError(err)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex_literal::hex;
|
||||
use crate::crypto::cipher::Cipher;
|
||||
|
||||
#[test]
|
||||
fn encrypt() {
|
||||
@ -33,7 +40,7 @@ mod tests {
|
||||
let key = hex!("e7aff3361c3e85347993c3219a87d24b");
|
||||
let iv = hex!("00000000000000000000000000000000");
|
||||
|
||||
let data_enc = crate::crypto::cipher::aes::encrypt(&data, key, &iv).unwrap();
|
||||
let data_enc = crate::crypto::cipher::aes::AES::encrypt(&data, &key, &iv).unwrap();
|
||||
|
||||
let data_enc_expected = hex!("3c79d74a4969ba7123e5d8f6df24493112d221fd131a4617d0eda5d92ccc1b46");
|
||||
|
||||
|
@ -6,7 +6,10 @@ pub mod tdes_3k;
|
||||
use crate::error::Result;
|
||||
|
||||
//TODO: impl this for all the ciphers
|
||||
trait Cipher {
|
||||
pub trait Cipher {
|
||||
const BLOCK_SIZE: usize;
|
||||
const KEY_SIZE: usize;
|
||||
|
||||
fn encrypt (data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>>;
|
||||
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>>;
|
||||
}
|
@ -3,31 +3,38 @@ use des::TdesEde2;
|
||||
use block_modes::{BlockMode, Cbc};
|
||||
use block_modes::block_padding::NoPadding;
|
||||
use crate::error::{Result, Error};
|
||||
use crate::crypto::cipher::Cipher;
|
||||
|
||||
type TDesEde2Cbc = Cbc<TdesEde2, NoPadding>;
|
||||
|
||||
pub const KEY_LEN: usize = 16;
|
||||
pub struct Tdes {}
|
||||
|
||||
pub fn encrypt (data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||
impl Cipher for Tdes {
|
||||
const BLOCK_SIZE: usize = 8;
|
||||
const KEY_SIZE: usize = 16;
|
||||
|
||||
return Ok(cipher.encrypt_vec(data));
|
||||
}
|
||||
fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||
|
||||
pub fn decrypt(data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||
return Ok(cipher.encrypt_vec(data));
|
||||
}
|
||||
|
||||
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||
|
||||
|
||||
let result = cipher.decrypt_vec(data);
|
||||
return match result {
|
||||
Ok(data) => {Ok(data)}
|
||||
Err(err) => {Err(Error::BlockModeError(err))}
|
||||
let result = cipher.decrypt_vec(data);
|
||||
return match result {
|
||||
Ok(data) => { Ok(data) }
|
||||
Err(err) => { Err(Error::BlockModeError(err)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex_literal::hex;
|
||||
use crate::crypto::cipher::Cipher;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
@ -36,7 +43,7 @@ mod tests {
|
||||
let key = hex!("00000000000000000000000000000000");
|
||||
let iv = hex!("00000000000000000000000000000000");
|
||||
|
||||
let data_enc = crate::crypto::cipher::tdes::encrypt(&data, key, &iv).unwrap();
|
||||
let data_enc = crate::crypto::cipher::tdes::Tdes::encrypt(&data, &key, &iv).unwrap();
|
||||
|
||||
let data_enc_expected = hex!("");
|
||||
|
||||
|
@ -3,31 +3,38 @@ use des::TdesEde2;
|
||||
use block_modes::{BlockMode, Cbc};
|
||||
use block_modes::block_padding::NoPadding;
|
||||
use crate::error::{Result, Error};
|
||||
use crate::crypto::cipher::Cipher;
|
||||
|
||||
type TDesEde2Cbc = Cbc<TdesEde2, NoPadding>;
|
||||
|
||||
pub const KEY_LEN: usize = 16;
|
||||
pub struct Tdes2k {}
|
||||
|
||||
pub fn encrypt (data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||
impl Cipher for Tdes2k {
|
||||
const BLOCK_SIZE: usize = 8;
|
||||
const KEY_SIZE: usize = 16;
|
||||
|
||||
return Ok(cipher.encrypt_vec(data));
|
||||
}
|
||||
fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||
|
||||
pub fn decrypt(data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||
return Ok(cipher.encrypt_vec(data));
|
||||
}
|
||||
|
||||
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||
|
||||
|
||||
let result = cipher.decrypt_vec(data);
|
||||
return match result {
|
||||
Ok(data) => {Ok(data)}
|
||||
Err(err) => {Err(Error::BlockModeError(err))}
|
||||
let result = cipher.decrypt_vec(data);
|
||||
return match result {
|
||||
Ok(data) => { Ok(data) }
|
||||
Err(err) => { Err(Error::BlockModeError(err)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex_literal::hex;
|
||||
use crate::crypto::cipher::Cipher;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
@ -36,7 +43,7 @@ mod tests {
|
||||
let key = hex!("00000000000000000000000000000000");
|
||||
let iv = hex!("00000000000000000000000000000000");
|
||||
|
||||
let data_enc = crate::crypto::cipher::tdes::encrypt(&data, key, &iv).unwrap();
|
||||
let data_enc = crate::crypto::cipher::tdes_2k::Tdes2k::encrypt(&data, &key, &iv).unwrap();
|
||||
|
||||
let data_enc_expected = hex!("");
|
||||
|
||||
|
@ -3,31 +3,38 @@ use des::TdesEde3;
|
||||
use block_modes::{BlockMode, Cbc};
|
||||
use block_modes::block_padding::NoPadding;
|
||||
use crate::error::{Result, Error};
|
||||
use crate::crypto::cipher::Cipher;
|
||||
|
||||
type TDesEde3Cbc = Cbc<TdesEde3, NoPadding>;
|
||||
|
||||
pub const KEY_LEN: usize = 24;
|
||||
pub struct Tdes3k {}
|
||||
|
||||
pub fn encrypt (data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde3Cbc::new_var(&key, &iv)?;
|
||||
impl Cipher for Tdes3k {
|
||||
const BLOCK_SIZE: usize = 8;
|
||||
const KEY_SIZE: usize = 24;
|
||||
|
||||
return Ok(cipher.encrypt_vec(data));
|
||||
}
|
||||
fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde3Cbc::new_var(&key, &iv)?;
|
||||
|
||||
pub fn decrypt(data: &[u8], key: [u8; KEY_LEN], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde3Cbc::new_var(&key, &iv)?;
|
||||
return Ok(cipher.encrypt_vec(data));
|
||||
}
|
||||
|
||||
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||
let cipher = TDesEde3Cbc::new_var(&key, &iv)?;
|
||||
|
||||
|
||||
let result = cipher.decrypt_vec(data);
|
||||
return match result {
|
||||
Ok(data) => {Ok(data)}
|
||||
Err(err) => {Err(Error::BlockModeError(err))}
|
||||
let result = cipher.decrypt_vec(data);
|
||||
return match result {
|
||||
Ok(data) => { Ok(data) }
|
||||
Err(err) => { Err(Error::BlockModeError(err)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex_literal::hex;
|
||||
use crate::crypto::cipher::Cipher;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
@ -36,7 +43,7 @@ mod tests {
|
||||
let key = hex!("00000000000000000000000000000000");
|
||||
let iv = hex!("00000000000000000000000000000000");
|
||||
|
||||
let data_enc = crate::crypto::cipher::tdes::encrypt(&data, key, &iv).unwrap();
|
||||
let data_enc = crate::crypto::cipher::tdes_3k::Tdes3k::encrypt(&data, &key, &iv).unwrap();
|
||||
|
||||
let data_enc_expected = hex!("");
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::crypto::cipher_type::CipherType;
|
||||
use crate::crypto::cipher_type::CipherType::*;
|
||||
use crate::crypto::cipher::{aes, tdes, tdes_2k, tdes_3k};
|
||||
use crate::crypto::cipher::{aes, tdes, tdes_2k, tdes_3k, Cipher};
|
||||
use crate::error::Error;
|
||||
use crate::error::Result;
|
||||
|
||||
@ -63,10 +63,10 @@ pub fn generate_empty_key(cipher: CipherType) -> Box<[u8]> {
|
||||
/// Get KeySize for CipherType
|
||||
pub fn get_key_size(cipher: CipherType) -> usize {
|
||||
match cipher {
|
||||
TDES => tdes::KEY_LEN,
|
||||
TDES2K => tdes_2k::KEY_LEN,
|
||||
TDES3K => tdes_3k::KEY_LEN,
|
||||
AES => aes::KEY_LEN
|
||||
TDES => tdes::Tdes::KEY_SIZE,
|
||||
TDES2K => tdes_2k::Tdes2k::KEY_SIZE,
|
||||
TDES3K => tdes_3k::Tdes3k::KEY_SIZE,
|
||||
AES => aes::AES::KEY_SIZE,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,14 +18,14 @@ pub fn calculate_with_initial(data: &[u8], mut crc32: u32) -> u32 {
|
||||
crc32
|
||||
}
|
||||
|
||||
pub fn calculate(data: &[u8]) -> Box<[u8]> {
|
||||
pub fn calculate(data: &[u8]) -> Vec<u8> {
|
||||
let mut crc32 = INIT_VALUE;
|
||||
|
||||
for d in data {
|
||||
crc32 = calculate_with_initial(from_ref(d), crc32);
|
||||
}
|
||||
|
||||
Box::new(crc32.to_ne_bytes())
|
||||
crc32.to_ne_bytes().to_vec()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub mod cipher;
|
||||
pub mod crc;
|
||||
pub mod cipher_type;
|
||||
pub mod cipher_key;
|
||||
pub mod cipher_key;
|
||||
pub mod util;
|
20
src/crypto/util.rs
Normal file
20
src/crypto/util.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use crate::error::{Result, Error};
|
||||
use simple_error::simple_error;
|
||||
use block_modes::block_padding::{ZeroPadding, Padding};
|
||||
|
||||
pub fn extract_last_block(data: &[u8], blocksize: usize) -> Result<&[u8]> {
|
||||
if data.len() % blocksize != 0 {
|
||||
return Err(simple_error!("Data is not compatible with blocksize: data(length): {}, blocksize: {}.", data.len(), blocksize).into())
|
||||
}
|
||||
|
||||
Ok(&data[(data.len() - blocksize)..])
|
||||
}
|
||||
|
||||
pub fn expand_to_blocksize(data: &mut [u8], blocksize: usize) -> Result<&mut [u8]> {
|
||||
// let diff = data.len() % blocksize;
|
||||
|
||||
match ZeroPadding::pad(data, data.len(), blocksize) {
|
||||
Ok(x) => {Ok(x)}
|
||||
Err(e) => {Err(Error::PadError(e))}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user