cipher-workshop/des/tests/des.rs

199 lines
10 KiB
Rust

use cipher_core::{BlockCipher, Output};
use claims::assert_ok;
use des::Des;
use rstest::rstest;
const TEST_KEY: u64 = 0x1334_5779_9BBC_DFF1;
const TEST_PLAINTEXT: u64 = 0x0123_4567_89AB_CDEF;
const TEST_CIPHERTEXT: u64 = 0x85E8_1354_0F0A_B405;
#[rstest]
#[case(TEST_PLAINTEXT, TEST_CIPHERTEXT, TEST_KEY)]
#[case(0xC6F9_3D51_0757_A8FE, 0x3FDF_8951_0F38_A29B, 0x0655_A407_0623_10E3)]
#[case(0x4230_ECB4_5CD4_C924, 0xB7D1_E902_48E5_51CA, 0xAF3B_75E7_6DAD_49C8)]
#[case(0xE277_0441_8EE8_AE59, 0x4687_4321_3707_A4C7, 0x2FD7_2C95_90E1_712E)]
#[case(0x0BB5_293D_2EA8_1028, 0xB91E_FD54_0D09_FB25, 0xC495_4CCA_1BF1_8FE9)]
#[case(0xEE0C_8BED_F695_AB5F, 0x60F8_EE47_069F_989A, 0x350E_304F_E0F1_253D)]
#[case(0xF737_BBEB_28AA_31E1, 0xF2C1_27AD_7122_66A6, 0xA7F7_E1E3_CD93_F95D)]
#[case(0x1497_1184_AD78_EE19, 0x10C6_89E2_60BA_4B8E, 0x78D0_0A8E_63B1_4B5D)]
#[case(0x0F67_735D_621A_52C5, 0x1617_C981_8A62_7760, 0xAA48_FE46_0CB0_D436)]
#[case(0x81DD_1F9B_2E46_2061, 0xF2D1_E793_EB75_664A, 0x9901_A819_87CA_4782)]
#[case(0xEDBB_18A4_3E6D_8547, 0xD6A2_2519_CC7A_0D3C, 0x8297_9633_08D3_EBEE)]
#[case(0xF8B9_B259_5140_7D92, 0x16D7_B2DA_E12B_D8E7, 0x097A_23AF_A6E1_D116)]
#[case(0x1544_4A64_DA36_DAFC, 0xFA77_0F17_2532_AA14, 0x4F22_671C_8797_BDD1)]
#[case(0xEB95_CC8B_258D_D5C8, 0xBD6D_1004_24D4_8B48, 0xA886_0128_721F_FBB7)]
#[case(0xF1C2_A5DE_F978_0E45, 0x212D_A009_B107_EB47, 0x2383_25F5_E681_B9E5)]
#[case(0x21CA_7D34_9158_6F61, 0x75DE_1ED4_C454_3E04, 0xB353_ECE0_0C1D_C4AD)]
#[case(0xC314_4A6F_EAA8_3D91, 0xD98E_150A_66EB_BC33, 0xAC4F_E060_2751_2FF4)]
#[case(0xE845_420B_7C46_DBBB, 0x2E4D_9248_2585_44FF, 0xE997_37D4_27AE_B5F9)]
#[case(0x0284_5E3F_2EDC_4809, 0x0D22_6DC1_532F_3E4A, 0xD339_51A2_9FD6_C3DF)]
#[case(0x0471_1CC5_0218_A7B8, 0x0F34_EA09_A837_33C7, 0xBFC2_3D34_930A_D36D)]
#[case(0xE696_EBC5_7577_B9C4, 0x5F54_48A0_670D_2B41, 0x2200_AA0C_3F42_226C)]
#[case(0xCF61_8B74_BE29_1BD8, 0x254C_D92C_A2FB_043B, 0x36E6_82D4_9799_C6B3)]
#[case(0x7E18_6E5A_8E95_7527, 0x4462_82B2_1A70_0BDB, 0x4510_A566_7793_F488)]
#[case(0x2352_0EA6_C837_E224, 0x7C6C_616F_0726_F45E, 0xCCE7_EC8E_DFD6_2C95)]
#[case(0x802F_22E9_FAE5_71FE, 0x9532_CC17_3FD6_CAEF, 0x3070_C587_0D54_2905)]
#[case(0xE1AE_534B_DF81_0003, 0xCEFE_8EA8_40A0_A830, 0x0F58_5495_20E3_BDDD)]
#[case(0xD074_AD28_E24B_10B4, 0x4CA2_31ED_48FA_F5ED, 0x5D04_DEF0_4DB7_C05A)]
#[case(0x7D6D_7F72_8247_D60A, 0xB350_CE16_4A60_E35D, 0x82A2_5738_1871_519F)]
#[case(0x922D_5265_A0C1_54FC, 0xB615_C26C_8624_27A8, 0x07B3_9AFE_02EC_FBC9)]
#[case(0x7A38_2A2D_1ED0_1EC7, 0x96C4_819F_5BF1_099C, 0x6AF2_B49D_2EB0_055D)]
#[case(0x0E9B_3302_66FD_964C, 0x4F42_A745_0D30_20DB, 0x8AFA_83AA_3158_858D)]
#[case(0x6872_A230_96B8_0143, 0x2DC8_6E8E_00F1_7D2E, 0x660E_D819_E232_5E0F)]
#[case(0x0FF9_554F_AEAA_DDE6, 0x7AA3_B1D9_22B8_0BF1, 0x9B32_8887_35DE_BB5D)]
#[case(0x00FB_729A_2201_5603, 0x2506_2232_CF4B_E95C, 0x7104_806D_7257_2CB7)]
#[case(0x2E1C_C29A_E40B_4CCD, 0xFC32_0B3E_6058_59AE, 0x4541_D83F_E726_7CD2)]
#[case(0x4336_2A6C_CE6E_CA97, 0xB2C8_FDFE_0A47_2A81, 0xD730_064E_E820_3C33)]
#[case(0x03FB_C27D_74F3_4AC0, 0x4EEC_87D2_9024_5136, 0x361E_1CC7_4E4E_434F)]
#[case(0x5830_0AAC_75D9_FD76, 0x9C41_87B5_BAF5_FA65, 0x4929_7C9B_86E9_ECFC)]
#[case(0x6224_F54C_2C0E_34C4, 0x7002_F5D4_E72B_C942, 0x91B9_3300_0209_EEB0)]
#[case(0x12FE_DF40_FA59_9757, 0x2D24_8A52_638A_CAA4, 0x11D4_7CC2_683B_41A6)]
#[case(0x463C_FBD3_EBED_A824, 0x9CE8_D4F9_521F_E37D, 0xFF05_82BC_587C_747E)]
#[case(0x66A8_196A_3212_B1CB, 0x24B2_CDE9_6BD0_43D1, 0xFA30_B9CE_04F6_53F2)]
#[case(0xC235_5E16_B36F_A90B, 0x56B6_6B72_5995_4B0C, 0x00CE_4F24_5AB0_F566)]
#[case(0x2497_9DE0_EAB2_724C, 0xF868_B877_0B46_2BD1, 0x62A5_FCF5_4F91_2784)]
#[case(0x6356_B043_0AF2_858B, 0x6743_750C_91C7_2828, 0x113B_96B8_2748_CCBF)]
#[case(0x9AE0_16CF_9F33_B1B9, 0x3CEB_D74D_CACC_1721, 0x7B8E_6CAF_FCF4_4E3F)]
#[case(0x0284_35F7_B1BC_4866, 0x5780_E4F5_90C3_8ABF, 0x3D67_EA7B_9BB1_0A48)]
#[case(0xC654_D706_82CF_BC74, 0x2BE2_1130_FD89_6F81, 0x7891_2150_1135_CD28)]
#[case(0x1E59_779F_E127_197B, 0x3960_BE8A_4475_41EC, 0x49E0_8524_68BF_FF70)]
#[case(0x1133_3FE5_F5B6_E8A1, 0x341E_2C24_9E3C_33EC, 0x3A0E_8C24_36FD_CB7E)]
#[case(0x8ABC_A73D_578D_3D58, 0xE0F3_AEFA_24AC_72D8, 0x3D09_4F8F_B36B_2049)]
#[case(0x13D0_E14D_1B09_D4D0, 0xFD12_4B52_065E_9B1C, 0x0DAF_83A5_B78B_D17A)]
#[case(0xB95A_AA93_1E18_D4F2, 0x2E7F_D3E0_1537_4051, 0x21AE_1AF0_DF76_10E7)]
#[case(0x086B_DA84_4066_F31E, 0xAD08_AEBC_32B1_D7CF, 0xA56A_E683_333C_7C7C)]
#[case(0x3728_381E_85C2_E4CD, 0x0C63_24A6_6E9F_5BDB, 0xCEA9_9BFE_6644_87D2)]
#[case(0x531B_541A_095A_A042, 0x7F3B_CA73_FF24_3276, 0x63FF_C197_52E3_591A)]
#[case(0xF3B0_C406_3FD6_CEF2, 0x8EE3_2764_B52A_9608, 0xAF1E_2FC7_7631_5A9C)]
#[case(0xB804_7091_8C20_F2F9, 0x610D_74A9_5D2E_5D04, 0xF03D_BBB8_B4B5_259A)]
#[case(0x745C_E01E_C299_5117, 0x7224_AD1D_3CB6_CFAD, 0xC06D_2C9B_8AC1_8FC5)]
#[case(0x36A2_D3C1_10B9_8ECD, 0xB4FC_F673_35A2_A6AD, 0x88C8_8DEF_D4F6_7DE4)]
#[case(0x1BAB_8249_68A6_F8D4, 0x5C98_AA0A_09E2_CAFB, 0xD8EC_0A6D_76B3_874C)]
#[case(0x9F2E_8659_16C3_2FE4, 0x8C0F_B383_CCBC_48BF, 0x5821_47BE_1321_F990)]
#[case(0x6B97_A57F_E2D1_6610, 0xA3A9_9BB3_1874_E7A6, 0x85ED_1A64_3CDC_3DBD)]
#[case(0x1F58_1813_046C_9976, 0xBAF3_B9F6_BED0_557B, 0x7B98_AAC7_F7CD_D742)]
#[case(0xB9E3_CDF0_B644_5B66, 0xC19E_9B37_15FF_9DC9, 0x9B97_837A_CEDE_EBC8)]
#[case(0xD2F7_4580_0662_407E, 0xA61C_888C_93C5_D990, 0x8FFE_C142_1E0E_A2AE)]
#[case(0xC257_8AE8_B7D1_4A0C, 0x3E30_CAE2_4D01_C06E, 0x90D5_78F0_87BE_D051)]
#[case(0x0E4D_192E_5C18_55BC, 0xCF7E_E266_0BD0_241F, 0xC946_5D9E_8051_3EA8)]
#[case(0xB8C8_823F_8919_5087, 0x42E5_989B_91E4_5B1F, 0x3EC9_0C5F_9542_B379)]
#[case(0xA100_840A_C4F9_FF14, 0x7847_1AE8_EA4D_8582, 0x3E4D_E0AE_BADC_DF35)]
#[case(0x4F8D_2946_5ED5_6262, 0x3185_4E24_A13A_8C53, 0xB256_D848_5014_11DE)]
#[case(0x5767_670D_87F1_FBBA, 0xF892_A9F3_1F76_6F45, 0xDDC9_0B98_F555_6EC9)]
#[case(0xF3BF_F8CB_AADF_D721, 0xB3F4_3D4C_B949_BD28, 0xDED3_DF1E_28B6_AC81)]
#[case(0xC63C_CDE5_88BB_17DB, 0x64A4_6861_E0D8_9377, 0x4317_56A0_9A71_8206)]
#[case(0xDF15_2CCF_DDC8_ACE1, 0x47F3_FE5A_9CA3_6720, 0x17AA_23E0_2E70_76DA)]
#[case(0x09CE_FF80_D62B_A1F3, 0xD706_DEF3_6B3D_9AA8, 0x52D8_119A_736E_D25A)]
#[case(0x6F5C_650B_8C57_370B, 0xEA60_1EBE_B37B_E6B7, 0xE6FD_5BEE_E9F7_89FB)]
#[case(0x4409_4AB7_9244_7C0B, 0x6489_004E_EDD7_65EE, 0x27DB_193D_4410_4800)]
#[case(0x61EE_5199_5804_30FF, 0xE3B1_F245_EEF5_7A8C, 0x8943_B7F5_0EBC_D4AE)]
#[case(0x6F39_1336_84A1_CB12, 0x7D45_A03A_D0C0_2B7C, 0x0FD7_AF51_4C4D_630E)]
#[case(0x7E84_F4DD_2A64_D8A0, 0x3271_8C71_68E5_D4B8, 0x8C5B_0274_F1E1_49F5)]
#[case(0xB14B_F9D2_FD61_626C, 0xCA2F_A9C5_E35D_BD5E, 0xE9C2_47B6_7B90_CB78)]
#[case(0x7315_721B_8072_C12E, 0xCBA1_3DE3_91A3_8CBC, 0xCABD_F1D8_F8C9_7F36)]
#[case(0x9D03_5D2F_FF2E_03F8, 0xA945_5400_A9F9_EC23, 0xF9CD_D65B_5A90_3491)]
#[case(0x7AC5_1308_FBB8_8ADF, 0xB1BA_F5FB_B4E0_968B, 0x87B3_45FF_336E_2C36)]
#[case(0xFA3A_4A1A_1732_C319, 0xC157_E3B9_6D1E_98B8, 0xB691_0EEF_5239_2E0B)]
#[case(0x3B5F_3343_9D31_3650, 0xA207_535D_9E2A_34E9, 0x0932_5791_B0EA_B667)]
#[case(0x72CE_CFD2_29AF_B46D, 0x7DCC_33A1_8CFC_BDC4, 0x2EB8_4231_BADA_C0CD)]
#[case(0xA0C6_7EA3_7D59_BA9E, 0x67F2_D204_2570_7DF3, 0x48B6_42F7_8149_BEAE)]
#[case(0xFB63_1637_53AF_FE64, 0x2345_9280_7EE3_4BB5, 0x2910_9B12_6637_5CF8)]
#[case(0xCFC5_0524_89ED_B7F8, 0xE4E3_E7E9_4B51_86D3, 0xB5CF_CD1E_62A3_C916)]
#[case(0x5C82_EB3D_13D6_DA31, 0x7960_9644_E8F8_D9DC, 0x7BF8_500F_95AF_A68B)]
#[case(0xBB0C_417D_CC7A_0EF3, 0x7B15_FEC1_253A_C2D9, 0xB463_988E_A3B7_F9E4)]
#[case(0xC3B8_37D6_5170_011B, 0x1B23_EF3B_4853_D5C1, 0x7652_8A30_9374_056C)]
#[case(0xE5E0_5D4F_262B_E8B1, 0x4683_AF44_7BA4_1944, 0x0A85_FD6F_ED35_3C99)]
#[case(0x547A_21D5_61C7_A98F, 0xFA1B_8BE3_9447_7DC5, 0x6B20_A7AE_40D8_C631)]
#[case(0x735F_1D3A_17FF_3F12, 0x0C14_C532_CC28_846D, 0xE1B9_6382_D363_4E1B)]
#[case(0x87D2_05D5_16DA_CEA7, 0x5CE9_0A9E_6938_9B59, 0x6683_8ACA_6C09_2897)]
#[case(0x342E_98E4_E3DF_DE9F, 0x1DC2_022E_DE59_79F0, 0x33E1_BD93_DFB6_F058)]
#[case(0x1524_18ED_94BF_6739, 0x0BF0_7F9A_A463_30B8, 0x4781_2ED0_129E_BB99)]
#[case(0xA9CD_C911_F01F_E7C8, 0x8777_9C21_AD54_E116, 0x3E9D_7D47_8FFF_F687)]
fn encrypt_decrypt_roundtrip(
#[case] plaintext: u64,
#[case] expected_ciphertext: u64,
#[case] key: u64,
) {
let des = Des::new(key);
let ciphertext = assert_ok!(des.encrypt(&plaintext.to_be_bytes()));
let dectrypted = assert_ok!(des.decrypt(&ciphertext));
let re_ciphertext = assert_ok!(des.encrypt(&dectrypted));
let ciphertext_u64 = cipher_block_to_u64(&ciphertext);
let decrypted_u64 = cipher_block_to_u64(&dectrypted);
let re_ciphertext_u64 = cipher_block_to_u64(&re_ciphertext);
assert_eq!(
ciphertext_u64, expected_ciphertext,
"Encyption failed. Expected 0x{expected_ciphertext:016X}, got 0x{ciphertext_u64:016X}"
);
assert_eq!(
decrypted_u64, plaintext,
"Decyption failed. Expected 0x{plaintext:016X}, got 0x{decrypted_u64:016X}"
);
assert_eq!(
re_ciphertext_u64, expected_ciphertext,
"Re-encyption failed. Expected 0x{expected_ciphertext:016X}, got 0x{re_ciphertext_u64:016X}"
);
}
#[rstest]
#[case(0x0101_0101_0101_0101)]
#[case(0xFEFE_FEFE_FEFE_FEFE)]
#[case(0xE001_E001_E001_E001)]
fn weak_keys(#[case] key: u64) {
let des = Des::new(key);
let plaintext = TEST_PLAINTEXT;
let ciphertext = assert_ok!(des.encrypt(&plaintext.to_be_bytes()));
let decrypted = assert_ok!(des.decrypt(&ciphertext));
let decrypted_u64 = cipher_block_to_u64(&decrypted);
assert_eq!(
decrypted_u64, plaintext,
"Weak key {key:016X} failed roundtrip"
);
}
#[test]
fn all_zero_paintext() {
let des = Des::new(TEST_KEY);
let plain = 0u64;
let encrypted = assert_ok!(des.encrypt(&plain.to_be_bytes()));
let decrypted = assert_ok!(des.decrypt(&encrypted));
let decrypted_u64 = cipher_block_to_u64(&decrypted);
assert_eq!(decrypted_u64, plain, "All-zero plaintext failed");
}
#[test]
fn all_one_paintext() {
let des = Des::new(TEST_KEY);
let plain = u64::MAX;
let encrypted = assert_ok!(des.encrypt(&plain.to_be_bytes()));
let decrypted = assert_ok!(des.decrypt(&encrypted));
let decrypted_u64 = cipher_block_to_u64(&decrypted);
assert_eq!(decrypted_u64, plain, "All-one plaintext failed");
}
#[test]
fn different_inputs() {
let des = Des::new(TEST_KEY);
let plain1 = 1u64;
let plain2 = 2u64;
let enc1 = assert_ok!(des.encrypt(&plain1.to_be_bytes()));
let enc2 = assert_ok!(des.encrypt(&plain2.to_be_bytes()));
assert_ne!(
enc1, enc2,
"Encryption not deterministic for different inputs"
);
}
fn cipher_block_to_u64(block: &Output) -> u64 {
let bytes = block.as_slice().try_into().expect("8 bytes");
u64::from_be_bytes(bytes)
}