cfxkey/
crypto.rs

1// Copyright 2015-2019 Parity Technologies (UK) Ltd.
2// This file is part of Parity Ethereum.
3//
4// Parity Ethereum is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Parity Ethereum is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Parity Ethereum.  If not, see <http://www.gnu.org/licenses/>.
16
17// Copyright 2020 Parity Technologies
18//
19// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
20// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
21// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
22// option. This file may not be copied, modified, or distributed
23// except according to those terms.
24
25// Re-export everything from cfx_crypto for compatibility
26pub use cfx_crypto::crypto::*;
27
28// Re-export constants
29pub use cfx_crypto::crypto::{KEY_ITERATIONS, KEY_LENGTH, KEY_LENGTH_AES};
30
31pub mod ecies {
32    use super::Error;
33    use crate::{Public, Random, Secret};
34
35    /// Encrypt a message with a public key, writing an HMAC covering both
36    /// the plaintext and authenticated data.
37    ///
38    /// Authenticated data may be empty.
39    pub fn encrypt(
40        public: &Public, auth_data: &[u8], plain: &[u8],
41    ) -> Result<Vec<u8>, Error> {
42        let mut generator = Random;
43        cfx_crypto::crypto::ecies::encrypt(
44            &mut generator,
45            public,
46            auth_data,
47            plain,
48        )
49    }
50
51    /// Decrypt a message with a secret key, checking HMAC for ciphertext
52    /// and authenticated data validity.
53    pub fn decrypt(
54        secret: &Secret, auth_data: &[u8], encrypted: &[u8],
55    ) -> Result<Vec<u8>, Error> {
56        cfx_crypto::crypto::ecies::decrypt(secret, auth_data, encrypted)
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::{ecdh, ecies};
63    use crate::{
64        crypto::scrypt::derive_key, KeyPairGenerator, Public, Random, Secret,
65    };
66    use std::{io::Error, str::FromStr};
67
68    #[test]
69    fn ecies_shared() {
70        let kp = Random.generate().unwrap();
71        let message = b"So many books, so little time";
72
73        let shared = b"shared";
74        let wrong_shared = b"incorrect";
75        let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap();
76        assert_ne!(encrypted[..], message[..]);
77        assert_eq!(encrypted[0], 0x04);
78
79        assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err());
80        let decrypted =
81            ecies::decrypt(kp.secret(), shared, &encrypted).unwrap();
82        assert_eq!(decrypted[..message.len()], message[..]);
83    }
84
85    #[test]
86    fn ecdh_agree() {
87        /*
88        kp1: KeyPair { secret: 0x3d6c3a910832105febef6f8111b51b11e6cb190fb45b5fc70ee6290c411e9a09, public: 0x057c7d5b963cb4605c3e0c4d5cbefd2a31fb3877e481172d6225a77e0a5964a0112f123aaee2d42f6bec55b396564ffcbd188c799f905253c9394642447063b0 }
89        kp2: KeyPair { secret: 0x6da0008f5531966a9637266fd180ca66e2643920a2d60d4c34350e25f0ccda98, public: 0x4cf74522f3c86d88cd2ba56b378d3fccd4ba3fe93fe4e11ebecc24b06085fc37ee63073aa998693cf2573dc9a437ac0a94d9093054419d23390bad2329ee5eee }
90         */
91        let secret = Secret::from_str(
92            "3d6c3a910832105febef6f8111b51b11e6cb190fb45b5fc70ee6290c411e9a09",
93        )
94        .unwrap();
95        let publ = Public::from_str("4cf74522f3c86d88cd2ba56b378d3fccd4ba3fe93fe4e11ebecc24b06085fc37ee63073aa998693cf2573dc9a437ac0a94d9093054419d23390bad2329ee5eee").unwrap();
96
97        let agree_secret = ecdh::agree(&secret, &publ).unwrap();
98
99        let expected = Secret::from_str(
100            "c6440592fa14256dbbc39639b77524e51bac84b64fa1b1726130a49263f1fb6f",
101        )
102        .unwrap();
103        assert_eq!(agree_secret, expected);
104    }
105    // test is build from previous crypto lib behaviour, values may be incorrect
106    // if previous crypto lib got a bug.
107    #[test]
108    pub fn test_derive() -> Result<(), Error> {
109        let pass = [109, 121, 112, 97, 115, 115, 10];
110        let salt = [
111            109, 121, 115, 97, 108, 116, 115, 104, 111, 117, 108, 100, 102,
112            105, 108, 108, 115, 111, 109, 109, 101, 98, 121, 116, 101, 108,
113            101, 110, 103, 116, 104, 10,
114        ];
115        let r1 = [
116            93, 134, 79, 68, 223, 27, 44, 174, 236, 184, 179, 203, 74, 139, 73,
117            66,
118        ];
119        let r2 = [
120            2, 24, 239, 131, 172, 164, 18, 171, 132, 207, 22, 217, 150, 20,
121            203, 37,
122        ];
123        let l1 = [
124            6, 90, 119, 45, 67, 2, 99, 151, 81, 88, 166, 210, 244, 19, 123, 208,
125        ];
126        let l2 = [
127            253, 123, 132, 12, 188, 89, 196, 2, 107, 224, 239, 231, 135, 177,
128            125, 62,
129        ];
130
131        let (l, r) = derive_key(&pass[..], &salt, 262, 1, 8).unwrap();
132        assert_eq!(l, r1);
133        assert_eq!(r, l1);
134        let (l, r) = derive_key(&pass[..], &salt, 144, 4, 4).unwrap();
135        assert_eq!(l, r2);
136        assert_eq!(r, l2);
137        Ok(())
138    }
139}