This repository has been archived by the owner on Jan 14, 2020. It is now read-only.
forked from mimblewimble/grin-wallet
-
Notifications
You must be signed in to change notification settings - Fork 1
/
message.rs
146 lines (127 loc) · 4.69 KB
/
message.rs
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
// Copyright 2018 The Vault713 Developers
// Modifications Copyright 2019 The Gotts Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Grin Relay Messages
use crate::grin_util::secp::key::{PublicKey, SecretKey};
use rand::thread_rng;
use rand::Rng;
use ring::aead;
use ring::{digest, pbkdf2};
use secp256k1zkp::Secp256k1;
use crate::crypto::{from_hex, to_hex};
use crate::error::ErrorKind;
use crate::grinrelay_address::GrinboxAddress;
use crate::Result;
#[derive(Debug, Serialize, Deserialize)]
pub struct EncryptedMessage {
pub destination: GrinboxAddress,
pub encrypted_message: String,
salt: String,
nonce: String,
}
impl EncryptedMessage {
pub fn new(
message: String,
destination: &GrinboxAddress,
receiver_public_key: &PublicKey,
secret_key: &SecretKey,
) -> Result<EncryptedMessage> {
let secp = Secp256k1::new();
let mut common_secret = receiver_public_key.clone();
common_secret
.mul_assign(&secp, secret_key)
.map_err(|_| ErrorKind::Encryption)?;
let common_secret_ser = common_secret.serialize_vec(&secp, true);
let common_secret_slice = &common_secret_ser[1..33];
let salt: [u8; 8] = thread_rng().gen();
let nonce: [u8; 12] = thread_rng().gen();
let mut key = [0; 32];
pbkdf2::derive(&digest::SHA512, 10000, &salt, common_secret_slice, &mut key);
let mut enc_bytes = message.as_bytes().to_vec();
let suffix_len = aead::CHACHA20_POLY1305.tag_len();
for _ in 0..suffix_len {
enc_bytes.push(0);
}
let sealing_key = aead::SealingKey::new(&aead::CHACHA20_POLY1305, &key)
.map_err(|_| ErrorKind::Encryption)?;
aead::seal_in_place(&sealing_key, &nonce, &[], &mut enc_bytes, suffix_len)
.map_err(|_| ErrorKind::Encryption)?;
Ok(EncryptedMessage {
destination: destination.clone(),
encrypted_message: to_hex(enc_bytes),
salt: to_hex(salt.to_vec()),
nonce: to_hex(nonce.to_vec()),
})
}
pub fn key(&self, sender_public_key: &PublicKey, secret_key: &SecretKey) -> Result<[u8; 32]> {
let salt = from_hex(self.salt.clone()).map_err(|_| ErrorKind::Decryption)?;
let secp = Secp256k1::new();
let mut common_secret = sender_public_key.clone();
common_secret
.mul_assign(&secp, secret_key)
.map_err(|_| ErrorKind::Decryption)?;
let common_secret_ser = common_secret.serialize_vec(&secp, true);
let common_secret_slice = &common_secret_ser[1..33];
let mut key = [0; 32];
pbkdf2::derive(&digest::SHA512, 10000, &salt, common_secret_slice, &mut key);
Ok(key)
}
pub fn decrypt_with_key(&self, key: &[u8; 32]) -> Result<String> {
let mut encrypted_message =
from_hex(self.encrypted_message.clone()).map_err(|_| ErrorKind::Decryption)?;
let nonce = from_hex(self.nonce.clone()).map_err(|_| ErrorKind::Decryption)?;
let opening_key = aead::OpeningKey::new(&aead::CHACHA20_POLY1305, key)
.map_err(|_| ErrorKind::Decryption)?;
let decrypted_data =
aead::open_in_place(&opening_key, &nonce, &[], 0, &mut encrypted_message)
.map_err(|_| ErrorKind::Decryption)?;
String::from_utf8(decrypted_data.to_vec()).map_err(|_| ErrorKind::Decryption.into())
}
pub fn get_decrypted_message(&self, key: &[u8; 32]) -> Result<DecryptedMessage> {
Ok(DecryptedMessage {
destination: self.destination.clone(),
message: self.decrypt_with_key(key)?,
salt: self.salt.clone(),
nonce: self.nonce.clone(),
})
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DecryptedMessage {
pub destination: GrinboxAddress,
pub message: String,
pub salt: String,
pub nonce: String,
}
impl DecryptedMessage {
pub fn encrypt_with_key(&self, key: &[u8; 32]) -> Result<EncryptedMessage> {
let mut enc_bytes = self.message.as_bytes().to_vec();
let suffix_len = aead::CHACHA20_POLY1305.tag_len();
for _ in 0..suffix_len {
enc_bytes.push(0);
}
let sealing_key = aead::SealingKey::new(&aead::CHACHA20_POLY1305, key)
.map_err(|_| ErrorKind::Encryption)?;
let nonce = from_hex(self.nonce.clone()).map_err(|_| ErrorKind::Encryption)?;
aead::seal_in_place(&sealing_key, &nonce, &[], &mut enc_bytes, suffix_len)
.map_err(|_| ErrorKind::Encryption)?;
let encrypted_message = to_hex(enc_bytes);
Ok(EncryptedMessage {
destination: self.destination.clone(),
encrypted_message,
salt: self.salt.clone(),
nonce: self.nonce.clone(),
})
}
}