From 44cc9179cadfcf0dc21fffadfe984251fb8a0972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolphe=20Br=C3=A9ard?= Date: Wed, 19 Jun 2024 17:08:11 +0200 Subject: [PATCH] Add a version number for exported IKML and encrypted data --- src/coffio.rs | 45 ++++++++++++++++++----------------- src/error.rs | 2 ++ src/ikm.rs | 12 +++++----- src/lib.rs | 2 ++ src/storage.rs | 64 +++++++++++++++++++++++++++++--------------------- 5 files changed, 70 insertions(+), 55 deletions(-) diff --git a/src/coffio.rs b/src/coffio.rs index d10f98c..b4627fd 100644 --- a/src/coffio.rs +++ b/src/coffio.rs @@ -98,7 +98,7 @@ mod tests { use super::*; use crate::{DataContext, KeyContext}; - const TEST_CIPHERTEXT: &str = "AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NgAAAAAAAAA"; + const TEST_CIPHERTEXT: &str = "enc-v1:AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NgAAAAAAAAA"; const TEST_DATA: &[u8] = b"Lorem ipsum dolor sit amet."; const TEST_KEY_CTX: &[&str] = &["db_name", "table_name", "column_name"]; const TEST_DATA_CTX: &[&str] = &["018db876-3d9d-79af-9460-55d17da991d8"]; @@ -118,7 +118,7 @@ mod tests { #[cfg(feature = "chacha")] fn get_ikm_lst_chacha20poly1305_blake3() -> InputKeyMaterialList { InputKeyMaterialList::import( - "AQAAAA:AQAAAAEAAAC_vYEw1ujVG5i-CtoPYSzik_6xaAq59odjPm5ij01-e6zz4mUAAAAALJGBiwAAAAAA", + "ikml-v1:AQAAAA:AQAAAAEAAAC_vYEw1ujVG5i-CtoPYSzik_6xaAq59odjPm5ij01-e6zz4mUAAAAALJGBiwAAAAAA", ) .unwrap() } @@ -126,7 +126,7 @@ mod tests { #[cfg(feature = "aes")] fn get_ikm_lst_aes128gcm_sha256() -> InputKeyMaterialList { InputKeyMaterialList::import( - "AQAAAA:AQAAAAIAAAA2lXqTSduZ22J0LiwEhmENjB6pLo0GVKvAQYocJcAAp1f8_2UAAAAAuzDPeAAAAAAA", + "ikml-v1:AQAAAA:AQAAAAIAAAA2lXqTSduZ22J0LiwEhmENjB6pLo0GVKvAQYocJcAAp1f8_2UAAAAAuzDPeAAAAAAA", ) .unwrap() } @@ -143,8 +143,8 @@ mod tests { let res = cb.encrypt(&key_ctx, &data_ctx, TEST_DATA); assert!(res.is_ok(), "res: {res:?}"); let ciphertext = res.unwrap(); - assert!(ciphertext.starts_with("AQAAAA:")); - assert_eq!(ciphertext.len(), 98); + assert!(ciphertext.starts_with("enc-v1:AQAAAA:")); + assert_eq!(ciphertext.len(), 105); // Decrypt let res = cb.decrypt(&key_ctx, &data_ctx, &ciphertext); @@ -165,8 +165,8 @@ mod tests { let res = cb.encrypt(&key_ctx, &data_ctx, TEST_DATA); assert!(res.is_ok(), "res: {res:?}"); let ciphertext = res.unwrap(); - assert!(ciphertext.starts_with("AQAAAA:")); - assert_eq!(ciphertext.len(), 82); + assert!(ciphertext.starts_with("enc-v1:AQAAAA:")); + assert_eq!(ciphertext.len(), 89); // Decrypt let res = cb.decrypt(&key_ctx, &data_ctx, &ciphertext); @@ -187,8 +187,8 @@ mod tests { let res = cb.encrypt(&key_ctx, &data_ctx, TEST_DATA); assert!(res.is_ok(), "res: {res:?}"); let ciphertext = res.unwrap(); - assert!(ciphertext.starts_with("AQAAAA:")); - assert_eq!(ciphertext.len(), 98); + assert!(ciphertext.starts_with("enc-v1:AQAAAA:")); + assert_eq!(ciphertext.len(), 105); // Decrypt let res = cb.decrypt(&key_ctx, &data_ctx, &ciphertext); @@ -209,8 +209,8 @@ mod tests { let res = cb.encrypt(&key_ctx, &data_ctx, TEST_DATA); assert!(res.is_ok(), "res: {res:?}"); let ciphertext = res.unwrap(); - assert!(ciphertext.starts_with("AQAAAA:")); - assert_eq!(ciphertext.len(), 82); + assert!(ciphertext.starts_with("enc-v1:AQAAAA:")); + assert_eq!(ciphertext.len(), 89); // Decrypt let res = cb.decrypt(&key_ctx, &data_ctx, &ciphertext); @@ -231,8 +231,8 @@ mod tests { let res = cb.encrypt(&key_ctx, &data_ctx, TEST_DATA); assert!(res.is_ok(), "res: {res:?}"); let ciphertext = res.unwrap(); - assert!(ciphertext.starts_with("AQAAAA:")); - assert_eq!(ciphertext.len(), 110); + assert!(ciphertext.starts_with("enc-v1:AQAAAA:")); + assert_eq!(ciphertext.len(), 117); // Decrypt let res = cb.decrypt(&key_ctx, &data_ctx, &ciphertext); @@ -253,8 +253,8 @@ mod tests { let res = cb.encrypt(&key_ctx, &data_ctx, TEST_DATA); assert!(res.is_ok(), "res: {res:?}"); let ciphertext = res.unwrap(); - assert!(ciphertext.starts_with("AQAAAA:")); - assert_eq!(ciphertext.len(), 94); + assert!(ciphertext.starts_with("enc-v1:AQAAAA:")); + assert_eq!(ciphertext.len(), 101); // Decrypt let res = cb.decrypt(&key_ctx, &data_ctx, &ciphertext); @@ -267,13 +267,14 @@ mod tests { #[cfg(feature = "chacha")] fn decrypt_invalid_ciphertext() { let tests = &[ - ("", "empty data"), - ("AQAATA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NgAAAAAAAAA", "unknown ikm id"), - ("AQAAAA:8pVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NgAAAAAAAAA", "invalid nonce"), - ("AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:8TkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NgAAAAAAAAA", "invalid ciphertext"), - ("AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NaAAAAAAAAA", "invalid time period"), - ("AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:", "empty time period"), - ("AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg", "missing time period"), + ("", "empty data 1"), + ("env-v1:", "empty data 2"), + ("enc-v1:AQAATA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NgAAAAAAAAA", "unknown ikm id"), + ("enc-v1:AQAAAA:8pVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NgAAAAAAAAA", "invalid nonce"), + ("enc-v1:AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:8TkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NgAAAAAAAAA", "invalid ciphertext"), + ("enc-v1:AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:NaAAAAAAAAA", "invalid time period"), + ("enc-v1:AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg:", "empty time period"), + ("enc-v1:AQAAAA:qpVDbGvu0wl2tQgfF5jngCWCoCq5d9gj:eTkOSKz9YyvJE8PyT1lAFn4hyeK_0l6tWU4yyHA-7WRCJ9G-HWNpqoKBxg", "missing time period"), ]; let lst = get_ikm_lst_chacha20poly1305_blake3(); diff --git a/src/error.rs b/src/error.rs index e4eb2af..61b1ba7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -32,6 +32,8 @@ pub enum Error { ParsingEncodedDataInvalidPartLen(usize, usize), #[error("parsing error: encoded data: invalid timestamp: {0:?}")] ParsingEncodedDataInvalidTimestamp(Vec), + #[error("parsing error: encoded data: invalid version")] + ParsingEncodedDataInvalidVersion, #[error("parsing error: scheme: {0}: unknown scheme")] ParsingSchemeUnknownScheme(crate::scheme::SchemeSerializeType), #[error("unable to generate random values: {0}")] diff --git a/src/ikm.rs b/src/ikm.rs index ef6fc0a..09e2295 100644 --- a/src/ikm.rs +++ b/src/ikm.rs @@ -325,7 +325,7 @@ impl InputKeyMaterialList { # Examples ``` -let stored_ikml = "AQAAAA:AQAAAAEAAAC_vYEw1ujVG5i-CtoPYSzik_6xaAq59odjPm5ij01-e6zz4mUAAAAALJGBiwAAAAAA"; +let stored_ikml = "ikml-v1:AQAAAA:AQAAAAEAAAC_vYEw1ujVG5i-CtoPYSzik_6xaAq59odjPm5ij01-e6zz4mUAAAAALJGBiwAAAAAA"; let mut ikml = coffio::InputKeyMaterialList::import(stored_ikml)?; assert_eq!(ikml.len(), 1); # Ok::<(), coffio::Error>(()) @@ -384,7 +384,7 @@ mod tests { #[cfg(feature = "chacha")] fn import() { let s = - "AQAAAA:AQAAAAEAAAC_vYEw1ujVG5i-CtoPYSzik_6xaAq59odjPm5ij01-e6zz4mUAAAAALJGBiwAAAAAA"; + "ikml-v1:AQAAAA:AQAAAAEAAAC_vYEw1ujVG5i-CtoPYSzik_6xaAq59odjPm5ij01-e6zz4mUAAAAALJGBiwAAAAAA"; let res = InputKeyMaterialList::import(s); assert!(res.is_ok(), "res: {res:?}"); let lst = res.unwrap(); @@ -407,7 +407,7 @@ mod tests { #[cfg(feature = "chacha")] fn from_str() { let s = - "AQAAAA:AQAAAAEAAAC_vYEw1ujVG5i-CtoPYSzik_6xaAq59odjPm5ij01-e6zz4mUAAAAALJGBiwAAAAAA"; + "ikml-v1:AQAAAA:AQAAAAEAAAC_vYEw1ujVG5i-CtoPYSzik_6xaAq59odjPm5ij01-e6zz4mUAAAAALJGBiwAAAAAA"; let res = InputKeyMaterialList::from_str(s); assert!(res.is_ok(), "res: {res:?}"); let lst = res.unwrap(); @@ -457,7 +457,7 @@ mod ikm_management { // 6: * not_before: Tuesday 15 August 2180 10:21:42 // * not_after: Wednesday 15 August 2181 10:21:42 // * is_revoked: false - const TEST_STR: &str = "BgAAAA:AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB:AgAAAAEAAADf7CR8vl_aWOUyfsO0ek0YQr_Yi7L_sJmF2nIt_XOaCzYNal4AAAAAtkBLYAAAAAAA:AwAAAAEAAAAMoNIW9gIGkzegUDEsU3N1Rf_Zz0OMuylUSiQjUzLXqzY0MmAAAAAANsk0iwEAAAAA:BAAAAAEAAABbwRrMz3x3DkfOEFg1BHfLLRHoNqg6d_xGWwdh48hH8rZm9mEAAAAANjy9YwAAAAAA:BQAAAAEAAAA2LwnTgDUF7qn7dy79VA24JSSgo6vllAtU5zmhrxNJu7YIz4sBAAAANoUMjgEAAAAB:BgAAAAEAAAAn0Vqe2f9YRXBt6xVYaeSLs0Gf0S0_5B-hk-a2b0rhlraCJbwAAAAAtlErjAEAAAAA"; + const TEST_STR: &str = "ikml-v1:BgAAAA:AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB:AgAAAAEAAADf7CR8vl_aWOUyfsO0ek0YQr_Yi7L_sJmF2nIt_XOaCzYNal4AAAAAtkBLYAAAAAAA:AwAAAAEAAAAMoNIW9gIGkzegUDEsU3N1Rf_Zz0OMuylUSiQjUzLXqzY0MmAAAAAANsk0iwEAAAAA:BAAAAAEAAABbwRrMz3x3DkfOEFg1BHfLLRHoNqg6d_xGWwdh48hH8rZm9mEAAAAANjy9YwAAAAAA:BQAAAAEAAAA2LwnTgDUF7qn7dy79VA24JSSgo6vllAtU5zmhrxNJu7YIz4sBAAAANoUMjgEAAAAB:BgAAAAEAAAAn0Vqe2f9YRXBt6xVYaeSLs0Gf0S0_5B-hk-a2b0rhlraCJbwAAAAAtlErjAEAAAAA"; fn round_time(t: SystemTime) -> SystemTime { let secs = t.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); @@ -504,7 +504,7 @@ mod ikm_management { let res = lst.export(); assert!(res.is_ok(), "res: {res:?}"); let s = res.unwrap(); - assert_eq!(&s, "AAAAAA"); + assert_eq!(&s, "ikml-v1:AAAAAA"); } #[test] @@ -515,7 +515,7 @@ mod ikm_management { let res = lst.export(); assert!(res.is_ok(), "res: {res:?}"); let s = res.unwrap(); - assert_eq!(s.len(), 83); + assert_eq!(s.len(), 91); } #[test] diff --git a/src/lib.rs b/src/lib.rs index 91b69c1..d0cdfb4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,3 +55,5 @@ pub const DEFAULT_KEY_CTX_PERIODICITY: u64 = 31_556_925; pub const DEFAULT_SCHEME: Scheme = Scheme::XChaCha20Poly1305WithBlake3; #[cfg(all(feature = "ikm-management", feature = "aes", not(feature = "chacha")))] pub const DEFAULT_SCHEME: Scheme = Scheme::Aes128GcmWithSha256; +const STORAGE_ENC_VERSION: &str = "enc-v1:"; +const STORAGE_IKML_VERSION: &str = "ikml-v1:"; diff --git a/src/storage.rs b/src/storage.rs index b82f9eb..0115ecb 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -28,6 +28,7 @@ pub(crate) fn encode_ikm_list(ikml: &InputKeyMaterialList) -> Result { acc + IKM_BASE_STRUCT_SIZE + ikm.scheme.get_ikm_size() })) + 4; let mut ret = String::with_capacity(data_size); + ret += crate::STORAGE_IKML_VERSION; ret += &encode_data(&ikml.id_counter.to_le_bytes()); for ikm in &ikml.ikm_lst { ret += STORAGE_SEPARATOR; @@ -42,7 +43,7 @@ pub(crate) fn encode_cipher( encrypted_data: &EncryptedData, time_period: Option, ) -> String { - let mut ret = String::new(); + let mut ret = String::from(crate::STORAGE_ENC_VERSION); ret += &encode_data(&ikm_id.to_le_bytes()); ret += STORAGE_SEPARATOR; ret += &encode_data(&encrypted_data.nonce); @@ -56,6 +57,9 @@ pub(crate) fn encode_cipher( } pub(crate) fn decode_ikm_list(data: &str) -> Result { + let data = data + .strip_prefix(crate::STORAGE_IKML_VERSION) + .ok_or(Error::ParsingEncodedDataInvalidVersion)?; let v: Vec<&str> = data.split(STORAGE_SEPARATOR).collect(); if v.is_empty() { return Err(Error::ParsingEncodedDataInvalidIkmListLen(v.len())); @@ -79,6 +83,9 @@ pub(crate) fn decode_ikm_list(data: &str) -> Result { #[cfg(feature = "encryption")] pub(crate) fn decode_cipher(data: &str) -> Result<(IkmId, EncryptedData, Option)> { + let data = data + .strip_prefix(crate::STORAGE_ENC_VERSION) + .ok_or(Error::ParsingEncodedDataInvalidVersion)?; let mut v: Vec<&str> = data.split(STORAGE_SEPARATOR).collect(); let time_period = if v.len() == NB_PARTS + 1 { match v.pop() { @@ -119,7 +126,7 @@ pub(crate) fn decode_cipher(data: &str) -> Result<(IkmId, EncryptedData, Option< #[cfg(all(test, feature = "ikm-management"))] mod ikm_lst { - const TEST_STR: &str = "BgAAAA:AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB:AgAAAAEAAADf7CR8vl_aWOUyfsO0ek0YQr_Yi7L_sJmF2nIt_XOaCzYNal4AAAAAtkBLYAAAAAAA:AwAAAAEAAAAMoNIW9gIGkzegUDEsU3N1Rf_Zz0OMuylUSiQjUzLXqzY0MmAAAAAANsk0iwEAAAAA:BAAAAAEAAABbwRrMz3x3DkfOEFg1BHfLLRHoNqg6d_xGWwdh48hH8rZm9mEAAAAANjy9YwAAAAAA:BQAAAAEAAAA2LwnTgDUF7qn7dy79VA24JSSgo6vllAtU5zmhrxNJu7YIz4sBAAAANoUMjgEAAAAB:BgAAAAEAAAAn0Vqe2f9YRXBt6xVYaeSLs0Gf0S0_5B-hk-a2b0rhlraCJbwAAAAAtlErjAEAAAAA"; + const TEST_STR: &str = "ikml-v1:BgAAAA:AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB:AgAAAAEAAADf7CR8vl_aWOUyfsO0ek0YQr_Yi7L_sJmF2nIt_XOaCzYNal4AAAAAtkBLYAAAAAAA:AwAAAAEAAAAMoNIW9gIGkzegUDEsU3N1Rf_Zz0OMuylUSiQjUzLXqzY0MmAAAAAANsk0iwEAAAAA:BAAAAAEAAABbwRrMz3x3DkfOEFg1BHfLLRHoNqg6d_xGWwdh48hH8rZm9mEAAAAANjy9YwAAAAAA:BQAAAAEAAAA2LwnTgDUF7qn7dy79VA24JSSgo6vllAtU5zmhrxNJu7YIz4sBAAAANoUMjgEAAAAB:BgAAAAEAAAAn0Vqe2f9YRXBt6xVYaeSLs0Gf0S0_5B-hk-a2b0rhlraCJbwAAAAAtlErjAEAAAAA"; const TEST_CTN_0: &[u8] = &[ 0x94, 0x00, 0xf7, 0x2a, 0x9e, 0x02, 0x78, 0xeb, 0xf1, 0xcc, 0xb4, 0x94, 0x9d, 0x23, 0x0f, 0x96, 0x79, 0x4b, 0x48, 0x99, 0xc0, 0x95, 0xc4, 0xe0, 0x38, 0xee, 0x7e, 0x94, 0x20, 0xde, @@ -251,8 +258,8 @@ mod ikm_lst { let res = super::encode_ikm_list(&lst); assert!(res.is_ok(), "res: {res:?}"); let s = res.unwrap(); - assert!(s.starts_with("AwAAAA:")); - assert_eq!(s.len(), 237); + assert!(s.starts_with("ikml-v1:AwAAAA:")); + assert_eq!(s.len(), 245); let res = super::decode_ikm_list(&s); assert!(res.is_ok(), "res: {res:?}"); @@ -277,24 +284,25 @@ mod ikm_lst { #[test] fn decode_invalid() { let tests = &[ - ("", "empty ikm"), + ("", "empty string"), + ("ikml-v1:", "empty ikm content"), ( - "AAAA:AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB", + "ikml-v1:AAAA:AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB", "invalid id", ), ( - ":AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB", + "ikml-v1::AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB", "empty id", ), ( - "AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB", + "ikml-v1:AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47n6UIN5K2TbmoVwAAAAANmuEXgAAAAAB", "no id", ), ( - "BgAAAA:AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47", + "ikml-v1:BgAAAA:AQAAAAEAAACUAPcqngJ46_HMtJSdIw-WeUtImcCVxOA47", "invalid ikm", ), - ("BgAAAA:", "empty ikm"), + ("ikml-v1:BgAAAA:", "empty ikm"), ]; for (s, error_str) in tests { let res = super::decode_ikm_list(s); @@ -308,8 +316,8 @@ mod ciphers { use crate::ikm::IkmId; use crate::storage::EncryptedData; - const TEST_STR: &str = "KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN"; - const TEST_STR_T: &str = "KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN:NaAAAAAAAAA"; + const TEST_STR: &str = "enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN"; + const TEST_STR_T: &str = "enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN:NaAAAAAAAAA"; const TEST_IKM_ID: IkmId = 42; const TEST_NONCE: &'static [u8] = &[ 0x6b, 0x94, 0xa9, 0x8c, 0x0a, 0x2a, 0x86, 0xfb, 0x88, 0xf6, 0x7d, 0xc6, 0x3e, 0x10, 0xca, @@ -378,27 +386,29 @@ mod ciphers { ("", "empty data 1"), (":", "empty data 2"), ("::", "empty data 3"), - (":::", "empty data 4"), - ("a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "missing ikm id"), - ("KgAAAA:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "missing nonce"), - ("KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb", "missing ciphertext"), + ("enc-v1::", "empty data 4"), + ("enc-v1:::", "empty data 5"), + ("enc-v1::::", "empty data 6"), + ("enc-v1:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "missing ikm id"), + ("enc-v1:KgAAAA:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "missing nonce"), + ("enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb", "missing ciphertext"), // Empty parts - (":a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "empty ikm id"), - ("KgAAAA::TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "empty nonce"), - ("KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:", "empty ciphertext"), - ("KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN:", "empty time period"), + ("enc-v1::a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "empty ikm id"), + ("enc-v1:KgAAAA::TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "empty nonce"), + ("enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:", "empty ciphertext"), + ("enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN:", "empty time period"), // Invalid base64 parts - ("KgAA.A:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "invalid base64 ikm id"), - ("KgAAAA:a5SpjAoqhvuI9n3GPhDKu@tqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "invalid base64 nonce"), - ("KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHK/xfnY-zR_bN", "invalid base64 ciphertext"), + ("enc-v1:KgAA.A:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "invalid base64 ikm id"), + ("enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKu@tqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "invalid base64 nonce"), + ("enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHK/xfnY-zR_bN", "invalid base64 ciphertext"), // Invalid data length - ("KgAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "invalid ikm id data length"), - ("KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "invalid nonce data length"), - ("KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR", "invalid ciphertext data length"), - ("KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN:AQAAAA", "invalid time period length"), + ("enc-v1:KgAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "invalid ikm id data length"), + ("enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN", "invalid nonce data length"), + ("enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR", "invalid ciphertext data length"), + ("enc-v1:KgAAAA:a5SpjAoqhvuI9n3GPhDKuotqoLbf7_Fb:TI24Wr_g-ZV7_X1oHqVKak9iRlQSneYVOMWB-3Lp-hFHKfxfnY-zR_bN:AQAAAA", "invalid time period length"), ]; for (ciphertext, error_str) in invalid_tests { let res = super::decode_cipher(ciphertext);