crypto.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. use crypto_box::{
  2. aead::{Aead, AeadCore},
  3. SalsaBox,
  4. };
  5. use fxhash::FxHashMap;
  6. use rand::rngs::OsRng;
  7. use crate::{
  8. settings::{ChannelInfo, ContactInfo},
  9. Privmsg,
  10. };
  11. /// The format we're using is nonce+ciphertext, where nonce is 24 bytes.
  12. fn try_decrypt(salt_box: &SalsaBox, ciphertext: &str) -> Option<String> {
  13. let bytes = match bs58::decode(ciphertext).into_vec() {
  14. Ok(v) => v,
  15. Err(_) => return None,
  16. };
  17. if bytes.len() < 25 {
  18. return None
  19. }
  20. // Try extracting the nonce
  21. let nonce = match bytes[0..24].try_into() {
  22. Ok(v) => v,
  23. Err(_) => return None,
  24. };
  25. // Take the remaining ciphertext
  26. let message = &bytes[24..];
  27. // Try decrypting the message
  28. match salt_box.decrypt(nonce, message) {
  29. Ok(v) => Some(String::from_utf8_lossy(&v).to_string()),
  30. Err(_) => None,
  31. }
  32. }
  33. /// The format we're using is nonce+ciphertext, where nonce is 24 bytes.
  34. pub fn encrypt(salt_box: &SalsaBox, plaintext: &str) -> String {
  35. let nonce = SalsaBox::generate_nonce(&mut OsRng);
  36. let mut ciphertext = salt_box.encrypt(&nonce, plaintext.as_bytes()).unwrap();
  37. let mut concat = vec![];
  38. concat.append(&mut nonce.as_slice().to_vec());
  39. concat.append(&mut ciphertext);
  40. bs58::encode(concat).into_string()
  41. }
  42. /// Decrypt PrivMsg target
  43. pub fn decrypt_target(
  44. contact: &mut String,
  45. privmsg: &mut Privmsg,
  46. configured_chans: FxHashMap<String, ChannelInfo>,
  47. configured_contacts: FxHashMap<String, ContactInfo>,
  48. ) {
  49. for chan_name in configured_chans.keys() {
  50. let chan_info = configured_chans.get(chan_name).unwrap();
  51. if !chan_info.joined {
  52. continue
  53. }
  54. let salt_box = chan_info.salt_box.clone();
  55. if let Some(salt_box) = salt_box {
  56. let decrypted_target = try_decrypt(&salt_box, &privmsg.target);
  57. if decrypted_target.is_none() {
  58. continue
  59. }
  60. let target = decrypted_target.unwrap();
  61. if *chan_name == target {
  62. privmsg.target = target;
  63. return
  64. }
  65. }
  66. }
  67. for cnt_name in configured_contacts.keys() {
  68. let cnt_info = configured_contacts.get(cnt_name).unwrap();
  69. let salt_box = cnt_info.salt_box.clone();
  70. if let Some(salt_box) = salt_box {
  71. let decrypted_target = try_decrypt(&salt_box, &privmsg.target);
  72. if decrypted_target.is_none() {
  73. continue
  74. }
  75. let target = decrypted_target.unwrap();
  76. privmsg.target = target;
  77. *contact = cnt_name.into();
  78. return
  79. }
  80. }
  81. }
  82. /// Decrypt PrivMsg nickname and message
  83. pub fn decrypt_privmsg(salt_box: &SalsaBox, privmsg: &mut Privmsg) {
  84. let decrypted_nick = try_decrypt(&salt_box.clone(), &privmsg.nickname);
  85. let decrypted_msg = try_decrypt(&salt_box.clone(), &privmsg.message);
  86. if decrypted_nick.is_none() && decrypted_msg.is_none() {
  87. return
  88. }
  89. privmsg.nickname = decrypted_nick.unwrap();
  90. privmsg.message = decrypted_msg.unwrap();
  91. }
  92. /// Encrypt PrivMsg
  93. pub fn encrypt_privmsg(salt_box: &SalsaBox, privmsg: &mut Privmsg) {
  94. privmsg.nickname = encrypt(salt_box, &privmsg.nickname);
  95. privmsg.target = encrypt(salt_box, &privmsg.target);
  96. privmsg.message = encrypt(salt_box, &privmsg.message);
  97. }