1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
use libsodium_sys::{
crypto_sign_ed25519_sk_to_pk,
crypto_box_easy,
crypto_scalarmult_base,
crypto_generichash,
crypto_sign_detached,
crypto_sign_BYTES as CRYPTO_SIGN_BYTES,
crypto_sign_SECRETKEYBYTES as CRYPTO_SIGN_SECRETKEYBYTES,
crypto_sign_PUBLICKEYBYTES as CRYPTO_SIGN_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES as CRYPTO_BOX_SECRETKEYBYTES,
crypto_box_PUBLICKEYBYTES as CRYPTO_BOX_PUBLICKEYBYTES,
crypto_box_NONCEBYTES as CRYPTO_BOX_NONCEBYTES,
crypto_box_MACBYTES as CRYPTO_BOX_MACBYTES,
};
use crate::util::randombytes_buf;
use crate::{error::NcryptfError as Error, VERSION_2_HEADER};
pub struct Request {
secret_key: Vec<u8>,
signature_secret_key: Vec<u8>,
nonce: Option<Vec<u8>>,
message: Option<Vec<u8>>
}
impl Request {
pub fn encrypt(&mut self, data: String, public_key: Vec<u8>) -> Result<Vec<u8>, Error> {
match self.encrypt_with_nonce(data, public_key, None, Some(2)) {
Ok(result) => {
self.message = Some(result.clone());
return Ok(result)
},
Err(error) => return Err(error)
};
}
pub fn get_message(&self) -> Option<Vec<u8>> {
return self.message.clone();
}
pub fn encrypt_with_nonce(&mut self, data: String, public_key: Vec<u8>, nonce: Option<Vec<u8>>, version: Option<i32>) -> Result<Vec<u8>, Error> {
let n = match nonce {
Some(n) => n,
None => randombytes_buf(CRYPTO_BOX_NONCEBYTES as usize)
};
self.nonce = Some(n.clone());
if public_key.len() != (CRYPTO_BOX_PUBLICKEYBYTES as usize) {
return Err(Error::InvalidArgument(format!("Public key should be {} bytes", CRYPTO_BOX_PUBLICKEYBYTES)));
}
if n.clone().len() != (CRYPTO_BOX_NONCEBYTES as usize) {
return Err(Error::InvalidArgument(format!("Nonce should be {} bytes", CRYPTO_BOX_NONCEBYTES)));
}
match version {
Some(2) => {
let h = VERSION_2_HEADER;
let header = hex::decode(h.to_string()).unwrap();
let mut body = match self.encrypt_body(data.clone(), public_key, n.clone()) {
Ok(body) => body,
Err(error) => {
return Err(error)
}
};
let mut ipk: [u8; (CRYPTO_BOX_PUBLICKEYBYTES as usize)] = vec![0; CRYPTO_BOX_PUBLICKEYBYTES as usize].try_into().unwrap();
let csk:[u8; (CRYPTO_BOX_SECRETKEYBYTES as usize)] = self.secret_key.clone().try_into().unwrap();
let _result = unsafe {crypto_scalarmult_base(
ipk.as_mut_ptr(),
csk.as_ptr()
) };
if _result != 0 {
return Err(Error::EncryptError);
}
let mut isk: [u8; (CRYPTO_SIGN_PUBLICKEYBYTES as usize)] = vec![0; CRYPTO_SIGN_PUBLICKEYBYTES as usize].try_into().unwrap();
let ssk: [u8; (CRYPTO_SIGN_SECRETKEYBYTES as usize)] = self.signature_secret_key.clone().try_into().unwrap();
let _result = unsafe { crypto_sign_ed25519_sk_to_pk(isk.as_mut_ptr(), ssk.as_ptr()) };
if _result != 0 {
return Err(Error::EncryptError);
}
let mut signature = match self.sign(data.clone()) {
Ok(signature) => signature,
Err(error) => return Err(error)
};
let mut payload: Vec<u8> = Vec::<u8>::new();
payload.append(&mut header.clone());
payload.append(&mut n.clone());
payload.append(&mut ipk.to_vec());
payload.append(&mut body);
payload.append(&mut isk.to_vec());
payload.append(&mut signature);
let s: &[u8; (CRYPTO_BOX_NONCEBYTES as usize)] = &n.clone().try_into().unwrap();
let input = payload.clone();
let mut hash: [u8; 64] = vec![0; 64].try_into().unwrap();
let _result = unsafe { crypto_generichash(
hash.as_mut_ptr(),
64,
input.as_ptr(),
input.len() as u64,
s.as_ptr(),
CRYPTO_BOX_NONCEBYTES as usize
) };
if _result != 0 {
return Err(Error::EncryptError);
}
payload.append(&mut hash.to_vec());
return Ok(payload);
},
_ => {
return self.encrypt_body(data.clone(), public_key, n.clone());
}
}
}
fn encrypt_body(&self, data: String, public_key: Vec<u8>, nonce: Vec<u8>) -> Result<Vec<u8>, Error> {
let message = data.into_bytes();
let len = message.len();
let mut ciphertext = Box::new(vec![0u8; len + (CRYPTO_BOX_MACBYTES as usize)]);
let sk:[u8; (CRYPTO_BOX_SECRETKEYBYTES as usize)] = self.secret_key.clone().try_into().unwrap();
let pk: [u8; (CRYPTO_BOX_PUBLICKEYBYTES as usize)] = public_key.clone().try_into().unwrap();
let n: [u8; (CRYPTO_BOX_NONCEBYTES as usize)] = nonce.clone().try_into().unwrap();
let result: i32= unsafe {
crypto_box_easy(
ciphertext.as_mut_ptr(),
message.as_ptr(),
message.len().try_into().unwrap(),
n.as_ptr(),
pk.as_ptr(),
sk.as_ptr()
)
};
match result {
0 => {
return Ok(ciphertext.to_vec());
},
_ => {
return Err(Error::DecryptError);
}
}
}
pub fn get_nonce(&self) -> Option<Vec<u8>> {
return self.nonce.clone();
}
pub fn sign(&self, data: String) -> Result<Vec<u8>, Error> {
let mut signature = [0u8; (CRYPTO_SIGN_BYTES as usize)];
let key: [u8; (CRYPTO_SIGN_SECRETKEYBYTES as usize)] = self.signature_secret_key.clone().try_into().unwrap();
let mut signature_size = signature.len() as u64;
let _result = unsafe {crypto_sign_detached(
signature.as_mut_ptr(),
&mut signature_size,
data.as_ptr(),
data.len() as u64,
key.as_ptr()
) };
if _result != 0 {
return Err(Error::EncryptError);
}
return Ok(signature.to_vec());
}
pub fn from(secret_key: Vec<u8>, signature_secret_key: Vec<u8>) -> Result<Self, Error> {
if secret_key.len() != (CRYPTO_BOX_SECRETKEYBYTES as usize) {
return Err(Error::InvalidArgument(format!("Secret key should be {} bytes", CRYPTO_BOX_SECRETKEYBYTES)));
}
if signature_secret_key.len() != (CRYPTO_SIGN_SECRETKEYBYTES as usize) {
return Err(Error::InvalidArgument(format!("Signature key should be {} bytes", CRYPTO_SIGN_SECRETKEYBYTES)));
}
return Ok(Request {
secret_key,
signature_secret_key,
nonce: None,
message: None
});
}
}