rtj/
lib.rs

1// rtj provides a generic job execution framework in Rust
2// Copyright 2021-2024 Anthony Martinez
3//
4// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
5// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
6// http://opensource.org/licenses/MIT>, at your option. This file may not be
7// copied, modified, or distributed except according to those terms.
8
9//! **rtj** aims to provide a generic, robust, and secure framework for users to develop
10//! their own job execution applications. Encryption uses [`crypto_box`] and is compatible with
11//! other implementations of the [standard](https://doc.libsodium.org/public-key_cryptography/authenticated_encryption).
12//!
13//! ### Example:
14//! ``` 
15//! // Full example avaialble in the source repo under /examples/hello.rs
16//! use rtj::{Job, Message};
17//!# use crypto_box::SecretKey;
18//!# use rmp_serde as rmps;
19//!# use serde::{Deserialize, Serialize};
20//!# type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
21//!# enum MsgType {
22//!#   Hello,
23//!#   Unknown,
24//!# }
25//!# impl From<u8> for MsgType {
26//!#     fn from(t: u8) -> MsgType {
27//!#         match t {
28//!#             0 => MsgType::Hello,
29//!#             _ => MsgType::Unknown,
30//!#         }
31//!#     }
32//!# }
33//!# impl From<MsgType> for u8 {
34//!#    fn from(t: MsgType) -> u8 {
35//!#        match t {
36//!#            MsgType::Hello => 0,
37//!#            MsgType::Unknown => 255,
38//!#        }
39//!#    }
40//!# }
41//!# #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
42//!# struct Hello {
43//!#    name: String,
44//!#    age: u8,
45//!# }
46//!# impl Job for Hello {
47//!#    fn encode(&self) -> Vec<u8> {
48//!#        rmps::to_vec(&self).unwrap()
49//!#    }
50//!#    fn decode(input: &[u8]) -> Hello {
51//!#        let hello: Hello = rmps::from_read(input).unwrap();
52//!#        hello
53//!#    }
54//!#    fn ack(&self) -> Vec<u8> {
55//!#        let name = &self.name;
56//!#        let age = &self.age;
57//!#        let ack_string = format!("Hello from {name}, age {age}");
58//!#        Vec::from(ack_string)
59//!#    }
60//!#    fn run(&self) -> Result<()> {
61//!#        let ack_string = String::from_utf8(self.ack())?;
62//!#        println!("{ack_string}");
63//!#        Ok(())
64//!#    }
65//!# }
66//!# fn main() -> Result<()> {
67//!#     let mut rng = rand::thread_rng();
68//!#     // Create the sender's keys
69//!#     // This would normally be loaded from a secure location
70//!#     let send_secret = SecretKey::generate(&mut rng);
71//!#     let send_pub = send_secret.public_key().as_bytes().to_owned();
72//!#     // Create the recipient's keys
73//!#     // This would normally exist on a remote node, and be loaded
74//!#     // from a secure location. The sender should have a copy of
75//!#     // the remote node's public key to encrypt towards.
76//!#     let recv_secret = SecretKey::generate(&mut rng);
77//!#
78//!#     let name = "Anthony J. Martinez".to_owned();
79//!#     let age = 38;
80//!     // Create a struct that implements Job
81//!     let hello = Hello { name, age };
82//!
83//!     // Build a Message from that struct
84//!     let msg = Message::new()
85//!         .set_payload(&hello)
86//!         .set_header(MsgType::Hello, send_pub, &mut rng)?;
87//!
88//!     // Encrypt the message payload for the recipient.
89//!     let encrypted_to_recv = msg.encrypt(recv_secret.public_key(), send_secret)?;
90//!
91//!     // Decrypt the message payload as the recipient.
92//!     let hello_again = encrypted_to_recv.decrypt(recv_secret)?;
93//!
94//!     // Verify the message type.
95//!     if let MsgType::Hello = hello_again.header.msgtype.into() {
96//!         // Deserialize the message payload as the correct type
97//!         let hello = Hello::decode(&hello_again.payload);
98//!
99//!         // Execute the runner method on the deserialized type
100//!         hello.run()?;
101//!     }
102//!
103//!#     Ok(())
104//!# }
105//! ```
106
107use crypto_box::{
108    aead::{consts::U24, generic_array::GenericArray, AeadMut},
109    PublicKey, SecretKey,
110};
111use rand::{CryptoRng, RngCore};
112use serde::{Deserialize, Serialize};
113
114mod error;
115mod header;
116mod job;
117mod message;
118
119pub use error::RtjError;
120pub use header::Header;
121pub use job::Job;
122pub use message::Message;
123
124type Result<T> = std::result::Result<T, RtjError>;