sym_crypto/cipher.rs
1// Copyright 2021 BlockPuppets developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use aes_gcm::{
10 aead::{generic_array::GenericArray, Aead, NewAead},
11 AeadInPlace, Aes256Gcm, Tag,
12};
13use anyhow::{anyhow, ensure, Result};
14use sha2::Sha512;
15
16use super::hkdf_sha256::hkdf_sha256;
17
18use crate::core::{
19 derive_shared_secret, random_bytes, AesKey, BlockCipher, PrivateKey, PublicKey, AES_TAG_LENGTH,
20 H256, KEY_BYTES_SIZE, SYM_AES_IV_LENGTH,
21};
22
23pub struct CryptoSym;
24
25impl BlockCipher for CryptoSym {
26 /// Encode a message text with AES-GCM algorithm using the signer's the PrivateKey and receiver's PublicKey.
27 ///
28 /// # Inputs
29 ///
30 /// * `signer_sk`: The signer's private key.
31 ///
32 /// * `receiver_pk`: The receiver's public key.
33 ///
34 /// * `msg`: Message to encrypt.
35 ///
36 /// # Returns
37 ///
38 /// A `Result` whose okay value is an encrypt message `Vec<u8>` or whose error value
39 /// is an `failure::Error` describing the error that occurred.
40 fn encrypt_message(
41 signer_sk: &[u8; KEY_BYTES_SIZE],
42 receiver_pk: &[u8; KEY_BYTES_SIZE],
43 msg: &[u8],
44 ) -> Result<Vec<u8>> {
45 let iv = random_bytes::<SYM_AES_IV_LENGTH>();
46
47 let signer_sk = PrivateKey::from(signer_sk);
48 let receiver_pk = PublicKey::from(receiver_pk);
49
50 let derive_key = derive_shared_key(signer_sk, receiver_pk);
51
52 let (encrypted, auth_tag) = encrypt(iv, derive_key, msg)?;
53
54 let mut enc = vec![];
55 enc.extend_from_slice(&auth_tag);
56 enc.extend_from_slice(&iv);
57 enc.extend_from_slice(&encrypted);
58 Ok(enc)
59 }
60
61 /// Decrypt a message text with AES-GCM algorithm using the receiver's the PrivateKey and signer's PublicKey.
62 ///
63 /// # Inputs
64 ///
65 /// * `receiver_sk`: The receiver's private key.
66 ///
67 /// * `signer_pk`: The signer's public key.
68 ///
69 /// * `enc_msg`: Message encrypted.
70 ///
71 /// # Example
72 ///
73 /// ```ignore
74 /// use std::str::FromStr;
75 /// use symbol_crypto_core::{PrivateKey, PublicKey,decrypt_message };
76 ///
77 /// # fn main() {
78 /// #
79 /// let receiver_sk = PrivateKey::from_str("A22A4BBF126A2D7D7ECE823174DFD184C5DE0FDE4CB2075D30CFA409F7EF8908").unwrap();
80 /// let signer_pk = PublicKey::from_str("3FD283D8543C12B81917C154CDF4EFD3D48E553E6D7BC77E29CB168138CED17D").unwrap();
81 ///
82 /// let encrypt_text_vec = [
83 /// 125, 59, 126, 248, 124, 129, 157, 100, 111, 84, 49, 163, 111, 68, 22, 137, 75, 132, 135,
84 /// 217, 251, 158, 115, 74, 226, 172, 200, 208, 33, 183, 110, 103, 107, 170, 52, 174, 192, 110,
85 /// 164, 44, 77, 69, 203, 48, 43, 17, 206, 143, 154, 155, 231, 72, 28, 24, 20, 241, 234, 202,
86 /// 184, 66,
87 /// ];
88 ///
89 /// let decrypted_text = decrypt_message( receiver_sk.as_fixed_bytes(), signer_pk.as_fixed_bytes(), &encrypt_text_vec).unwrap();
90 /// # println!("{}", String::from_utf8(decrypted_text).unwrap());
91 /// # }
92 /// ```
93 ///
94 /// # Returns
95 ///
96 /// A `Result` whose okay value is an decrypted message `Vec<u8>` or whose error value
97 /// is an `failure::Error` describing the error that occurred.
98 fn decrypt_message(
99 receiver_sk: &[u8; KEY_BYTES_SIZE],
100 signer_pk: &[u8; KEY_BYTES_SIZE],
101 enc_msg: &[u8],
102 ) -> Result<Vec<u8>> {
103 ensure!(!enc_msg.is_empty(), "msg cannot be empty");
104
105 let iv = &enc_msg[AES_TAG_LENGTH..AES_TAG_LENGTH + SYM_AES_IV_LENGTH];
106 let mut iv_bytes = [0u8; SYM_AES_IV_LENGTH];
107 iv_bytes.copy_from_slice(&iv[..]);
108
109 let tag = &enc_msg[0..AES_TAG_LENGTH];
110
111 let mut msg_and_tag_bytes = Vec::with_capacity(enc_msg.len() - SYM_AES_IV_LENGTH);
112 msg_and_tag_bytes.extend_from_slice(&enc_msg[AES_TAG_LENGTH + SYM_AES_IV_LENGTH..]);
113 msg_and_tag_bytes.extend_from_slice(&tag[..]);
114
115 let recipient_sk = PrivateKey::from(receiver_sk);
116 let signer_pk = PublicKey::from(signer_pk);
117
118 let enc_key = derive_shared_key(recipient_sk, signer_pk);
119
120 let decrypt_vec = decrypt(iv_bytes, enc_key, &msg_and_tag_bytes)?;
121
122 Ok(decrypt_vec)
123 }
124}
125
126// internal functions.
127fn derive_shared_key(secret_key: PrivateKey, public_key: PublicKey) -> H256 {
128 let shared_secret = derive_shared_secret::<Sha512>(secret_key, public_key);
129 hkdf_sha256(shared_secret)
130}
131
132/// Encrypt the given plaintext slice with AES-GCM algorithm with a 256-bit key and 96-bit nonce.
133///
134/// # Returns
135///
136/// A `Result` whose okay value is a ciphertext as a vector of bytes and auth_tag or whose error
137/// value
138/// is an `Error` describing the error that occurred.
139fn encrypt(iv: [u8; SYM_AES_IV_LENGTH], derive_key: AesKey, msg: &[u8]) -> Result<(Vec<u8>, Tag)> {
140 let key = GenericArray::from_slice(derive_key.as_fixed_bytes());
141 let cipher = Aes256Gcm::new(key);
142
143 let nonce = GenericArray::from_slice(&iv); // 96-bits; unique per message
144
145 let mut msg_buf: Vec<u8> = vec![];
146 msg_buf.extend_from_slice(msg);
147
148 let auth_tag = cipher
149 .encrypt_in_place_detached(nonce, &vec![], &mut msg_buf)
150 .map_err(|e| anyhow!("{}", e))?;
151
152 Ok((msg_buf, auth_tag))
153}
154
155/// Decrypt the given ciphertext slice with AES-GCM with a 256-bit key and 96-bit nonce.
156///
157/// # Returns
158///
159/// A `Result` whose okay value is a plaintext as a vector of bytes or whose error value
160/// is an `Error` describing the error that occurred.
161fn decrypt(iv: [u8; SYM_AES_IV_LENGTH], derive_key: AesKey, enc_msg: &[u8]) -> Result<Vec<u8>> {
162 let key = GenericArray::from_slice(derive_key.as_fixed_bytes());
163 let cipher = Aes256Gcm::new(key);
164
165 let iv = GenericArray::from_slice(&iv);
166
167 let decrypted = cipher.decrypt(iv, enc_msg).map_err(|e| anyhow!("{}", e))?;
168
169 Ok(decrypted)
170}