exif_oxide/implementations/nikon/
encryption.rs1use crate::exif::ExifReader;
17use crate::tiff_types::{ByteOrder, IfdEntry};
18use crate::types::{Result, TagValue};
19use tracing::{debug, trace, warn};
20
21#[derive(Debug, Clone)]
24pub struct NikonEncryptionKeys {
25 pub serial_number: Option<String>,
28
29 pub shutter_count: Option<u32>,
32
33 pub camera_model: String,
36
37 pub additional_params: std::collections::HashMap<String, String>,
40}
41
42impl NikonEncryptionKeys {
43 pub fn new(model: String) -> Self {
46 debug!("Initializing Nikon encryption keys for model: {}", model);
47 Self {
48 serial_number: None,
49 shutter_count: None,
50 camera_model: model,
51 additional_params: std::collections::HashMap::new(),
52 }
53 }
54
55 pub fn store_serial_key(&mut self, serial: String) {
58 debug!("Storing Nikon serial encryption key: {}", serial);
59 self.serial_number = Some(serial);
60 }
61
62 pub fn store_count_key(&mut self, count: u32) {
65 debug!("Storing Nikon shutter count encryption key: {}", count);
66 self.shutter_count = Some(count);
67 }
68
69 pub fn has_required_keys(&self) -> bool {
72 let has_keys = self.serial_number.is_some() && self.shutter_count.is_some();
73
74 if has_keys {
75 debug!("Nikon encryption keys available (serial + count)");
76 } else {
77 trace!(
78 "Nikon encryption keys incomplete - serial: {}, count: {}",
79 self.serial_number.is_some(),
80 self.shutter_count.is_some()
81 );
82 }
83
84 has_keys
85 }
86
87 pub fn get_serial_key(&self) -> Option<&str> {
90 self.serial_number.as_deref()
91 }
92
93 pub fn get_count_key(&self) -> Option<u32> {
96 self.shutter_count
97 }
98
99 pub fn set_parameter(&mut self, key: String, value: String) {
102 trace!("Setting Nikon encryption parameter: {} = {}", key, value);
103 self.additional_params.insert(key, value);
104 }
105
106 pub fn get_parameter(&self, key: &str) -> Option<&str> {
109 self.additional_params.get(key).map(|s| s.as_str())
110 }
111}
112
113pub fn process_nikon_encrypted(
116 reader: &mut crate::exif::ExifReader,
117 data: &[u8],
118 keys: &NikonEncryptionKeys,
119) -> crate::types::Result<()> {
120 debug!("Processing Nikon encrypted data (Phase 1: detection only)");
121
122 if data.is_empty() {
123 warn!("No encrypted data to process");
124 return Ok(());
125 }
126
127 let tag_source = reader.create_tag_source_info("MakerNotes");
129
130 let status = if keys.has_required_keys() {
131 debug!("Nikon encrypted section detected with valid keys");
132 format!(
133 "Encrypted data detected (keys available: serial={}, count={}, decryption not implemented)",
134 keys.get_serial_key().unwrap_or("none"),
135 keys.get_count_key().map(|c| c.to_string()).unwrap_or("none".to_string())
136 )
137 } else {
138 debug!("Nikon encrypted section detected without keys");
139 "Encrypted data detected (keys required for decryption)".to_string()
140 };
141
142 reader.store_tag_with_precedence(
143 0x00FE, crate::types::TagValue::String(status),
145 tag_source,
146 );
147
148 Ok(())
156}
157
158pub fn validate_encryption_keys(keys: &NikonEncryptionKeys, model: &str) -> Result<()> {
161 use crate::types::ExifError;
162
163 if !keys.has_required_keys() {
165 return Err(ExifError::ParseError(
166 "Required encryption keys not available".to_string(),
167 ));
168 }
169
170 match model {
173 model if model.contains("Z 9") => {
174 debug!("Validated encryption keys for Nikon Z 9");
175 }
176 model if model.contains("D850") => {
177 debug!("Validated encryption keys for Nikon D850");
178 }
179 _ => {
180 debug!("Generic encryption key validation for model: {}", model);
181 }
182 }
183
184 Ok(())
185}
186
187pub fn process_encrypted_sections(
190 reader: &mut ExifReader,
191 base_offset: usize,
192 keys: &NikonEncryptionKeys,
193) -> Result<()> {
194 trace!(
195 "Processing encrypted Nikon sections at offset {:#x}",
196 base_offset
197 );
198
199 let data = reader.get_data().to_vec();
200
201 if base_offset + 2 > data.len() {
203 debug!(
204 "Insufficient data for encrypted section processing at offset {:#x}",
205 base_offset
206 );
207 return Ok(());
208 }
209
210 let byte_order = match &reader.header {
212 Some(header) => header.byte_order,
213 None => {
214 debug!("No TIFF header available for byte order, using little endian");
215 ByteOrder::LittleEndian
216 }
217 };
218
219 let num_entries = match byte_order.read_u16(&data, base_offset) {
221 Ok(count) => count as usize,
222 Err(_) => {
223 debug!(
224 "Failed to read IFD entry count for encrypted section at offset {:#x}",
225 base_offset
226 );
227 return Ok(());
228 }
229 };
230
231 debug!("Scanning {} entries for encrypted Nikon data", num_entries);
232
233 let mut encrypted_sections_found = 0;
234 let mut encrypted_tags = Vec::new();
235
236 for index in 0..num_entries {
239 let entry_offset = base_offset + 2 + 12 * index;
240
241 if entry_offset + 12 > data.len() {
242 debug!(
243 "Entry {} at offset {:#x} beyond data bounds during encryption scan",
244 index, entry_offset
245 );
246 break;
247 }
248
249 let entry = match IfdEntry::parse(&data, entry_offset, byte_order) {
251 Ok(entry) => entry,
252 Err(e) => {
253 trace!(
254 "Failed to parse IFD entry {} during encryption scan: {:?}",
255 index,
256 e
257 );
258 continue;
259 }
260 };
261
262 if is_encrypted_nikon_tag(entry.tag_id) {
265 encrypted_sections_found += 1;
266 encrypted_tags.push(entry.tag_id);
267
268 trace!("Found encrypted tag {:#x} at entry {}", entry.tag_id, index);
269
270 let tag_source = reader.create_tag_source_info("Nikon");
272 let tag_info = if keys.has_required_keys() {
273 format!(
274 "Encrypted tag {:#x} (keys available, decryption not implemented)",
275 entry.tag_id
276 )
277 } else {
278 format!(
279 "Encrypted tag {:#x} (keys required for decryption)",
280 entry.tag_id
281 )
282 };
283
284 reader.store_tag_with_precedence(
285 0x1000 + entry.tag_id, TagValue::String(tag_info),
287 tag_source,
288 );
289 }
290 }
291
292 let tag_source = reader.create_tag_source_info("Nikon");
294
295 if encrypted_sections_found > 0 {
296 let encryption_summary = if keys.has_required_keys() {
297 format!(
298 "Found {} encrypted sections (keys available: serial={}, count={})",
299 encrypted_sections_found,
300 keys.get_serial_key().unwrap_or("none"),
301 keys.get_count_key()
302 .map(|c| c.to_string())
303 .unwrap_or("none".to_string())
304 )
305 } else {
306 format!(
307 "Found {encrypted_sections_found} encrypted sections (keys incomplete for decryption)"
308 )
309 };
310
311 reader.store_tag_with_precedence(
312 0x00FF, TagValue::String(encryption_summary),
314 tag_source,
315 );
316
317 debug!(
318 "Detected {} encrypted Nikon sections: {:?}",
319 encrypted_sections_found, encrypted_tags
320 );
321 } else {
322 reader.store_tag_with_precedence(
323 0x00FF, "No encrypted sections detected".into(),
325 tag_source,
326 );
327
328 debug!("No encrypted Nikon sections detected");
329 }
330
331 debug!(
332 "Encrypted section processing completed - {} sections found",
333 encrypted_sections_found
334 );
335 Ok(())
336}
337
338pub fn is_encrypted_nikon_tag(tag_id: u16) -> bool {
341 match tag_id {
344 0x0088 => true, 0x0091 => true, 0x0097 => true, 0x0098 => true, 0x00A8 => true, 0x00B0 => true, 0x00B7 => true, 0x00B9 => true, _ => false, }
355}
356
357#[cfg(test)]
358mod tests {
359 use super::*;
360
361 #[test]
362 fn test_encryption_keys_initialization() {
363 let keys = NikonEncryptionKeys::new("NIKON Z 9".to_string());
364 assert_eq!(keys.camera_model, "NIKON Z 9");
365 assert!(!keys.has_required_keys());
366 }
367
368 #[test]
369 fn test_serial_key_storage() {
370 let mut keys = NikonEncryptionKeys::new("NIKON D850".to_string());
371 keys.store_serial_key("12345678".to_string());
372
373 assert_eq!(keys.get_serial_key(), Some("12345678"));
374 assert!(!keys.has_required_keys()); }
376
377 #[test]
378 fn test_count_key_storage() {
379 let mut keys = NikonEncryptionKeys::new("NIKON Z 9".to_string());
380 keys.store_count_key(1000);
381
382 assert_eq!(keys.get_count_key(), Some(1000));
383 assert!(!keys.has_required_keys()); }
385
386 #[test]
387 fn test_complete_key_set() {
388 let mut keys = NikonEncryptionKeys::new("NIKON D850".to_string());
389 keys.store_serial_key("12345678".to_string());
390 keys.store_count_key(1500);
391
392 assert!(keys.has_required_keys());
393 assert_eq!(keys.get_serial_key(), Some("12345678"));
394 assert_eq!(keys.get_count_key(), Some(1500));
395 }
396
397 #[test]
398 fn test_additional_parameters() {
399 let mut keys = NikonEncryptionKeys::new("NIKON Z 9".to_string());
400 keys.set_parameter("DecryptStart".to_string(), "0x100".to_string());
401
402 assert_eq!(keys.get_parameter("DecryptStart"), Some("0x100"));
403 assert_eq!(keys.get_parameter("Unknown"), None);
404 }
405
406 #[test]
407 fn test_encryption_validation_without_keys() {
408 let keys = NikonEncryptionKeys::new("NIKON D850".to_string());
409 let result = validate_encryption_keys(&keys, "NIKON D850");
410
411 assert!(result.is_err());
412 assert!(result
413 .unwrap_err()
414 .to_string()
415 .contains("Required encryption keys not available"));
416 }
417
418 #[test]
419 fn test_encryption_validation_with_keys() {
420 let mut keys = NikonEncryptionKeys::new("NIKON Z 9".to_string());
421 keys.store_serial_key("12345678".to_string());
422 keys.store_count_key(2000);
423
424 let result = validate_encryption_keys(&keys, "NIKON Z 9");
425 assert!(result.is_ok());
426 }
427}