cliff3_util/
encrypt_util.rs

1//! SHA(256, 512), AES 및 RSA 암호화 관련 함수 모음
2//!
3//! 사용한 crate 목록은 다음과 같다.
4//! * [sha256](https://crates.io/crates/sha256)
5//! * [rsa](https://crates.io/crates/rsa)
6
7use std::fmt::{Display, Formatter};
8
9use openssl::error::ErrorStack;
10use openssl::pkey::Private;
11use openssl::rsa::{Padding, Rsa};
12use openssl::symm::{decrypt, encrypt, Cipher};
13use sha2::{Digest, Sha256 as sha2_256, Sha512 as sha2_512};
14
15use crate::error::{InvalidArgumentError, LibError, MissingArgumentError};
16
17// 반복 횟수 기본값
18// const DEFAULT_REPEAT: u16 = 1_000;
19
20// /// TODO(joonho): 2024-02-14 주석 추가
21// #[allow(non_camel_case_types)]
22// pub enum Transformation {
23//     /// RSA/ECB/PKCS1Padding
24//     RSA_ECB_PKCS1PADDING,
25//
26//     // AES/CBC/PKCS5Padding
27//     AES_CBC_PKCS5PADDING,
28//
29//     /// [Transformation::RSA_ECB_PKCS1PADDING]와 동일
30//     RSA,
31// }
32//
33// impl Transformation {
34//     /// [Transformation] 항목을 문자열 형태로 반환
35//     pub fn get_transformation(&self) -> &'static str {
36//         match self {
37//             Transformation::RSA_ECB_PKCS1PADDING => "RSA/ECB/PKCS1Padding",
38//             Transformation::AES_CBC_PKCS5PADDING => "AES/CBC/PKCS5Padding",
39//             _ => "RSA/ECB/PKCS1Padding",
40//         }
41//     }
42// }
43
44// CryptoError -------------------------------------------------------------------------------------
45/// 암호화 처리 중 발생하는 오류
46#[derive(PartialEq, Debug)]
47pub struct CryptoError {
48    message: String,
49}
50
51impl Default for CryptoError {
52    fn default() -> Self {
53        CryptoError {
54            message: "암호화 처리중 오류가 발생하였습니다.".to_owned(),
55        }
56    }
57}
58
59impl Display for CryptoError {
60    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61        write!(f, "Encrypt/Decrypt error.")
62    }
63}
64
65impl From<&str> for CryptoError {
66    fn from(value: &str) -> Self {
67        CryptoError {
68            message: value.to_owned(),
69        }
70    }
71}
72
73impl LibError for CryptoError {
74    fn get_message(&self) -> &str {
75        self.message.as_str()
76    }
77
78    fn get_type_name_from_instance(&self) -> &str {
79        std::any::type_name::<CryptoError>()
80    }
81}
82
83// Define enum -------------------------------------------------------------------------------------
84/// SHA 256/512
85#[derive(PartialEq)]
86#[allow(non_camel_case_types)]
87pub enum SHA_TYPE {
88    /// SHA-256
89    SHA_256,
90
91    /// SHA-512
92    SHA_512,
93}
94
95/// AES 128/256
96#[derive(PartialEq)]
97#[allow(non_camel_case_types)]
98pub enum AES_TYPE {
99    /// AES-128
100    AES_128,
101
102    /// AES-256
103    AES_256,
104}
105
106/// 대상 문자열을 `SHA` 알고리즘을 이용하여 hash 처리 후 반환
107///
108/// 두 번째 인자 `salt`가 존재할 경우 이를 반영하여 처리함.
109///
110/// # Arguments
111///
112/// - `hash_type` - [SHA_TYPE]
113/// - `target` - Hash 대상
114/// - `salt` - Salt
115///
116/// # Return
117///
118/// - 생성 결과 `Result<Box<u8>, MissingArgumentError>`
119///
120/// # Errors
121///
122/// - [MissingArgumentError] - Hash 대상 문자열 미지정
123///
124/// # Link
125///
126/// - [SHA_TYPE]
127/// - [MissingArgumentError]
128///
129/// # Example
130///
131/// ```rust
132/// use cliff3_util::encrypt_util::{make_sha_hash, SHA_TYPE};
133///
134/// let mut result = make_sha_hash(SHA_TYPE::SHA_256, "test".as_bytes(), Some("salt"));
135///
136/// assert!(!result.is_err());
137///
138/// let mut v: Vec<String> = result.unwrap().iter().map(|b| format!("{:02x}", b)).collect();
139///
140/// assert_eq!(v.join(""), "4edf07edc95b2fdcbcaf2378fd12d8ac212c2aa6e326c59c3e629be3039d6432");
141///
142/// result = make_sha_hash(SHA_TYPE::SHA_512, "test".as_bytes(), Some("salt"));
143///
144/// assert!(!result.is_err());
145///
146/// v = result.unwrap().iter().map(|b| format!("{:02x}", b)).collect();
147///
148/// assert_eq!(v.join(""), "6c838e934e3feefae6cfa53af11375d4954f85c6f5ed888c02cd7806a71696d1cb449f2be78e9e6ea301a95c81f28ad8766f3ae582f9beaac33c7dc2b7ba9187")
149/// ```
150pub fn make_sha_hash(
151    hash_type: SHA_TYPE,
152    target: &[u8],
153    salt: Option<&str>,
154) -> Result<Box<[u8]>, MissingArgumentError> {
155    if target.is_empty() {
156        return Err(MissingArgumentError::from("Hash 대상이 빈 문자열 입니다."));
157    }
158
159    return match hash_type {
160        SHA_TYPE::SHA_256 => _hash_::<sha2_256>(target, salt),
161        SHA_TYPE::SHA_512 => _hash_::<sha2_512>(target, salt),
162    };
163
164    fn _hash_<D: Digest>(
165        target: &[u8],
166        salt: Option<&str>,
167    ) -> Result<Box<[u8]>, MissingArgumentError> {
168        let mut _hash = D::new();
169
170        _hash.update(target);
171
172        if !salt.is_none() && !salt.unwrap().is_empty() {
173            _hash.update(salt.unwrap().as_bytes());
174        }
175
176        let result: Vec<u8> = _hash.finalize().to_vec();
177
178        return Ok(Box::from(result.as_slice()));
179    }
180}
181
182/// 대상 문자열을 `SHA` 알고리즘을 이용하여 hash 처리 후 문자열 형태로 반환
183///
184/// 두 번째 인자 `salt`가 존재할 경우 이를 반영하여 처리함.
185///
186/// # Arguments
187///
188/// - `hash_type` - [SHA_TYPE]
189/// - `target`- Hash 대상
190/// - `salt`- Salt
191///
192/// # Return
193///
194/// - 생성 결과 `Result<Box<u8>, MissingArgumentError>`
195///
196/// # Errors
197///
198/// - [MissingArgumentError] - Hash 대상 문자열 미지정
199///
200/// # Link
201///
202/// - [SHA_TYPE]
203/// - [MissingArgumentError]
204///
205/// # Example
206///
207/// ```rust
208/// use cliff3_util::encrypt_util::{make_sha_hash_string, SHA_TYPE};
209///
210/// let result = make_sha_hash_string(SHA_TYPE::SHA_256, "test".as_bytes(), Some("salt"));
211///
212/// assert!(result.is_ok());
213///
214/// assert_eq!("4edf07edc95b2fdcbcaf2378fd12d8ac212c2aa6e326c59c3e629be3039d6432", result.unwrap());
215/// ```
216pub fn make_sha_hash_string(
217    hash_type: SHA_TYPE,
218    target: &[u8],
219    salt: Option<&str>,
220) -> Result<String, MissingArgumentError> {
221    let result = make_sha_hash(hash_type, target, salt);
222
223    match result {
224        Ok(r) => {
225            let v: Vec<String> = r.iter().map(|b| format!("{:02x}", b)).collect();
226
227            Ok(v.join(""))
228        }
229        Err(e) => Err(e),
230    }
231}
232
233/// AES 암호화 결과
234#[derive(Debug)]
235pub struct AESResult {
236    /// Salt
237    salt: Option<Vec<u8>>,
238
239    /// 암호화 결과
240    result: Vec<u8>,
241
242    /// 암호화 결과(16진수 문자열)
243    result_str: Option<String>,
244
245    /// 생성된 Initialize vector
246    iv: Vec<u8>,
247}
248
249impl AESResult {
250    fn new(salt: Option<&[u8]>, result: &[u8], iv: &[u8]) -> Self {
251        AESResult {
252            salt: match salt {
253                None => None,
254                Some(v) => Some(Vec::from(v)),
255            },
256            result: Vec::from(result),
257            result_str: {
258                let v = Vec::from(result);
259                let v: Vec<String> = v.iter().map(|b| format!("{:02x}", b)).collect();
260
261                Some(v.join(""))
262            },
263            iv: Vec::from(iv),
264        }
265    }
266
267    /// `salt` 반환
268    #[inline]
269    pub fn salt(&self) -> Option<&[u8]> {
270        return match &self.salt {
271            None => None,
272            Some(v) => {
273                return Some(v.as_ref());
274            }
275        };
276    }
277
278    /// 암호화 결과 반환
279    #[inline]
280    pub fn result(&self) -> &[u8] {
281        self.result.as_ref()
282    }
283
284    /// 암호화 결과(16진수 문자열) 반환
285    #[inline]
286    pub fn result_str(&self) -> Option<&str> {
287        match &self.result_str {
288            None => None,
289            Some(v) => Some(v.as_str()),
290        }
291    }
292
293    /// `iv` 반환
294    #[inline]
295    pub fn iv(&self) -> &[u8] {
296        self.iv.as_ref()
297    }
298
299    // ---------------------------------------------------------------------------------------------
300    // deprecated
301    // ---------------------------------------------------------------------------------------------
302
303    /// `salt` 반환
304    #[deprecated(note = "salt(&self)로 대체. 삭제 예정.")]
305    pub fn get_salt(&self) -> Option<&[u8]> {
306        return match &self.salt {
307            None => None,
308            Some(v) => {
309                return Some(v.as_ref());
310            }
311        };
312    }
313
314    /// 암호화 결과 반환
315    #[deprecated(note = "result(&self)로 대체. 삭제 예정.")]
316    pub fn get_result(&self) -> &[u8] {
317        return self.result.as_ref();
318    }
319
320    /// `iv` 반환
321    #[deprecated(note = "iv(&self)로 대체. 삭제 예정.")]
322    pub fn get_iv(&self) -> &[u8] {
323        return self.iv.as_ref();
324    }
325}
326
327impl Display for AESResult {
328    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
329        write!(
330            f,
331            "salt : {:#?}\n, result : {:#?}\n, iv : {:#?}",
332            self.salt, self.result, self.iv
333        )
334    }
335}
336
337/// 인자로 전달된 `salt` 유효성 검사. 만약 `salt`가 전달 되었을 경우 **8 bytes** 여부를 확인
338///
339/// # Arguments
340///
341/// - `salt` - Salt
342///
343/// # Return
344///
345/// - 유효성 검사 결과
346///
347/// # Errors
348///
349/// - [InvalidArgumentError] - **8 bytes** 조건 불일치
350pub fn validate_salt(salt: Option<&[u8]>) -> Result<(), InvalidArgumentError> {
351    return match salt {
352        None => Ok(()),
353        Some(v) => {
354            return if v.len() != 8 {
355                Err(InvalidArgumentError::from(
356                    "Salt length is invalid(must 8 bytes)",
357                ))
358            } else {
359                Ok(())
360            };
361        }
362    };
363}
364
365/// [AES_TYPE]을 이용한 `AES 128/256` 암호화
366///
367/// 정상적으로 처리된 경우 [AESResult]를 반환한다. `salt`는 **8 bytes**여야 한다.
368///
369/// ### `salt` 관련 참고 사항
370/// - [openssl::pkcs5::bytes_to_key] => `pub const PKCS5_SALT_LEN: c_int = 8;`
371/// - [Git hub comment][github_comment]
372/// - [openssl-enc options][openssl_enc_options]
373///
374/// # Arguments
375///
376/// - `enc_type` - [AES_TYPE]
377/// - `target` - 암호화 대상
378/// - `secret` - Secret key
379/// - `salt` - salt (8 bytes) ([validate_salt] 참고)
380/// - `repeat_count` - 반복 횟수
381///
382/// # Return
383///
384/// - 암호화 결과 `Result<AESResult, Box<dyn LibError>>`
385///
386/// # Errors
387///
388/// - [MissingArgumentError] - 암호화 대상 문자열 미지정
389/// - [InvalidArgumentError] - `salt`의 길이가 `8 bytes`가 아닐 경우 혹은 암호화 대상 문자열이 빈 문자열일 경우
390/// - [CryptoError] - [openssl::pkcs5::KeyIvPair] 생성 실패
391///
392/// # Link
393///
394/// - [AES_TYPE]
395/// - [AESResult]
396///
397/// # Example
398///
399/// [github_comment]: https://github.com/openssl/openssl/issues/19026#issuecomment-1251538241
400/// [openssl_enc_options]: https://www.openssl.org/docs/manmaster/man1/openssl-enc.html
401///
402/// ```rust
403/// use cliff3_util::encrypt_util::{aes_encrypt, AES_TYPE, AESResult};
404///
405/// let plain_text = "This 이것 that 저것";
406/// let secret = "this is secret key";
407/// let salt = "12ag3$s!"; // 8 bytes
408/// let result = aes_encrypt(AES_TYPE::AES_128, plain_text.as_bytes(), secret.as_bytes(), Some(salt.as_bytes()), 10);
409///
410/// assert!(!result.is_err());
411///
412/// let unwrapped: AESResult = result.unwrap();
413///
414/// assert!(unwrapped.result().len() > 0);
415/// ```
416pub fn aes_encrypt(
417    enc_type: AES_TYPE,
418    target: &[u8],
419    secret: &[u8],
420    salt: Option<&[u8]>,
421    repeat_count: usize,
422) -> Result<AESResult, Box<dyn LibError>> {
423    if target.is_empty() {
424        return Err(Box::from(InvalidArgumentError::from(
425            "암호화 대상이 빈 문자열 입니다",
426        )));
427    }
428
429    let validate_salt = validate_salt(salt);
430
431    if validate_salt.is_err() {
432        return Err(Box::from(validate_salt.err().unwrap()));
433    }
434
435    let cipher = if AES_TYPE::AES_128 == enc_type {
436        Cipher::aes_128_cbc()
437    } else {
438        Cipher::aes_256_cbc()
439    };
440    let key_spec = openssl::pkcs5::bytes_to_key(
441        cipher,
442        openssl::hash::MessageDigest::md5(),
443        secret,
444        salt,
445        repeat_count as i32,
446    );
447
448    if key_spec.is_err() {
449        eprintln!("AES error : {:#?}", key_spec.err());
450
451        return Err(Box::from(CryptoError::from(
452            "AES 암호화 처리 중 오류가 발생하였습니다.",
453        )));
454    }
455
456    let unwrapped_spec = key_spec.unwrap();
457    let key = unwrapped_spec.key;
458    let iv = unwrapped_spec.iv.unwrap();
459
460    // let mut iv: [u8; 16] = [0u8; 16];
461    //
462    // rand::thread_rng().fill_bytes(&mut iv);
463
464    let result: Result<Vec<u8>, ErrorStack> =
465        encrypt(cipher, key.as_slice(), Some(iv.as_slice()), target);
466
467    match result {
468        Ok(vv) => Ok(AESResult::new(salt, vv.as_slice(), iv.as_slice())),
469        Err(e) => {
470            eprintln!("AES encrypt error : {:#?}", e);
471
472            Err(Box::from(InvalidArgumentError::from("암호화 처리 오류")))
473        }
474    }
475}
476
477/// [AES_TYPE]을 이용한 암호화(`AES 128/256`) 결과를 복호화 처리
478///
479/// 정상적으로 처리된 경우 `Box<u8>`을 반환한다.
480///
481/// # Arguments
482///
483/// - `enc_type` - [AES_TYPE]
484/// - `target` - [aes_encrypt]를 이용한 암호화 결과
485/// - `secret` - Secret key
486/// - `iv` - Initialize vector
487/// - `salt` - [aes_encrypt]시 사용한 `salt` ([validate_salt] 참고)
488/// - `repeat_count` - [aes_encrypt]시 지정한 반복 횟수
489///
490/// # Return
491///
492/// - 복호화 결과 `Result<Box<u8>, Box<dyn LibError>>`
493///
494/// # Errors
495///
496/// - [MissingArgumentError] - 복호화 대상 미지정
497/// - [InvalidArgumentError] - `salt`의 길이가 `8 bytes`가 아닐 경우 혹은 복호화 대상의 길이가 `0`일 경우
498/// - [CryptoError] - [openssl::pkcs5::KeyIvPair] 생성 실패
499///
500/// # Example
501///
502/// ```rust
503/// use cliff3_util::encrypt_util::{aes_decrypt, aes_encrypt, AES_TYPE, AESResult};
504/// use cliff3_util::encrypt_util::AES_TYPE::AES_128;
505///
506/// let plain_text = "abcd한글";
507/// let salt = "4s8sdf*!"; // 8 bytes
508/// let secret = "LSDIy8&%^&Dfshfbsjf";
509/// let result = aes_encrypt(AES_128, plain_text.as_bytes(), secret.as_bytes(), Some(salt.as_bytes()), 10);
510///
511/// assert!(!result.is_err());
512///
513/// let unwrapped: AESResult = result.unwrap();
514///
515/// println!("unwrapped: {:#?}", unwrapped);
516///
517/// let decrypted_result = aes_decrypt(AES_128, Some(unwrapped.result()), secret.as_bytes(), unwrapped.iv(), Some(salt.as_bytes()), 10);
518///
519/// assert!(!decrypted_result.is_err());
520///
521/// let decrypted_raw = decrypted_result.unwrap();
522///
523/// assert_eq!(plain_text, String::from_utf8_lossy(decrypted_raw.as_ref()));
524/// ```
525pub fn aes_decrypt(
526    enc_type: AES_TYPE,
527    target: Option<&[u8]>,
528    secret: &[u8],
529    iv: &[u8],
530    salt: Option<&[u8]>,
531    repeat_count: usize,
532) -> Result<Box<[u8]>, Box<dyn LibError>> {
533    match target {
534        None => Err(Box::from(MissingArgumentError::from(
535            "복호화 대상이 지정되지 않았습니다.",
536        ))),
537        Some(v) => {
538            if v.len() == 0 {
539                return Err(Box::from(InvalidArgumentError::from(
540                    "복호화 대상의 길이가 0 입니다.",
541                )));
542            }
543
544            let validate_salt = validate_salt(salt);
545
546            if validate_salt.is_err() {
547                return Err(Box::from(validate_salt.err().unwrap()));
548            }
549
550            let cipher = if AES_TYPE::AES_128 == enc_type {
551                Cipher::aes_128_cbc()
552            } else {
553                Cipher::aes_256_cbc()
554            };
555            let key_spec = openssl::pkcs5::bytes_to_key(
556                cipher,
557                openssl::hash::MessageDigest::md5(),
558                secret,
559                salt,
560                repeat_count as i32,
561            );
562
563            if key_spec.is_err() {
564                eprintln!("AES error: {:#?}", key_spec.err());
565
566                return Err(Box::from(CryptoError::from(
567                    "AES 복호화 처리 중 오류가 발생하였습니다.",
568                )));
569            }
570
571            let unwrapped_spec = key_spec.unwrap();
572            let key = unwrapped_spec.key;
573
574            let result = decrypt(cipher, key.as_slice(), Some(iv), v);
575
576            match result {
577                Ok(vv) => Ok(Box::from(vv.as_slice())),
578
579                Err(e) => {
580                    eprintln!("AES decrypt error: {:#?}", e);
581
582                    Err(Box::from(InvalidArgumentError::from("복호화 처리 오류")))
583                }
584            }
585        }
586    }
587}
588
589// RSA ---------------------------------------------------------------------------------------------
590// #[allow(non_camel_case_types)]
591// enum LoadKeyType {
592//     /// 공개키
593//     PUBLIC_KEY,
594//
595//     /// 개인키
596//     PRIVATE_KEY,
597// }
598
599/// RSA 암호화 bit 지정
600#[allow(non_camel_case_types)]
601pub enum RSA_BIT {
602    /// 1024 bit, 암호화 결과는 128 bytes
603    B_1024,
604
605    /// 2048 bit, 암호화 결과는 256 bytes
606    B_2048,
607
608    /// 4096 bit, 암호화 결과는 512 bytes
609    B_4096,
610
611    /// 8192 bit, 암호화 결과는 1024 bytes
612    B_8192,
613}
614
615impl RSA_BIT {
616    /// 해당 값을 `usize` 형태로 반환
617    pub fn bit(&self) -> usize {
618        match self {
619            RSA_BIT::B_1024 => 1024usize,
620            RSA_BIT::B_2048 => 2048usize,
621            RSA_BIT::B_4096 => 4096usize,
622            RSA_BIT::B_8192 => 8192usize,
623        }
624    }
625
626    pub fn bytes(&self) -> u16 {
627        match self {
628            RSA_BIT::B_1024 => 128,
629            RSA_BIT::B_2048 => 256,
630            RSA_BIT::B_4096 => 512,
631            RSA_BIT::B_8192 => 1024,
632        }
633    }
634}
635
636/// RSA 암호화 결과
637pub struct RSAResult {
638    /// 공개키
639    public_key: Vec<u8>,
640
641    /// 공개키 계수(modulus)
642    public_modulus: Vec<u8>,
643
644    /// 공개키 지수(exponent)
645    public_exponent: Vec<u8>,
646
647    /// 개인키
648    private_key: Vec<u8>,
649
650    /// 개인키 계수(modulus)
651    private_modulus: Vec<u8>,
652
653    /// 개인키 지수(exponent)
654    private_exponent: Vec<u8>,
655
656    /// 암호화 결과
657    result: Vec<u8>,
658
659    /// 암호화 결과(16진수 문자열)
660    result_str: Option<String>,
661}
662
663impl RSAResult {
664    pub fn new(
665        pub_key: &[u8],
666        pub_mod: &[u8],
667        pub_exp: &[u8],
668        prv_key: &[u8],
669        prv_mod: &[u8],
670        prv_exp: &[u8],
671        result: &[u8],
672    ) -> Self {
673        RSAResult {
674            public_key: Vec::from(pub_key),
675            public_modulus: Vec::from(pub_mod),
676            public_exponent: Vec::from(pub_exp),
677            private_key: Vec::from(prv_key),
678            private_modulus: Vec::from(prv_mod),
679            private_exponent: Vec::from(prv_exp),
680            result: Vec::from(result),
681            result_str: {
682                let v = Vec::from(result);
683                let v: Vec<String> = v.iter().map(|b| format!("{:02x}", b)).collect();
684
685                Some(v.join(""))
686            },
687        }
688    }
689
690    /// 공개키 반환
691    #[inline]
692    pub fn public_key(&self) -> &[u8] {
693        self.public_key.as_ref()
694    }
695
696    /// 공개키 계수(modulus) 반환
697    #[inline]
698    pub fn public_modulus(&self) -> &[u8] {
699        self.public_modulus.as_ref()
700    }
701
702    /// 공개키 지수(exponent) 반환
703    #[inline]
704    pub fn public_exponent(&self) -> &[u8] {
705        self.public_exponent.as_ref()
706    }
707    /// 개인키 반환
708    #[inline]
709    pub fn private_key(&self) -> &[u8] {
710        self.private_key.as_ref()
711    }
712
713    /// 개인키 계수(modulus) 반환
714    #[inline]
715    pub fn private_modulus(&self) -> &[u8] {
716        self.private_modulus.as_ref()
717    }
718
719    /// 개인키 지수(exponent) 반환
720    #[inline]
721    pub fn private_exponent(&self) -> &[u8] {
722        self.private_exponent.as_ref()
723    }
724
725    /// 암호화 결과 반환
726    #[inline]
727    pub fn result(&self) -> &[u8] {
728        self.result.as_ref()
729    }
730
731    /// 암호화 결과(16진수 문자열) 반환
732    #[inline]
733    pub fn result_str(&self) -> Option<&str> {
734        match &self.result_str {
735            None => None,
736            Some(v) => Some(v.as_str()),
737        }
738    }
739
740    // ---------------------------------------------------------------------------------------------
741    // deprecated
742    // ---------------------------------------------------------------------------------------------
743
744    /// 공개키 반환
745    #[deprecated(note = "public_key(&self)로 대체. 삭제 예정.")]
746    pub fn get_public_key(&self) -> &[u8] {
747        self.public_key.as_ref()
748    }
749
750    /// 공개키 계수(modulus) 반환
751    #[deprecated(note = "public_modulus(&self)로 대체. 삭제 예정.")]
752    pub fn get_public_modulus(&self) -> &[u8] {
753        self.public_modulus.as_ref()
754    }
755
756    /// 공개키 지수(exponent) 반환
757    #[deprecated(note = "public_exponent(&self)로 대체. 삭제 예정.")]
758    pub fn get_public_exponent(&self) -> &[u8] {
759        self.public_exponent.as_ref()
760    }
761
762    /// 개인키 반환
763    #[deprecated(note = "private_key(&self)로 대체. 삭제 예정.")]
764    pub fn get_private_key(&self) -> &[u8] {
765        self.private_key.as_ref()
766    }
767
768    /// 개인키 계수(modulus) 반환
769    #[deprecated(note = "private_modulus(&self)로 대체. 삭제 예정.")]
770    pub fn get_private_modulus(&self) -> &[u8] {
771        self.private_modulus.as_ref()
772    }
773
774    /// 개인키 지수(exponent) 반환
775    #[deprecated(note = "private_exponent(&self)로 대체. 삭제 예정.")]
776    pub fn get_private_exponent(&self) -> &[u8] {
777        self.private_exponent.as_ref()
778    }
779
780    /// 암호화 결과 반환
781    #[deprecated(note = "result(&self)로 대체. 삭제 예정.")]
782    pub fn get_result(&self) -> &[u8] {
783        self.result.as_ref()
784    }
785}
786
787/// 지정된 [RSA_BIT] 기준으로 RSA keypair를 생성하여 반환
788///
789/// # Arguments
790///
791/// - `bit_size` - [RSA_BIT]
792///
793/// # Return
794///
795/// - 생성된 keypair 결과 `Result<Rsa<Private>, CryptoError>`
796///
797/// # Errors
798///
799/// - [CryptoError] - Keypair 생성 오류
800///
801/// # Link
802///
803/// - [Rsa]
804/// - [Private]
805/// - [CryptoError]
806pub fn generate_rsa_keypair(bit_size: RSA_BIT) -> Result<Rsa<Private>, CryptoError> {
807    let rsa: Result<Rsa<Private>, ErrorStack> = Rsa::generate(bit_size.bit() as u32);
808
809    if rsa.is_err() {
810        eprintln!("Generate RSA key pair fail : {:#?}", rsa.err());
811
812        return Err(CryptoError::from(
813            "RSA key pair 생성 중 오류가 발생하였습니다.",
814        ));
815    }
816
817    return Ok(rsa.unwrap());
818}
819
820/// [RSA_BIT]를 이용한 RSA 암호화 처리
821///
822/// 자동으로 [`Rsa<Private>`]를 생성하여 암호화 처리를 한 후 [RSAResult]에 생성된 키 정보와 암호화
823/// 결과를 포함하여 반환한다.
824///
825/// # Arguments
826///
827/// - `target` - 암호화 대상
828/// - `bit_size` - [RSA_BIT]
829///
830/// # Return
831///
832/// - RSA 암호화 결과 `Result<Box<RSAResult>, CryptoError>`
833///
834/// # Errors
835///
836/// ## [CryptoError]
837///
838/// - [generate_rsa_keypair] 호출에서 발생
839///     - `Rsa<Private>.public_key_to_pem` 호출에서 발생
840///     - `Rsa<Private>.private_key_to_pem` 호출에서 발생
841///     - [rsa_encrypt] 호출에서 발생
842///
843/// # Link
844///
845/// - [RSA_BIT]
846/// - [RSAResult]
847/// - [CryptoError]
848///
849/// # Example
850///
851/// ```rust
852/// use cliff3_util::encrypt_util::{RSA_BIT, rsa_encrypt_without_key};
853///
854/// const PLAIN_TEXT: &str = "이것은 테스트 입니다.";
855/// let result =rsa_encrypt_without_key(PLAIN_TEXT.as_bytes(), RSA_BIT::B_4096);
856///
857/// assert!(!result.is_err());
858///
859/// let raw = result.unwrap();
860///
861/// assert!(raw.private_key().len() > 0, "개인키 반환 실패");
862/// assert!(raw.private_exponent().len() > 0, "개인키 지수 반환 실패");
863/// assert!(raw.private_modulus().len() > 0, "개인키 계수 반환 실패");
864/// assert!(raw.public_key().len() > 0, "공개키 반환 실패");
865/// assert!(raw.public_exponent().len() > 0, "공개키 지수 반환 실패");
866/// assert!(raw.public_modulus().len() > 0, "공개키 계수 반환 실패");
867/// assert_eq!(raw.result().len(), RSA_BIT::B_4096.bytes() as usize, "암호화 결과 길이 불일치");
868/// ```
869pub fn rsa_encrypt_without_key(
870    target: &[u8],
871    bit_size: RSA_BIT,
872) -> Result<Box<RSAResult>, CryptoError> {
873    let key_pair: Rsa<Private> = generate_rsa_keypair(bit_size)?;
874    let public_key = key_pair.public_key_to_pem();
875    let private_key = key_pair.private_key_to_pem();
876
877    if public_key.is_err() {
878        eprintln!("public key error: {:#?}", public_key.err());
879
880        return Err(CryptoError::from("Public key에서 오류가 발생하였습니다."));
881    }
882
883    if private_key.is_err() {
884        eprintln!("private key error: {:#?}", private_key.err());
885
886        return Err(CryptoError::from("Private key에서 오류가 발생하였습니다."));
887    }
888
889    let unwrapped_pub_key = public_key.unwrap();
890    let unwrapped_prv_key = private_key.unwrap();
891
892    let result = rsa_encrypt(target, unwrapped_pub_key.as_slice())?;
893
894    let rsa_result = RSAResult::new(
895        unwrapped_pub_key.as_slice(),
896        key_pair.n().to_vec().as_slice(),
897        key_pair.e().to_vec().as_slice(),
898        unwrapped_prv_key.as_slice(),
899        key_pair.n().to_vec().as_slice(),
900        key_pair.d().to_vec().as_slice(),
901        result.as_ref(),
902    );
903
904    return Ok(Box::from(rsa_result));
905}
906
907/// RSA 복호화
908///
909/// # Arguments
910///
911/// - `target` - 복호화 대상
912/// - `prv_key` - 암호화시 생성된 개인키
913///
914/// # Return
915///
916/// - RSA 복호화 결과 `Result<Vec<u8>, CryptoError>`
917///
918/// # Errors
919///
920/// - [CryptoError] - 암호화 처리 중 오류 발생
921///
922/// # Example
923///
924/// ```rust
925/// use cliff3_util::encrypt_util::{RSA_BIT, rsa_decrypt, rsa_encrypt_without_key, RSAResult};
926///
927/// let plaint_text = "This 이것 that 저것";
928/// let result = rsa_encrypt_without_key(plaint_text.as_bytes(), RSA_BIT::B_2048);
929///
930/// assert!(!result.is_err());
931///
932/// let unwrapped_encrypt_result = result.unwrap();
933///
934/// assert_eq!(unwrapped_encrypt_result.result().len(), RSA_BIT::B_2048.bytes() as usize, "암호화 결과 불일치");
935///
936/// let decrypt_result = rsa_decrypt(unwrapped_encrypt_result.result(), unwrapped_encrypt_result.private_key());
937///
938/// assert!(!decrypt_result.is_err());
939///
940/// let unwrapped_decrypt_result = decrypt_result.unwrap();
941/// let decrypted_text = String::from_utf8(unwrapped_decrypt_result.to_vec()).unwrap();
942///
943/// assert_eq!(decrypted_text, plaint_text, "복호화 실패");
944/// ```
945pub fn rsa_decrypt(target: &[u8], prv_key: &[u8]) -> Result<Vec<u8>, CryptoError> {
946    let private_key = Rsa::private_key_from_pem(prv_key);
947
948    if private_key.is_err() {
949        eprintln!("개인키 생성 오류: {:#?}", private_key.err());
950
951        return Err(CryptoError::from("개인키 오류가 발생하였습니다."));
952    }
953
954    let rsa = private_key.unwrap();
955    let mut buffer: Vec<u8> = vec![0; rsa.size() as usize];
956
957    let result = rsa.private_decrypt(target, &mut buffer, Padding::PKCS1);
958
959    if result.is_err() {
960        eprintln!("RSA decrypt error : {:#?}", result.err());
961
962        return Err(CryptoError::from(
963            "RSA 복호화 처리 중 오류가 발생하였습니다.",
964        ));
965    }
966
967    let real_size = result.unwrap();
968    let final_result = &buffer[0..real_size];
969
970    return Ok(Vec::from(final_result)); // 실제 복호화된 길이 만큼만 반환
971}
972
973/// RSA 암호화 처리
974///
975/// 암호화 대상 정보(`target`)를 `pub_key`를 이용하여 암호화 처리 한다.
976///
977/// # Arguments
978///
979/// - `target` - 암호화 대상 정보
980/// - `pub_key` - 공개키 정보
981///
982/// # Return
983///
984/// - RSA 암호화 결과 `Result<Box<u8>, CryptoError>`
985fn rsa_encrypt(target: &[u8], pub_key: &[u8]) -> Result<Box<[u8]>, CryptoError> {
986    // let rsa = Rsa::generate(bit_size.bit() as u32).unwrap();
987    let public_key = Rsa::public_key_from_pem(pub_key).unwrap();
988    let rsa = Rsa::from(public_key);
989    let mut buffer = vec![0; rsa.size() as usize];
990    let result = rsa.public_encrypt(target, &mut buffer, Padding::PKCS1);
991
992    if result.is_err() {
993        eprintln!("RSA encrypt error : {:#?}", result.err());
994
995        return Err(CryptoError::from(
996            "RSA 암호화 처리 중 오류가 발생하였습니다.",
997        ));
998    }
999
1000    return Ok(Box::from(buffer.as_slice()));
1001}
1002
1003#[cfg(test)]
1004mod tests {
1005    use base64::prelude::*;
1006
1007    use super::*;
1008
1009    const PLAIN_TEXT: &str = "This 이것, That 저것";
1010
1011    #[test]
1012    pub fn make_sha_hash_test() {
1013        let mut result: Result<Box<[u8]>, MissingArgumentError> =
1014            make_sha_hash(SHA_TYPE::SHA_256, "test".as_bytes(), Some("salt"));
1015
1016        assert!(!result.is_err());
1017
1018        let v: Vec<String> = result
1019            .unwrap()
1020            .iter()
1021            .map(|b| format!("{:02x}", b))
1022            .collect();
1023
1024        println!("SHA-256 result : {}", v.join(""));
1025
1026        result = make_sha_hash(SHA_TYPE::SHA_512, "test".as_bytes(), Some("salt"));
1027
1028        assert!(!result.is_err());
1029
1030        let v: Vec<String> = result
1031            .unwrap()
1032            .iter()
1033            .map(|b| format!("{:02x}", b))
1034            .collect();
1035        let v = v.join("");
1036
1037        println!("SHA-512 result : {}", v);
1038
1039        let vv = make_sha_hash_string(SHA_TYPE::SHA_512, "test".as_bytes(), Some("salt"));
1040
1041        assert!(vv.is_ok(), "make_sha_hash_string error => {:#?}", vv.err());
1042
1043        assert_eq!(v, vv.unwrap(), "hash string 불일치")
1044    }
1045
1046    // #[test]
1047    // #[should_panic]
1048    // pub fn aes_key_length_mismatch_test() {
1049    //     // let key = Aes256Gcm::generate_key(OsRng);
1050    //
1051    //     // println!("{:#?}", key);
1052    //
1053    //     // length 32 mismatched
1054    //     let key = Key::<Aes256Gcm>::from_slice(b"abc");
1055    //     let cipher = Aes256Gcm::new(&key);
1056    // }
1057
1058    #[test]
1059    pub fn aes_encrypt_test() {
1060        let repeat_count = 10usize;
1061        let result: Result<AESResult, Box<dyn LibError>> = aes_encrypt(
1062            AES_TYPE::AES_128,
1063            PLAIN_TEXT.as_bytes(),
1064            "abc".as_bytes(),
1065            Some("salt".as_bytes()),
1066            10,
1067        );
1068
1069        assert!(result.is_err());
1070
1071        let err = result.err().unwrap();
1072        let err_name = err.get_type_name_from_instance();
1073
1074        assert_eq!(err_name, std::any::type_name::<InvalidArgumentError>());
1075        println!("err_name : {}", err_name);
1076
1077        let encrypt_result = aes_encrypt(
1078            AES_TYPE::AES_128,
1079            PLAIN_TEXT.as_bytes(),
1080            "abcdefgh".as_bytes(),
1081            Some("saltsalt".as_bytes()), // 8 bytes
1082            repeat_count,
1083        );
1084
1085        assert!(!encrypt_result.is_err(), "aes 암호화 오류 발생");
1086
1087        // LibError + Debug mixin 하지 않았을 경우 unwrap()을 호출하면 에러 발생
1088        // 만일 LibError + Debug mixin을 하지 않을 경우 unwrap_or_default() 호출해야 함
1089        let result_value = encrypt_result.unwrap();
1090
1091        println!("unwrapped value : {:#?}", result_value);
1092        println!("unwrapped result value : {:#?}", result_value.result);
1093
1094        // result_str 비교
1095        assert!(result_value.result_str().is_some());
1096
1097        let raw_result: Vec<String> = result_value
1098            .result()
1099            .iter()
1100            .map(|b| format!("{:02x}", b))
1101            .collect();
1102        let raw_result: String = raw_result.join("");
1103
1104        assert_eq!(raw_result, result_value.result_str().unwrap());
1105
1106        println!("aes result str ===> {}", result_value.result_str().unwrap());
1107
1108        let encoded_value = BASE64_STANDARD.encode(result_value.result.clone());
1109
1110        println!("aes base64 encoded value : {:#?}", encoded_value);
1111
1112        let mut salt: Option<&[u8]> = None;
1113        let unwrapped_salt: Vec<u8>;
1114
1115        if result_value.salt.is_some() {
1116            unwrapped_salt = result_value.salt.unwrap();
1117            salt = Some(unwrapped_salt.as_slice());
1118        }
1119
1120        println!("final sal : {:#?}", salt);
1121
1122        let decrypt_result = aes_decrypt(
1123            AES_TYPE::AES_128,
1124            Some(result_value.result.as_ref()),
1125            b"abcdefgh",
1126            result_value.iv.as_ref(),
1127            salt,
1128            repeat_count,
1129        );
1130
1131        assert!(!decrypt_result.is_err(), "aes 복호화 오류 발생");
1132
1133        let decrypted_raw_value = decrypt_result.unwrap();
1134        let decrypted_value = decrypted_raw_value.as_ref();
1135
1136        assert_eq!(
1137            PLAIN_TEXT,
1138            String::from_utf8_lossy(decrypted_value),
1139            "복호화 값 불일치"
1140        );
1141
1142        println!(
1143            "decrypted text: {:?}",
1144            String::from_utf8_lossy(decrypted_value)
1145        );
1146    }
1147
1148    #[test]
1149    pub fn rsa_encrypt_test() {
1150        let key_pair = generate_rsa_keypair(RSA_BIT::B_4096);
1151        let result1 = rsa_encrypt(
1152            PLAIN_TEXT.as_bytes(),
1153            key_pair.unwrap().public_key_to_pem().unwrap().as_slice(),
1154        );
1155
1156        assert!(!result1.is_err(), "RSA 2048 암호화 실패");
1157
1158        let result_raw = result1.unwrap();
1159
1160        assert_eq!(
1161            result_raw.len(),
1162            RSA_BIT::B_4096.bytes() as usize,
1163            "암호화 결과 길이 불일치"
1164        );
1165
1166        println!(
1167            "rsa result(4096) : {:?}\nlength : {}",
1168            result_raw,
1169            result_raw.len()
1170        );
1171
1172        let encoded_value = BASE64_STANDARD.encode(result_raw);
1173
1174        println!("rsa base 64 encoded value : {:?}", encoded_value);
1175
1176        let key_pair = generate_rsa_keypair(RSA_BIT::B_8192);
1177        let result1 = rsa_encrypt(
1178            PLAIN_TEXT.as_bytes(),
1179            key_pair.unwrap().public_key_to_pem().unwrap().as_slice(),
1180        );
1181
1182        assert!(!result1.is_err(), "RSA 8192 암호화 실패");
1183
1184        let result_raw = result1.unwrap();
1185
1186        assert_eq!(
1187            result_raw.len(),
1188            RSA_BIT::B_8192.bytes() as usize,
1189            "암호화 결과 길이 불일치"
1190        );
1191        println!(
1192            "rsa result(8192) : {:?}\nlength : {}",
1193            result_raw,
1194            result_raw.len()
1195        );
1196
1197        let result2 = rsa_encrypt_without_key(PLAIN_TEXT.as_bytes(), RSA_BIT::B_2048);
1198
1199        assert!(result2.is_ok());
1200
1201        let result2_raw = result2.unwrap();
1202
1203        assert!(result2_raw.private_key().len() > 0, "개인키 반환 실패");
1204        assert!(
1205            result2_raw.private_exponent().len() > 0,
1206            "개인키 지수 반환 실패"
1207        );
1208        assert!(
1209            result2_raw.private_modulus().len() > 0,
1210            "개인키 계수 반환 실패"
1211        );
1212        assert!(result2_raw.public_key().len() > 0, "공개키 반환 실패");
1213        assert!(
1214            result2_raw.public_exponent().len() > 0,
1215            "공개키 지수 반환 실패"
1216        );
1217        assert!(
1218            result2_raw.public_modulus().len() > 0,
1219            "공개키 계수 반환 실패"
1220        );
1221        assert!(result2_raw.result().len() > 0, "암호화 결과 반환 실패");
1222        assert_eq!(
1223            result2_raw.result().len(),
1224            RSA_BIT::B_2048.bytes() as usize,
1225            "암호화 결과 길이 불일치"
1226        );
1227
1228        // result_str 비교
1229        assert!(result2_raw.result_str().is_some());
1230
1231        let raw_result: Vec<String> = result2_raw
1232            .result()
1233            .iter()
1234            .map(|b| format!("{:02x}", b))
1235            .collect();
1236        let raw_result = raw_result.join("");
1237
1238        assert_eq!(raw_result, result2_raw.result_str().unwrap());
1239
1240        println!("rsa result str ===> {}", result2_raw.result_str().unwrap());
1241
1242        let decrypt2 = rsa_decrypt(result2_raw.result(), result2_raw.private_key());
1243
1244        assert!(!decrypt2.is_err());
1245
1246        let decrypt2_raw = decrypt2.unwrap();
1247        let decrypt2_result = String::from_utf8(decrypt2_raw.to_vec()).unwrap();
1248
1249        assert_eq!(decrypt2_result, PLAIN_TEXT, "복호화 실패");
1250
1251        println!("원문: {:?}\n복호화 결과: {:?}", PLAIN_TEXT, decrypt2_result);
1252    }
1253}