1#![allow(missing_docs)]
2
3use crate::{
4 error::ECIESErrorImpl,
5 mac::MAC,
6 util::{hmac_sha256, sha256},
7 ECIESError,
8};
9use aes::{cipher::StreamCipher, Aes128, Aes256};
10use alloy_primitives::{
11 bytes::{BufMut, Bytes, BytesMut},
12 B128, B256, B512 as PeerId,
13};
14use alloy_rlp::{Encodable, Rlp, RlpEncodable, RlpMaxEncodedLen};
15use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
16use ctr::Ctr64BE;
17use digest::{crypto_common::KeyIvInit, Digest};
18use rand_08::{thread_rng as rng, Rng};
19use reth_network_peers::{id2pk, pk2id};
20use secp256k1::{
21 ecdsa::{RecoverableSignature, RecoveryId},
22 PublicKey, SecretKey, SECP256K1,
23};
24use sha2::Sha256;
25use sha3::Keccak256;
26
27const PROTOCOL_VERSION: usize = 4;
28
29fn ecdh_x(public_key: &PublicKey, secret_key: &SecretKey) -> B256 {
36 B256::from_slice(&secp256k1::ecdh::shared_secret_point(public_key, secret_key)[..32])
37}
38
39fn kdf(secret: B256, s1: &[u8], dest: &mut [u8]) {
50 concat_kdf::derive_key_into::<Sha256>(secret.as_slice(), s1, dest).unwrap();
51}
52
53pub struct ECIES {
54 secret_key: SecretKey,
55 public_key: PublicKey,
56 remote_public_key: Option<PublicKey>,
57
58 pub(crate) remote_id: Option<PeerId>,
59
60 ephemeral_secret_key: SecretKey,
61 ephemeral_public_key: PublicKey,
62 ephemeral_shared_secret: Option<B256>,
63 remote_ephemeral_public_key: Option<PublicKey>,
64
65 nonce: B256,
66 remote_nonce: Option<B256>,
67
68 ingress_aes: Option<Ctr64BE<Aes256>>,
69 egress_aes: Option<Ctr64BE<Aes256>>,
70 ingress_mac: Option<MAC>,
71 egress_mac: Option<MAC>,
72
73 init_msg: Option<Bytes>,
74 remote_init_msg: Option<Bytes>,
75
76 body_size: Option<usize>,
77}
78
79impl core::fmt::Debug for ECIES {
80 #[inline]
81 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
82 f.debug_struct("ECIES")
83 .field("public_key", &self.public_key)
84 .field("remote_public_key", &self.remote_public_key)
85 .field("remote_id", &self.remote_id)
86 .field("ephemeral_public_key", &self.ephemeral_public_key)
87 .field("ephemeral_shared_secret", &self.ephemeral_shared_secret)
88 .field("remote_ephemeral_public_key", &self.remote_ephemeral_public_key)
89 .field("nonce", &self.nonce)
90 .field("remote_nonce", &self.remote_nonce)
91 .field("ingress_mac", &self.ingress_mac)
92 .field("egress_mac", &self.egress_mac)
93 .field("init_msg", &self.init_msg)
94 .field("remote_init_msg", &self.remote_init_msg)
95 .field("body_size", &self.body_size)
96 .finish()
97 }
98}
99
100fn split_at_mut<T>(arr: &mut [T], idx: usize) -> Result<(&mut [T], &mut [T]), ECIESError> {
101 if idx > arr.len() {
102 return Err(ECIESErrorImpl::OutOfBounds { idx, len: arr.len() }.into())
103 }
104 Ok(arr.split_at_mut(idx))
105}
106
107#[derive(Debug)]
117pub struct EncryptedMessage<'a> {
118 auth_data: [u8; 2],
124 public_key: PublicKey,
126 iv: B128,
128 encrypted_data: &'a mut [u8],
130 tag: B256,
132}
133
134impl<'a> EncryptedMessage<'a> {
135 pub fn parse(data: &mut [u8]) -> Result<EncryptedMessage<'_>, ECIESError> {
139 if data.len() < 65 + 2 {
141 return Err(ECIESErrorImpl::EncryptedDataTooSmall.into())
142 }
143 let (auth_data, encrypted) = data.split_at_mut(2);
144
145 let auth_data = auth_data.try_into().unwrap();
149
150 let (pubkey_bytes, encrypted) = encrypted.split_at_mut(65);
151 let public_key = PublicKey::from_slice(pubkey_bytes)?;
152
153 let tag_index =
155 encrypted.len().checked_sub(32).ok_or(ECIESErrorImpl::EncryptedDataTooSmall)?;
156
157 let (data_iv, tag_bytes) = encrypted.split_at_mut(tag_index);
160
161 let tag = B256::from_slice(tag_bytes);
164
165 if data_iv.len() < 16 {
167 return Err(ECIESErrorImpl::EncryptedDataTooSmall.into())
168 }
169 let (iv, encrypted_data) = data_iv.split_at_mut(16);
170
171 let iv = B128::from_slice(iv);
173
174 Ok(EncryptedMessage { auth_data, public_key, iv, encrypted_data, tag })
175 }
176
177 pub fn derive_keys(&self, secret_key: &SecretKey) -> RLPxSymmetricKeys {
180 let x = ecdh_x(&self.public_key, secret_key);
183 let mut key = [0u8; 32];
184
185 kdf(x, &[], &mut key);
194
195 let enc_key = B128::from_slice(&key[..16]);
196
197 let mac_key = sha256(&key[16..32]);
204
205 RLPxSymmetricKeys { enc_key, mac_key }
206 }
207
208 pub fn check_integrity(&self, keys: &RLPxSymmetricKeys) -> Result<(), ECIESError> {
210 let check_tag = hmac_sha256(
232 keys.mac_key.as_ref(),
233 &[self.iv.as_slice(), self.encrypted_data],
234 &self.auth_data,
235 );
236 if check_tag != self.tag {
237 return Err(ECIESErrorImpl::TagCheckDecryptFailed.into())
238 }
239
240 Ok(())
241 }
242
243 pub fn decrypt(self, keys: &RLPxSymmetricKeys) -> &'a mut [u8] {
246 let Self { iv, encrypted_data, .. } = self;
247
248 let decrypted_data = encrypted_data;
250
251 let mut decryptor = Ctr64BE::<Aes128>::new((&keys.enc_key.0).into(), (&*iv).into());
252 decryptor.apply_keystream(decrypted_data);
253 decrypted_data
254 }
255
256 pub fn check_and_decrypt(self, keys: RLPxSymmetricKeys) -> Result<&'a mut [u8], ECIESError> {
259 self.check_integrity(&keys)?;
260 Ok(self.decrypt(&keys))
261 }
262}
263
264#[derive(Debug)]
266pub struct RLPxSymmetricKeys {
267 pub enc_key: B128,
270
271 pub mac_key: B256,
274}
275
276impl ECIES {
277 fn new_static_client(
280 secret_key: SecretKey,
281 remote_id: PeerId,
282 nonce: B256,
283 ephemeral_secret_key: SecretKey,
284 ) -> Result<Self, ECIESError> {
285 let public_key = PublicKey::from_secret_key(SECP256K1, &secret_key);
286 let remote_public_key = id2pk(remote_id)?;
287 let ephemeral_public_key = PublicKey::from_secret_key(SECP256K1, &ephemeral_secret_key);
288
289 Ok(Self {
290 secret_key,
291 public_key,
292 ephemeral_secret_key,
293 ephemeral_public_key,
294 nonce,
295
296 remote_public_key: Some(remote_public_key),
297 remote_ephemeral_public_key: None,
298 remote_nonce: None,
299 ephemeral_shared_secret: None,
300 init_msg: None,
301 remote_init_msg: None,
302
303 remote_id: Some(remote_id),
304
305 body_size: None,
306 egress_aes: None,
307 ingress_aes: None,
308 egress_mac: None,
309 ingress_mac: None,
310 })
311 }
312
313 pub fn new_client(secret_key: SecretKey, remote_id: PeerId) -> Result<Self, ECIESError> {
315 let mut rng = rng();
317 let nonce = B256::random();
318 let ephemeral_secret_key = SecretKey::new(&mut rng);
319 Self::new_static_client(secret_key, remote_id, nonce, ephemeral_secret_key)
320 }
321
322 pub fn new_static_server(
325 secret_key: SecretKey,
326 nonce: B256,
327 ephemeral_secret_key: SecretKey,
328 ) -> Result<Self, ECIESError> {
329 let public_key = PublicKey::from_secret_key(SECP256K1, &secret_key);
330 let ephemeral_public_key = PublicKey::from_secret_key(SECP256K1, &ephemeral_secret_key);
331
332 Ok(Self {
333 secret_key,
334 public_key,
335 ephemeral_secret_key,
336 ephemeral_public_key,
337 nonce,
338
339 remote_public_key: None,
340 remote_ephemeral_public_key: None,
341 remote_nonce: None,
342 ephemeral_shared_secret: None,
343 init_msg: None,
344 remote_init_msg: None,
345
346 remote_id: None,
347
348 body_size: None,
349 egress_aes: None,
350 ingress_aes: None,
351 egress_mac: None,
352 ingress_mac: None,
353 })
354 }
355
356 pub fn new_server(secret_key: SecretKey) -> Result<Self, ECIESError> {
358 let mut rng = rng();
359 let nonce = B256::random();
360 let ephemeral_secret_key = SecretKey::new(&mut rng);
361 Self::new_static_server(secret_key, nonce, ephemeral_secret_key)
362 }
363
364 pub const fn remote_id(&self) -> PeerId {
366 self.remote_id.unwrap()
367 }
368
369 fn encrypt_message(&self, data: &[u8], out: &mut BytesMut) {
370 let mut rng = rng();
371
372 out.reserve(secp256k1::constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + 16 + data.len() + 32);
373
374 let secret_key = SecretKey::new(&mut rng);
375 out.extend_from_slice(
376 &PublicKey::from_secret_key(SECP256K1, &secret_key).serialize_uncompressed(),
377 );
378
379 let x = ecdh_x(&self.remote_public_key.unwrap(), &secret_key);
380 let mut key = [0u8; 32];
381 kdf(x, &[], &mut key);
382
383 let enc_key = B128::from_slice(&key[..16]);
384 let mac_key = sha256(&key[16..32]);
385
386 let iv = B128::random();
387 let mut encryptor = Ctr64BE::<Aes128>::new((&enc_key.0).into(), (&iv.0).into());
388
389 let mut encrypted = data.to_vec();
390 encryptor.apply_keystream(&mut encrypted);
391
392 let total_size: u16 = u16::try_from(65 + 16 + data.len() + 32).unwrap();
393
394 let tag =
395 hmac_sha256(mac_key.as_ref(), &[iv.as_slice(), &encrypted], &total_size.to_be_bytes());
396
397 out.extend_from_slice(iv.as_slice());
398 out.extend_from_slice(&encrypted);
399 out.extend_from_slice(tag.as_ref());
400 }
401
402 fn decrypt_message<'a>(&self, data: &'a mut [u8]) -> Result<&'a mut [u8], ECIESError> {
403 let encrypted_message = EncryptedMessage::parse(data)?;
405
406 let keys = encrypted_message.derive_keys(&self.secret_key);
408
409 encrypted_message.check_and_decrypt(keys)
411 }
412
413 fn create_auth_unencrypted(&self) -> BytesMut {
414 let x = ecdh_x(&self.remote_public_key.unwrap(), &self.secret_key);
415 let msg = x ^ self.nonce;
416 let (rec_id, sig) = SECP256K1
417 .sign_ecdsa_recoverable(
418 &secp256k1::Message::from_digest(msg.0),
419 &self.ephemeral_secret_key,
420 )
421 .serialize_compact();
422
423 let mut sig_bytes = [0u8; 65];
424 sig_bytes[..64].copy_from_slice(&sig);
425 sig_bytes[64] = i32::from(rec_id) as u8;
426
427 let id = pk2id(&self.public_key);
428
429 #[derive(RlpEncodable)]
430 struct S<'a> {
431 sig_bytes: &'a [u8; 65],
432 id: &'a PeerId,
433 nonce: &'a B256,
434 protocol_version: u8,
435 }
436
437 let mut out = BytesMut::new();
438 S {
439 sig_bytes: &sig_bytes,
440 id: &id,
441 nonce: &self.nonce,
442 protocol_version: PROTOCOL_VERSION as u8,
443 }
444 .encode(&mut out);
445
446 out.resize(out.len() + rng().gen_range(100..=300), 0);
447 out
448 }
449
450 #[cfg(test)]
451 fn create_auth(&mut self) -> BytesMut {
452 let mut buf = BytesMut::new();
453 self.write_auth(&mut buf);
454 buf
455 }
456
457 pub fn write_auth(&mut self, buf: &mut BytesMut) {
459 let unencrypted = self.create_auth_unencrypted();
460
461 let mut out = buf.split_off(buf.len());
462 out.put_u16(0);
463
464 let mut encrypted = out.split_off(out.len());
465 self.encrypt_message(&unencrypted, &mut encrypted);
466
467 let len_bytes = u16::try_from(encrypted.len()).unwrap().to_be_bytes();
468 out[..len_bytes.len()].copy_from_slice(&len_bytes);
469
470 out.unsplit(encrypted);
471
472 self.init_msg = Some(Bytes::copy_from_slice(&out));
473
474 buf.unsplit(out);
475 }
476
477 fn parse_auth_unencrypted(&mut self, data: &[u8]) -> Result<(), ECIESError> {
478 let mut data = Rlp::new(data)?;
479
480 let sigdata = data.get_next::<[u8; 65]>()?.ok_or(ECIESErrorImpl::InvalidAuthData)?;
481 let signature = RecoverableSignature::from_compact(
482 &sigdata[..64],
483 RecoveryId::try_from(sigdata[64] as i32)?,
484 )?;
485 let remote_id = data.get_next()?.ok_or(ECIESErrorImpl::InvalidAuthData)?;
486 self.remote_id = Some(remote_id);
487 self.remote_public_key = Some(id2pk(remote_id)?);
488 self.remote_nonce = Some(data.get_next()?.ok_or(ECIESErrorImpl::InvalidAuthData)?);
489
490 let x = ecdh_x(&self.remote_public_key.unwrap(), &self.secret_key);
491 self.remote_ephemeral_public_key = Some(SECP256K1.recover_ecdsa(
492 &secp256k1::Message::from_digest((x ^ self.remote_nonce.unwrap()).0),
493 &signature,
494 )?);
495 self.ephemeral_shared_secret =
496 Some(ecdh_x(&self.remote_ephemeral_public_key.unwrap(), &self.ephemeral_secret_key));
497
498 Ok(())
499 }
500
501 #[tracing::instrument(level = "trace", skip_all)]
503 pub fn read_auth(&mut self, data: &mut [u8]) -> Result<(), ECIESError> {
504 self.remote_init_msg = Some(Bytes::copy_from_slice(data));
505 let unencrypted = self.decrypt_message(data)?;
506 self.parse_auth_unencrypted(unencrypted)
507 }
508
509 fn create_ack_unencrypted(&self) -> impl AsRef<[u8]> {
512 #[derive(RlpEncodable, RlpMaxEncodedLen)]
513 struct S {
514 id: PeerId,
515 nonce: B256,
516 protocol_version: u8,
517 }
518
519 alloy_rlp::encode_fixed_size(&S {
520 id: pk2id(&self.ephemeral_public_key),
521 nonce: self.nonce,
522 protocol_version: PROTOCOL_VERSION as u8,
523 })
524 }
525
526 #[cfg(test)]
527 pub fn create_ack(&mut self) -> BytesMut {
528 let mut buf = BytesMut::new();
529 self.write_ack(&mut buf);
530 buf
531 }
532
533 pub fn write_ack(&mut self, out: &mut BytesMut) {
535 let mut buf = out.split_off(out.len());
536
537 buf.put_u16(0);
539
540 let mut encrypted = buf.split_off(buf.len());
542 self.encrypt_message(self.create_ack_unencrypted().as_ref(), &mut encrypted);
543 let len_bytes = u16::try_from(encrypted.len()).unwrap().to_be_bytes();
544 buf.unsplit(encrypted);
545
546 buf[..len_bytes.len()].copy_from_slice(&len_bytes[..]);
548
549 self.init_msg = Some(buf.clone().freeze());
550 out.unsplit(buf);
551
552 self.setup_frame(true);
553 }
554
555 fn parse_ack_unencrypted(&mut self, data: &[u8]) -> Result<(), ECIESError> {
563 let mut data = Rlp::new(data)?;
564 self.remote_ephemeral_public_key =
565 Some(id2pk(data.get_next()?.ok_or(ECIESErrorImpl::InvalidAckData)?)?);
566 self.remote_nonce = Some(data.get_next()?.ok_or(ECIESErrorImpl::InvalidAckData)?);
567
568 self.ephemeral_shared_secret =
569 Some(ecdh_x(&self.remote_ephemeral_public_key.unwrap(), &self.ephemeral_secret_key));
570 Ok(())
571 }
572
573 #[tracing::instrument(level = "trace", skip_all)]
575 pub fn read_ack(&mut self, data: &mut [u8]) -> Result<(), ECIESError> {
576 self.remote_init_msg = Some(Bytes::copy_from_slice(data));
577 let unencrypted = self.decrypt_message(data)?;
578 self.parse_ack_unencrypted(unencrypted)?;
579 self.setup_frame(false);
580 Ok(())
581 }
582
583 fn setup_frame(&mut self, incoming: bool) {
584 let mut hasher = Keccak256::new();
585 for el in &if incoming {
586 [self.nonce, self.remote_nonce.unwrap()]
587 } else {
588 [self.remote_nonce.unwrap(), self.nonce]
589 } {
590 hasher.update(el);
591 }
592 let h_nonce = B256::from(hasher.finalize().as_ref());
593
594 let iv = B128::default();
595 let shared_secret: B256 = {
596 let mut hasher = Keccak256::new();
597 hasher.update(self.ephemeral_shared_secret.unwrap().0.as_ref());
598 hasher.update(h_nonce.0.as_ref());
599 B256::from(hasher.finalize().as_ref())
600 };
601
602 let aes_secret: B256 = {
603 let mut hasher = Keccak256::new();
604 hasher.update(self.ephemeral_shared_secret.unwrap().0.as_ref());
605 hasher.update(shared_secret.0.as_ref());
606 B256::from(hasher.finalize().as_ref())
607 };
608 self.ingress_aes = Some(Ctr64BE::<Aes256>::new((&aes_secret.0).into(), (&iv.0).into()));
609 self.egress_aes = Some(Ctr64BE::<Aes256>::new((&aes_secret.0).into(), (&iv.0).into()));
610
611 let mac_secret: B256 = {
612 let mut hasher = Keccak256::new();
613 hasher.update(self.ephemeral_shared_secret.unwrap().0.as_ref());
614 hasher.update(aes_secret.0.as_ref());
615 B256::from(hasher.finalize().as_ref())
616 };
617 self.ingress_mac = Some(MAC::new(mac_secret));
618 self.ingress_mac.as_mut().unwrap().update((mac_secret ^ self.nonce).as_ref());
619 self.ingress_mac.as_mut().unwrap().update(self.remote_init_msg.as_ref().unwrap());
620 self.egress_mac = Some(MAC::new(mac_secret));
621 self.egress_mac
622 .as_mut()
623 .unwrap()
624 .update((mac_secret ^ self.remote_nonce.unwrap()).as_ref());
625 self.egress_mac.as_mut().unwrap().update(self.init_msg.as_ref().unwrap());
626 }
627
628 #[cfg(test)]
629 fn create_header(&mut self, size: usize) -> BytesMut {
630 let mut out = BytesMut::new();
631 self.write_header(&mut out, size);
632 out
633 }
634
635 pub fn write_header(&mut self, out: &mut BytesMut, size: usize) {
636 let mut buf = [0u8; 8];
637 BigEndian::write_uint(&mut buf, size as u64, 3);
638 let mut header = [0u8; 16];
639 header[..3].copy_from_slice(&buf[..3]);
640 header[3..6].copy_from_slice(&[194, 128, 128]);
641
642 self.egress_aes.as_mut().unwrap().apply_keystream(&mut header);
643 self.egress_mac.as_mut().unwrap().update_header(&header);
644 let tag = self.egress_mac.as_mut().unwrap().digest();
645
646 out.reserve(Self::header_len());
647 out.extend_from_slice(&header[..]);
648 out.extend_from_slice(tag.as_slice());
649 }
650
651 pub fn read_header(&mut self, data: &mut [u8]) -> Result<usize, ECIESError> {
654 if data.len() < 32 {
658 return Err(ECIESErrorImpl::InvalidHeader.into())
659 }
660
661 let (header_bytes, mac_bytes) = split_at_mut(data, 16)?;
662 let header: &mut [u8; 16] = header_bytes.try_into().unwrap();
663 let mac = B128::from_slice(&mac_bytes[..16]);
664
665 self.ingress_mac.as_mut().unwrap().update_header(header);
666 let check_mac = self.ingress_mac.as_mut().unwrap().digest();
667 if check_mac != mac {
668 return Err(ECIESErrorImpl::TagCheckHeaderFailed.into())
669 }
670
671 self.ingress_aes.as_mut().unwrap().apply_keystream(header);
672 if header.len() < 3 {
673 return Err(ECIESErrorImpl::InvalidHeader.into())
674 }
675
676 let body_size = usize::try_from((&header[..]).read_uint::<BigEndian>(3)?)?;
677
678 self.body_size = Some(body_size);
679
680 Ok(body_size)
681 }
682
683 pub const fn header_len() -> usize {
684 32
685 }
686
687 pub const fn body_len(&self) -> usize {
688 let len = self.body_size.unwrap();
689 Self::align_16(len) + 16
690 }
691
692 #[cfg(test)]
693 fn create_body(&mut self, data: &[u8]) -> BytesMut {
694 let mut out = BytesMut::new();
695 self.write_body(&mut out, data);
696 out
697 }
698
699 pub fn write_body(&mut self, out: &mut BytesMut, data: &[u8]) {
700 let len = Self::align_16(data.len());
701 let old_len = out.len();
702 out.resize(old_len + len, 0);
703
704 let encrypted = &mut out[old_len..old_len + len];
705 encrypted[..data.len()].copy_from_slice(data);
706
707 self.egress_aes.as_mut().unwrap().apply_keystream(encrypted);
708 self.egress_mac.as_mut().unwrap().update_body(encrypted);
709 let tag = self.egress_mac.as_mut().unwrap().digest();
710
711 out.extend_from_slice(tag.as_slice());
712 }
713
714 pub fn read_body<'a>(&mut self, data: &'a mut [u8]) -> Result<&'a mut [u8], ECIESError> {
715 let mac_index = data.len().checked_sub(16).ok_or(ECIESErrorImpl::EncryptedDataTooSmall)?;
719 let (body, mac_bytes) = split_at_mut(data, mac_index)?;
720 let mac = B128::from_slice(mac_bytes);
721 self.ingress_mac.as_mut().unwrap().update_body(body);
722 let check_mac = self.ingress_mac.as_mut().unwrap().digest();
723 if check_mac != mac {
724 return Err(ECIESErrorImpl::TagCheckBodyFailed.into())
725 }
726
727 let size = self.body_size.unwrap();
728 self.body_size = None;
729 let ret = body;
730 self.ingress_aes.as_mut().unwrap().apply_keystream(ret);
731 Ok(split_at_mut(ret, size)?.0)
732 }
733
734 #[inline]
738 const fn align_16(num: usize) -> usize {
739 (num + (16 - 1)) & !(16 - 1)
740 }
741}
742
743#[cfg(test)]
744mod tests {
745 use super::*;
746 use alloy_primitives::{b256, hex};
747
748 #[test]
749 fn ecdh() {
750 let our_secret_key = SecretKey::from_slice(&hex!(
751 "202a36e24c3eb39513335ec99a7619bad0e7dc68d69401b016253c7d26dc92f8"
752 ))
753 .unwrap();
754 let remote_public_key = id2pk(hex!("d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666").into()).unwrap();
755
756 assert_eq!(
757 ecdh_x(&remote_public_key, &our_secret_key),
758 hex!("821ce7e01ea11b111a52b2dafae8a3031a372d83bdf1a78109fa0783c2b9d5d3")
759 )
760 }
761
762 #[test]
763 fn communicate() {
764 let mut rng = rng();
765 let server_secret_key = SecretKey::new(&mut rng);
766 let server_public_key = PublicKey::from_secret_key(SECP256K1, &server_secret_key);
767 let client_secret_key = SecretKey::new(&mut rng);
768
769 let mut server_ecies = ECIES::new_server(server_secret_key).unwrap();
770 let mut client_ecies =
771 ECIES::new_client(client_secret_key, pk2id(&server_public_key)).unwrap();
772
773 let mut auth = client_ecies.create_auth();
775 server_ecies.read_auth(&mut auth).unwrap();
776 let mut ack = server_ecies.create_ack();
777 client_ecies.read_ack(&mut ack).unwrap();
778 let mut ack = client_ecies.create_ack();
779 server_ecies.read_ack(&mut ack).unwrap();
780
781 let server_to_client_data = [0u8, 1u8, 2u8, 3u8, 4u8];
782 let client_to_server_data = [5u8, 6u8, 7u8];
783
784 let mut header = server_ecies.create_header(server_to_client_data.len());
786 assert_eq!(header.len(), ECIES::header_len());
787 client_ecies.read_header(&mut header).unwrap();
788 let mut body = server_ecies.create_body(&server_to_client_data);
789 assert_eq!(body.len(), client_ecies.body_len());
790 let ret = client_ecies.read_body(&mut body).unwrap();
791 assert_eq!(ret, server_to_client_data);
792
793 server_ecies
795 .read_header(&mut client_ecies.create_header(client_to_server_data.len()))
796 .unwrap();
797 let mut b = client_ecies.create_body(&client_to_server_data);
798 let ret = server_ecies.read_body(&mut b).unwrap();
799 assert_eq!(ret, client_to_server_data);
800
801 client_ecies
803 .read_header(&mut server_ecies.create_header(server_to_client_data.len()))
804 .unwrap();
805 let mut b = server_ecies.create_body(&server_to_client_data);
806 let ret = client_ecies.read_body(&mut b).unwrap();
807 assert_eq!(ret, server_to_client_data);
808
809 client_ecies
811 .read_header(&mut server_ecies.create_header(server_to_client_data.len()))
812 .unwrap();
813 let mut b = server_ecies.create_body(&server_to_client_data);
814 let ret = client_ecies.read_body(&mut b).unwrap();
815 assert_eq!(ret, server_to_client_data);
816
817 server_ecies
819 .read_header(&mut client_ecies.create_header(client_to_server_data.len()))
820 .unwrap();
821 let mut b = client_ecies.create_body(&client_to_server_data);
822 let ret = server_ecies.read_body(&mut b).unwrap();
823 assert_eq!(ret, client_to_server_data);
824
825 server_ecies
827 .read_header(&mut client_ecies.create_header(client_to_server_data.len()))
828 .unwrap();
829 let mut b = client_ecies.create_body(&client_to_server_data);
830 let ret = server_ecies.read_body(&mut b).unwrap();
831 assert_eq!(ret, client_to_server_data);
832 }
833
834 fn eip8_test_server_key() -> SecretKey {
835 SecretKey::from_slice(&hex!(
836 "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
837 ))
838 .unwrap()
839 }
840
841 fn eip8_test_client() -> ECIES {
842 let client_static_key = SecretKey::from_slice(&hex!(
843 "49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee"
844 ))
845 .unwrap();
846
847 let client_ephemeral_key = SecretKey::from_slice(&hex!(
848 "869d6ecf5211f1cc60418a13b9d870b22959d0c16f02bec714c960dd2298a32d"
849 ))
850 .unwrap();
851
852 let client_nonce =
853 b256!("0x7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6");
854
855 let server_id = pk2id(&PublicKey::from_secret_key(SECP256K1, &eip8_test_server_key()));
856
857 ECIES::new_static_client(client_static_key, server_id, client_nonce, client_ephemeral_key)
858 .unwrap()
859 }
860
861 fn eip8_test_server() -> ECIES {
862 let server_ephemeral_key = SecretKey::from_slice(&hex!(
863 "e238eb8e04fee6511ab04c6dd3c89ce097b11f25d584863ac2b6d5b35b1847e4"
864 ))
865 .unwrap();
866
867 let server_nonce =
868 b256!("0x559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd");
869
870 ECIES::new_static_server(eip8_test_server_key(), server_nonce, server_ephemeral_key)
871 .unwrap()
872 }
873
874 #[test]
875 fn eip8_test() {
877 let auth2 = hex!(
879 "
880 01b304ab7578555167be8154d5cc456f567d5ba302662433674222360f08d5f1534499d3678b513b
881 0fca474f3a514b18e75683032eb63fccb16c156dc6eb2c0b1593f0d84ac74f6e475f1b8d56116b84
882 9634a8c458705bf83a626ea0384d4d7341aae591fae42ce6bd5c850bfe0b999a694a49bbbaf3ef6c
883 da61110601d3b4c02ab6c30437257a6e0117792631a4b47c1d52fc0f8f89caadeb7d02770bf999cc
884 147d2df3b62e1ffb2c9d8c125a3984865356266bca11ce7d3a688663a51d82defaa8aad69da39ab6
885 d5470e81ec5f2a7a47fb865ff7cca21516f9299a07b1bc63ba56c7a1a892112841ca44b6e0034dee
886 70c9adabc15d76a54f443593fafdc3b27af8059703f88928e199cb122362a4b35f62386da7caad09
887 c001edaeb5f8a06d2b26fb6cb93c52a9fca51853b68193916982358fe1e5369e249875bb8d0d0ec3
888 6f917bc5e1eafd5896d46bd61ff23f1a863a8a8dcd54c7b109b771c8e61ec9c8908c733c0263440e
889 2aa067241aaa433f0bb053c7b31a838504b148f570c0ad62837129e547678c5190341e4f1693956c
890 3bf7678318e2d5b5340c9e488eefea198576344afbdf66db5f51204a6961a63ce072c8926c
891 "
892 );
893
894 let auth3 = hex!(
896 "
897 01b8044c6c312173685d1edd268aa95e1d495474c6959bcdd10067ba4c9013df9e40ff45f5bfd6f7
898 2471f93a91b493f8e00abc4b80f682973de715d77ba3a005a242eb859f9a211d93a347fa64b597bf
899 280a6b88e26299cf263b01b8dfdb712278464fd1c25840b995e84d367d743f66c0e54a586725b7bb
900 f12acca27170ae3283c1073adda4b6d79f27656993aefccf16e0d0409fe07db2dc398a1b7e8ee93b
901 cd181485fd332f381d6a050fba4c7641a5112ac1b0b61168d20f01b479e19adf7fdbfa0905f63352
902 bfc7e23cf3357657455119d879c78d3cf8c8c06375f3f7d4861aa02a122467e069acaf513025ff19
903 6641f6d2810ce493f51bee9c966b15c5043505350392b57645385a18c78f14669cc4d960446c1757
904 1b7c5d725021babbcd786957f3d17089c084907bda22c2b2675b4378b114c601d858802a55345a15
905 116bc61da4193996187ed70d16730e9ae6b3bb8787ebcaea1871d850997ddc08b4f4ea668fbf3740
906 7ac044b55be0908ecb94d4ed172ece66fd31bfdadf2b97a8bc690163ee11f5b575a4b44e36e2bfb2
907 f0fce91676fd64c7773bac6a003f481fddd0bae0a1f31aa27504e2a533af4cef3b623f4791b2cca6
908 d490
909 "
910 );
911
912 let ack2 = hex!(
914 "
915 01ea0451958701280a56482929d3b0757da8f7fbe5286784beead59d95089c217c9b917788989470
916 b0e330cc6e4fb383c0340ed85fab836ec9fb8a49672712aeabbdfd1e837c1ff4cace34311cd7f4de
917 05d59279e3524ab26ef753a0095637ac88f2b499b9914b5f64e143eae548a1066e14cd2f4bd7f814
918 c4652f11b254f8a2d0191e2f5546fae6055694aed14d906df79ad3b407d94692694e259191cde171
919 ad542fc588fa2b7333313d82a9f887332f1dfc36cea03f831cb9a23fea05b33deb999e85489e645f
920 6aab1872475d488d7bd6c7c120caf28dbfc5d6833888155ed69d34dbdc39c1f299be1057810f34fb
921 e754d021bfca14dc989753d61c413d261934e1a9c67ee060a25eefb54e81a4d14baff922180c395d
922 3f998d70f46f6b58306f969627ae364497e73fc27f6d17ae45a413d322cb8814276be6ddd13b885b
923 201b943213656cde498fa0e9ddc8e0b8f8a53824fbd82254f3e2c17e8eaea009c38b4aa0a3f306e8
924 797db43c25d68e86f262e564086f59a2fc60511c42abfb3057c247a8a8fe4fb3ccbadde17514b7ac
925 8000cdb6a912778426260c47f38919a91f25f4b5ffb455d6aaaf150f7e5529c100ce62d6d92826a7
926 1778d809bdf60232ae21ce8a437eca8223f45ac37f6487452ce626f549b3b5fdee26afd2072e4bc7
927 5833c2464c805246155289f4
928 "
929 );
930
931 let ack3 = hex!(
933 "
934 01f004076e58aae772bb101ab1a8e64e01ee96e64857ce82b1113817c6cdd52c09d26f7b90981cd7
935 ae835aeac72e1573b8a0225dd56d157a010846d888dac7464baf53f2ad4e3d584531fa203658fab0
936 3a06c9fd5e35737e417bc28c1cbf5e5dfc666de7090f69c3b29754725f84f75382891c561040ea1d
937 dc0d8f381ed1b9d0d4ad2a0ec021421d847820d6fa0ba66eaf58175f1b235e851c7e2124069fbc20
938 2888ddb3ac4d56bcbd1b9b7eab59e78f2e2d400905050f4a92dec1c4bdf797b3fc9b2f8e84a482f3
939 d800386186712dae00d5c386ec9387a5e9c9a1aca5a573ca91082c7d68421f388e79127a5177d4f8
940 590237364fd348c9611fa39f78dcdceee3f390f07991b7b47e1daa3ebcb6ccc9607811cb17ce51f1
941 c8c2c5098dbdd28fca547b3f58c01a424ac05f869f49c6a34672ea2cbbc558428aa1fe48bbfd6115
942 8b1b735a65d99f21e70dbc020bfdface9f724a0d1fb5895db971cc81aa7608baa0920abb0a565c9c
943 436e2fd13323428296c86385f2384e408a31e104670df0791d93e743a3a5194ee6b076fb6323ca59
944 3011b7348c16cf58f66b9633906ba54a2ee803187344b394f75dd2e663a57b956cb830dd7a908d4f
945 39a2336a61ef9fda549180d4ccde21514d117b6c6fd07a9102b5efe710a32af4eeacae2cb3b1dec0
946 35b9593b48b9d3ca4c13d245d5f04169b0b1
947 "
948 );
949
950 eip8_test_server().read_auth(&mut auth2.to_vec()).unwrap();
951 eip8_test_server().read_auth(&mut auth3.to_vec()).unwrap();
952
953 let mut test_client = eip8_test_client();
954 let mut test_server = eip8_test_server();
955
956 test_server.read_auth(&mut test_client.create_auth()).unwrap();
957
958 test_client.read_ack(&mut test_server.create_ack()).unwrap();
959
960 test_client.read_ack(&mut ack2.to_vec()).unwrap();
961 test_client.read_ack(&mut ack3.to_vec()).unwrap();
962 }
963
964 #[test]
965 fn kdf_out_of_bounds() {
966 let len_range = 1..65;
968 for len in len_range {
969 let mut dest = vec![1u8; len];
970 kdf(
971 b256!("0x7000000000000000000000000000000000000000000000000000000000000007"),
972 &[0x01, 0x33, 0x70, 0xbe, 0xef],
973 &mut dest,
974 );
975 }
976 }
977}