mirror of
https://github.com/lune-org/lune.git
synced 2025-04-11 22:10:53 +01:00
feat: initial crypto library rust-side implementation
This commit is contained in:
parent
1aa6aef679
commit
21d91856a3
4 changed files with 270 additions and 7 deletions
60
Cargo.lock
generated
60
Cargo.lock
generated
|
@ -840,6 +840,12 @@ version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
version = "0.5.5"
|
version = "0.5.5"
|
||||||
|
@ -1113,6 +1119,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"base64 0.21.4",
|
||||||
"chrono",
|
"chrono",
|
||||||
"chrono_lc",
|
"chrono_lc",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -1123,11 +1130,13 @@ dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"glam",
|
"glam",
|
||||||
|
"hex",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-tungstenite",
|
"hyper-tungstenite",
|
||||||
"include_dir",
|
"include_dir",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lz4_flex",
|
"lz4_flex",
|
||||||
|
"md-5",
|
||||||
"mlua",
|
"mlua",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -1143,6 +1152,7 @@ dependencies = [
|
||||||
"rbx_xml",
|
"rbx_xml",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"ring 0.17.3",
|
||||||
"rustyline",
|
"rustyline",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -1194,6 +1204,16 @@ dependencies = [
|
||||||
"regex-automata 0.1.10",
|
"regex-automata 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "md-5"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.6.4"
|
version = "2.6.4"
|
||||||
|
@ -1780,12 +1800,26 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"spin",
|
"spin 0.5.2",
|
||||||
"untrusted",
|
"untrusted 0.7.1",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ring"
|
||||||
|
version = "0.17.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9babe80d5c16becf6594aa32ad2be8fe08498e7ae60b77de8df700e67f191d7e"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"getrandom 0.2.10",
|
||||||
|
"libc",
|
||||||
|
"spin 0.9.8",
|
||||||
|
"untrusted 0.9.0",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rmp"
|
name = "rmp"
|
||||||
version = "0.8.12"
|
version = "0.8.12"
|
||||||
|
@ -1861,7 +1895,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8"
|
checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"ring",
|
"ring 0.16.20",
|
||||||
"rustls-webpki",
|
"rustls-webpki",
|
||||||
"sct",
|
"sct",
|
||||||
]
|
]
|
||||||
|
@ -1881,8 +1915,8 @@ version = "0.101.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe"
|
checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ring",
|
"ring 0.16.20",
|
||||||
"untrusted",
|
"untrusted 0.7.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1941,8 +1975,8 @@ version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
|
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ring",
|
"ring 0.16.20",
|
||||||
"untrusted",
|
"untrusted 0.7.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2127,6 +2161,12 @@ version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "standback"
|
name = "standback"
|
||||||
version = "0.2.17"
|
version = "0.2.17"
|
||||||
|
@ -2639,6 +2679,12 @@ version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "untrusted"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.4.1"
|
version = "2.4.1"
|
||||||
|
|
|
@ -98,6 +98,11 @@ serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
toml = { version = "0.8", features = ["preserve_order"] }
|
toml = { version = "0.8", features = ["preserve_order"] }
|
||||||
|
|
||||||
|
ring = "0.17.3"
|
||||||
|
base64 = "0.21.4"
|
||||||
|
hex = "0.4.3"
|
||||||
|
md-5 = "0.10.6"
|
||||||
|
|
||||||
### NET
|
### NET
|
||||||
|
|
||||||
hyper = { version = "0.14", features = ["full"] }
|
hyper = { version = "0.14", features = ["full"] }
|
||||||
|
|
211
src/lune/builtins/serde/crypto.rs
Normal file
211
src/lune/builtins/serde/crypto.rs
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use base64::{engine::general_purpose as Base64, Engine as _};
|
||||||
|
use ring::digest::{self, digest, Digest};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Crypto;
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct CryptoResult<T, C>
|
||||||
|
where
|
||||||
|
T: AsRef<[u8]>,
|
||||||
|
C: AsRef<[u8]>,
|
||||||
|
{
|
||||||
|
algo: CryptoAlgo,
|
||||||
|
content: Option<T>,
|
||||||
|
computed: Option<C>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum CryptoAlgo {
|
||||||
|
Sha256,
|
||||||
|
Sha512,
|
||||||
|
// We shouldn't be able to Pass Hmac(Hmac), would there be a way to limit this?
|
||||||
|
Hmac(Box<CryptoAlgo>),
|
||||||
|
Md5,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Crypto {
|
||||||
|
pub fn sha256<T>(content: Option<T>) -> CryptoResult<String, Digest>
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
let content = content.map(|data| data.to_string());
|
||||||
|
|
||||||
|
CryptoResult {
|
||||||
|
algo: CryptoAlgo::Sha256,
|
||||||
|
content,
|
||||||
|
computed: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sha512<T>(content: Option<T>) -> CryptoResult<String, Digest>
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
let content = content.map(|data| data.to_string());
|
||||||
|
|
||||||
|
CryptoResult {
|
||||||
|
algo: CryptoAlgo::Sha512,
|
||||||
|
content,
|
||||||
|
computed: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hmac<T>(content: Option<T>, algo: CryptoAlgo) -> CryptoResult<String, ring::hmac::Tag>
|
||||||
|
where
|
||||||
|
T: ToString,
|
||||||
|
{
|
||||||
|
let content = content.map(|data| data.to_string());
|
||||||
|
|
||||||
|
CryptoResult {
|
||||||
|
algo: CryptoAlgo::Hmac(Box::new(algo)),
|
||||||
|
content,
|
||||||
|
computed: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait FromCryptoAlgo {
|
||||||
|
fn from_crypto_algo(value: CryptoAlgo) -> &'static Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait FromCryptoAlgoOwned {
|
||||||
|
fn from_crypto_algo(value: CryptoAlgo) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromCryptoAlgo for ring::digest::Algorithm {
|
||||||
|
fn from_crypto_algo(value: CryptoAlgo) -> &'static Self {
|
||||||
|
match &value {
|
||||||
|
CryptoAlgo::Sha256 => &digest::SHA256,
|
||||||
|
CryptoAlgo::Sha512 => &digest::SHA512,
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromCryptoAlgoOwned for ring::hmac::Algorithm {
|
||||||
|
fn from_crypto_algo(value: CryptoAlgo) -> Self {
|
||||||
|
let val: ring::hmac::Algorithm = match value {
|
||||||
|
CryptoAlgo::Hmac(algo) => match *algo {
|
||||||
|
CryptoAlgo::Sha256 => ring::hmac::HMAC_SHA256,
|
||||||
|
CryptoAlgo::Sha512 => ring::hmac::HMAC_SHA512,
|
||||||
|
CryptoAlgo::Hmac(_) => panic!("Hmac(Hmac) is not allowed!"),
|
||||||
|
CryptoAlgo::Md5 => ring::hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
|
||||||
|
},
|
||||||
|
_ => panic!("invalid type"),
|
||||||
|
};
|
||||||
|
|
||||||
|
val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum EncodingKind {
|
||||||
|
Utf8,
|
||||||
|
Base64,
|
||||||
|
Hex,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that compute and digest declared here are identical to those of the below implementation
|
||||||
|
// Quite a bit of boilerplate, is there any way to avoid this without using derive macros?
|
||||||
|
impl CryptoResult<String, ring::hmac::Tag> {
|
||||||
|
pub fn update(&mut self, content: String) -> Self {
|
||||||
|
self.content = Some(content);
|
||||||
|
|
||||||
|
(*self).to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute(&mut self) -> Self {
|
||||||
|
let content = match &self.content {
|
||||||
|
Some(inner) => inner.to_owned(),
|
||||||
|
None => "".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.algo {
|
||||||
|
CryptoAlgo::Hmac(_) => {
|
||||||
|
let rng = ring::rand::SystemRandom::new();
|
||||||
|
let key = ring::hmac::Key::generate(
|
||||||
|
ring::hmac::Algorithm::from_crypto_algo(self.algo.clone()),
|
||||||
|
&rng,
|
||||||
|
)
|
||||||
|
.expect("failed to generate random key");
|
||||||
|
|
||||||
|
self.computed = Some(ring::hmac::sign(&key, content.as_bytes()));
|
||||||
|
}
|
||||||
|
_ => panic!("Invalid implementation"),
|
||||||
|
};
|
||||||
|
|
||||||
|
(*self).to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn digest(&self, encoding: EncodingKind) -> Result<String> {
|
||||||
|
let computed = self.computed.ok_or(anyhow::Error::msg(
|
||||||
|
"compute the hash first before trying to obtain a digest",
|
||||||
|
))?;
|
||||||
|
|
||||||
|
match encoding {
|
||||||
|
EncodingKind::Utf8 => {
|
||||||
|
String::from_utf8(computed.as_ref().to_vec()).map_err(anyhow::Error::from)
|
||||||
|
}
|
||||||
|
EncodingKind::Base64 => Ok(Base64::STANDARD.encode(computed)),
|
||||||
|
EncodingKind::Hex => Ok(hex::encode(computed.as_ref())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CryptoResult<String, Digest> {
|
||||||
|
pub fn update(&mut self, content: String) -> Self {
|
||||||
|
self.content = Some(content);
|
||||||
|
|
||||||
|
(*self).to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute(&mut self) -> Self {
|
||||||
|
let content = match &self.content {
|
||||||
|
Some(inner) => inner.to_owned(),
|
||||||
|
None => "".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.algo {
|
||||||
|
CryptoAlgo::Sha256 | CryptoAlgo::Sha512 => {
|
||||||
|
self.computed = Some(digest(
|
||||||
|
ring::digest::Algorithm::from_crypto_algo(self.algo.clone()),
|
||||||
|
content.as_bytes(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
CryptoAlgo::Hmac(_) => unreachable!(),
|
||||||
|
CryptoAlgo::Md5 => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
(*self).to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn digest(&self, encoding: EncodingKind) -> Result<String> {
|
||||||
|
let computed = self.computed.ok_or(anyhow::Error::msg(
|
||||||
|
"compute the hash first before trying to obtain a digest",
|
||||||
|
))?;
|
||||||
|
|
||||||
|
match encoding {
|
||||||
|
EncodingKind::Utf8 => {
|
||||||
|
String::from_utf8(computed.as_ref().to_vec()).map_err(anyhow::Error::from)
|
||||||
|
}
|
||||||
|
EncodingKind::Base64 => Ok(Base64::STANDARD.encode(computed)),
|
||||||
|
EncodingKind::Hex => Ok(hex::encode(computed.as_ref())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test() {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
Crypto::sha256::<&str>(None /* or Some("some string!") */)
|
||||||
|
.update("some string!".to_string())
|
||||||
|
.compute()
|
||||||
|
.digest(EncodingKind::Hex)
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
Crypto::hmac(Some("test"), CryptoAlgo::Sha256)
|
||||||
|
.compute()
|
||||||
|
.digest(EncodingKind::Base64)
|
||||||
|
.unwrap();
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
pub(super) mod compress_decompress;
|
pub(super) mod compress_decompress;
|
||||||
|
pub(super) mod crypto;
|
||||||
pub(super) mod encode_decode;
|
pub(super) mod encode_decode;
|
||||||
|
|
||||||
use compress_decompress::{compress, decompress, CompressDecompressFormat};
|
use compress_decompress::{compress, decompress, CompressDecompressFormat};
|
||||||
|
|
Loading…
Add table
Reference in a new issue