enquo-core 0.8.0.1.gff74b4f-x86_64-darwin → 0.8.0.5.gdc04874-x86_64-darwin
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/enquo/Cargo.lock +4 -27
- data/ext/enquo/Cargo.toml +7 -1
- data/ext/enquo/src/field.rs +47 -7
- data/ext/enquo/src/lib.rs +28 -3
- data/ext/enquo/src/root.rs +12 -3
- data/ext/enquo/src/root_key.rs +24 -12
- data/lib/2.7/enquo.bundle +0 -0
- data/lib/3.0/enquo.bundle +0 -0
- data/lib/3.1/enquo.bundle +0 -0
- data/lib/3.2/enquo.bundle +0 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f411b3a54db00f3a2f91a3f534c9061f21f9737627ff4fb079b9fc681416dd80
|
4
|
+
data.tar.gz: ced94d2f24ab53435ee1c65a28e5521f2f85a42fd7ce5dca162c1f16de3cca45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2044ce4c4b568b758e9c28472cc0f31dd31256d9a5fd1764039e56c72cabb80813067c1c1c7eb9b17d11b2197c781bc711f8f010ddd23a884d7ac9b8a61b5d01
|
7
|
+
data.tar.gz: 8ef21fc646431aa42ddbe150271df7e98e336ccc8d064bfdd3d1852da4df345b2f706af3410f1146bf23cc0bc60d413d008ef212ada615ec95f79f5618cdca19
|
data/ext/enquo/Cargo.lock
CHANGED
@@ -228,17 +228,17 @@ dependencies = [
|
|
228
228
|
|
229
229
|
[[package]]
|
230
230
|
name = "cretrit"
|
231
|
-
version = "0.
|
231
|
+
version = "0.5.0"
|
232
232
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
233
|
-
checksum = "
|
233
|
+
checksum = "e4ba460081834719b3cfc064384b7ba19c0292f8833c55169a5177d995f1b4a8"
|
234
234
|
dependencies = [
|
235
235
|
"aes",
|
236
236
|
"cmac",
|
237
|
-
"hmac",
|
238
237
|
"num",
|
239
238
|
"rand",
|
240
239
|
"rand_chacha",
|
241
|
-
"
|
240
|
+
"serde",
|
241
|
+
"serde_bytes",
|
242
242
|
"thiserror",
|
243
243
|
"zeroize",
|
244
244
|
]
|
@@ -368,7 +368,6 @@ version = "0.0.0"
|
|
368
368
|
dependencies = [
|
369
369
|
"enquo-core",
|
370
370
|
"hex",
|
371
|
-
"lazy_static",
|
372
371
|
"magnus",
|
373
372
|
"serde_json",
|
374
373
|
]
|
@@ -380,12 +379,10 @@ dependencies = [
|
|
380
379
|
"aes-gcm-siv",
|
381
380
|
"ciborium",
|
382
381
|
"cretrit",
|
383
|
-
"hmac",
|
384
382
|
"rand_chacha",
|
385
383
|
"serde",
|
386
384
|
"serde_bytes",
|
387
385
|
"serde_with",
|
388
|
-
"sha2",
|
389
386
|
"thiserror",
|
390
387
|
"unicode-normalization",
|
391
388
|
]
|
@@ -441,15 +438,6 @@ version = "0.4.3"
|
|
441
438
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
442
439
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
443
440
|
|
444
|
-
[[package]]
|
445
|
-
name = "hmac"
|
446
|
-
version = "0.12.1"
|
447
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
448
|
-
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
449
|
-
dependencies = [
|
450
|
-
"digest",
|
451
|
-
]
|
452
|
-
|
453
441
|
[[package]]
|
454
442
|
name = "iana-time-zone"
|
455
443
|
version = "0.1.54"
|
@@ -898,17 +886,6 @@ dependencies = [
|
|
898
886
|
"syn",
|
899
887
|
]
|
900
888
|
|
901
|
-
[[package]]
|
902
|
-
name = "sha2"
|
903
|
-
version = "0.10.5"
|
904
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
905
|
-
checksum = "cf9db03534dff993187064c4e0c05a5708d2a9728ace9a8959b77bedf415dac5"
|
906
|
-
dependencies = [
|
907
|
-
"cfg-if",
|
908
|
-
"cpufeatures",
|
909
|
-
"digest",
|
910
|
-
]
|
911
|
-
|
912
889
|
[[package]]
|
913
890
|
name = "shell-words"
|
914
891
|
version = "1.1.0"
|
data/ext/enquo/Cargo.toml
CHANGED
@@ -1,11 +1,17 @@
|
|
1
1
|
[package]
|
2
2
|
name = "enquo"
|
3
|
+
description = "Rust dynamic library for Ruby enquo-core"
|
4
|
+
license = "MIT"
|
5
|
+
repository = "https://github.com/enquo/enquo-core"
|
6
|
+
homepage = "https://enquo.org"
|
7
|
+
readme = "../../../README.md"
|
8
|
+
keywords = ["encryption", "search", "query", "ore", "ruby"]
|
9
|
+
categories = ["algorithms", "cryptography"]
|
3
10
|
version = "0.0.0"
|
4
11
|
edition = "2021"
|
5
12
|
|
6
13
|
[dependencies]
|
7
14
|
enquo-core = { path = "../../../rust" }
|
8
|
-
lazy_static = "1.0"
|
9
15
|
serde_json = "1.0"
|
10
16
|
magnus = "0.5"
|
11
17
|
hex = "0.4"
|
data/ext/enquo/src/field.rs
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
|
1
|
+
//! Everything related to `Enquo::Field`
|
2
|
+
//!
|
3
|
+
|
4
|
+
use enquo_core::{
|
5
|
+
datatype::{Boolean, Date, Text, I64},
|
6
|
+
Error,
|
7
|
+
};
|
2
8
|
use magnus::{
|
3
9
|
class, eval, exception, function, method,
|
4
10
|
prelude::*,
|
@@ -7,10 +13,11 @@ use magnus::{
|
|
7
13
|
};
|
8
14
|
use std::ops::Deref;
|
9
15
|
|
10
|
-
use crate::maybe_raise;
|
16
|
+
use crate::{maybe_raise, string_to_bytes};
|
11
17
|
|
18
|
+
/// Wrapper struct for the `enquo_core` `Field` struct
|
12
19
|
#[magnus::wrap(class = "Enquo::Field")]
|
13
|
-
pub struct Field(pub enquo_core::Field);
|
20
|
+
pub(crate) struct Field(pub(crate) enquo_core::Field);
|
14
21
|
|
15
22
|
impl Deref for Field {
|
16
23
|
type Target = enquo_core::Field;
|
@@ -20,17 +27,32 @@ impl Deref for Field {
|
|
20
27
|
}
|
21
28
|
}
|
22
29
|
|
30
|
+
/// The results of parsing all the various options that can be passed when encrypting a value
|
23
31
|
struct EncryptOpts<T>
|
24
32
|
where
|
25
33
|
T: TryConvert,
|
26
34
|
{
|
35
|
+
/// The value to be encrypted
|
27
36
|
input: T,
|
37
|
+
/// The encryption context
|
28
38
|
context: Vec<u8>,
|
39
|
+
/// Whether the ciphertext should be created with unsafe parts included
|
29
40
|
unsafe_ok: bool,
|
41
|
+
/// Whether the ciphertext should have all querying portions removed
|
30
42
|
no_query: bool,
|
43
|
+
/// (Text only) how long to make the ordering code
|
31
44
|
order_prefix_length: Option<u8>,
|
32
45
|
}
|
33
46
|
|
47
|
+
/// Convert *actual* Ruby booleans into Rust `bool`
|
48
|
+
///
|
49
|
+
/// Magnus supports converting into a Rust `bool`, but it takes Ruby's extremely laissez-faire
|
50
|
+
/// approach, where basically everything is `true` unless it's strictly defined as `false`
|
51
|
+
/// (basically just `false` and `nil`).
|
52
|
+
///
|
53
|
+
/// I, on the other hand, want to accept only *actual booleans* when encrypting a bool, so... here
|
54
|
+
/// we are.
|
55
|
+
///
|
34
56
|
fn strict_bool(value: Option<magnus::Value>, e: &str) -> Result<Option<bool>, magnus::Error> {
|
35
57
|
match value {
|
36
58
|
None => Ok(None),
|
@@ -49,6 +71,11 @@ fn strict_bool(value: Option<magnus::Value>, e: &str) -> Result<Option<bool>, ma
|
|
49
71
|
}
|
50
72
|
}
|
51
73
|
|
74
|
+
/// Convert *actual* Ruby Integers into Rust integer types
|
75
|
+
///
|
76
|
+
/// Magnus will accept various floaty-type things and truncate them into integers, which we really,
|
77
|
+
/// absolutely, do not want.
|
78
|
+
///
|
52
79
|
fn strict_int<T: TryConvert>(
|
53
80
|
value: Option<magnus::Value>,
|
54
81
|
e: &str,
|
@@ -68,6 +95,9 @@ fn strict_int<T: TryConvert>(
|
|
68
95
|
}
|
69
96
|
}
|
70
97
|
|
98
|
+
/// Transmogrify the range of options that can be passed to an encrypt function into a more
|
99
|
+
/// appealing structure
|
100
|
+
///
|
71
101
|
fn parse_encrypt_args<T>(args: &[magnus::Value]) -> Result<EncryptOpts<T>, magnus::Error>
|
72
102
|
where
|
73
103
|
T: TryConvert,
|
@@ -96,14 +126,14 @@ where
|
|
96
126
|
|
97
127
|
Ok(EncryptOpts::<T> {
|
98
128
|
input,
|
99
|
-
|
100
|
-
context: unsafe { context_str.as_slice().to_vec() },
|
129
|
+
context: string_to_bytes(context_str),
|
101
130
|
unsafe_ok,
|
102
131
|
no_query,
|
103
132
|
order_prefix_length,
|
104
133
|
})
|
105
134
|
}
|
106
135
|
|
136
|
+
#[allow(clippy::missing_docs_in_private_items)] // I think the names speak for themselves, really
|
107
137
|
impl Field {
|
108
138
|
fn key_id(&self) -> Result<String, magnus::Error> {
|
109
139
|
maybe_raise(self.0.key_id().map(hex::encode), None)
|
@@ -116,7 +146,12 @@ impl Field {
|
|
116
146
|
Some(opts.input),
|
117
147
|
"Enquo::Field#encrypt_boolean can only encrypt booleans",
|
118
148
|
)?
|
119
|
-
.
|
149
|
+
.ok_or_else(|| {
|
150
|
+
magnus::Error::new(
|
151
|
+
exception::runtime_error(),
|
152
|
+
"CAN'T HAPPEN: got None from strict_bool(Some(opts.input))",
|
153
|
+
)
|
154
|
+
})?;
|
120
155
|
|
121
156
|
let mut res = maybe_raise(
|
122
157
|
if opts.unsafe_ok {
|
@@ -137,6 +172,7 @@ impl Field {
|
|
137
172
|
)
|
138
173
|
}
|
139
174
|
|
175
|
+
#[allow(clippy::needless_pass_by_value)] // Magnus is not friends with &str args
|
140
176
|
fn decrypt_boolean(&self, ciphertext: String, context: String) -> Result<bool, magnus::Error> {
|
141
177
|
let ct: Boolean = maybe_raise(
|
142
178
|
serde_json::from_str(&ciphertext),
|
@@ -183,6 +219,7 @@ impl Field {
|
|
183
219
|
)
|
184
220
|
}
|
185
221
|
|
222
|
+
#[allow(clippy::needless_pass_by_value)] // Magnus is not friends with &str args
|
186
223
|
fn decrypt_i64(&self, ciphertext: String, context: String) -> Result<i64, magnus::Error> {
|
187
224
|
let ct: I64 = maybe_raise(
|
188
225
|
serde_json::from_str(&ciphertext),
|
@@ -229,6 +266,7 @@ impl Field {
|
|
229
266
|
)
|
230
267
|
}
|
231
268
|
|
269
|
+
#[allow(clippy::needless_pass_by_value)] // Magnus is not friends with &str args
|
232
270
|
fn decrypt_date(
|
233
271
|
&self,
|
234
272
|
ciphertext: String,
|
@@ -290,6 +328,7 @@ impl Field {
|
|
290
328
|
)
|
291
329
|
}
|
292
330
|
|
331
|
+
#[allow(clippy::needless_pass_by_value)] // Magnus is not friends with &str args
|
293
332
|
fn decrypt_text(&self, ciphertext: String, context: String) -> Result<String, magnus::Error> {
|
294
333
|
let ct: Text = maybe_raise(
|
295
334
|
serde_json::from_str(&ciphertext),
|
@@ -308,7 +347,8 @@ impl Field {
|
|
308
347
|
}
|
309
348
|
}
|
310
349
|
|
311
|
-
|
350
|
+
/// Create the Field class and setup all its methods
|
351
|
+
pub(crate) fn init(base: RModule) -> Result<(), magnus::Error> {
|
312
352
|
let class = base.define_class("Field", class::object())?;
|
313
353
|
|
314
354
|
class.define_singleton_method(
|
data/ext/enquo/src/lib.rs
CHANGED
@@ -1,18 +1,28 @@
|
|
1
|
+
//! Ruby extension for enquo-core
|
2
|
+
//!
|
3
|
+
//!
|
4
|
+
|
5
|
+
// magnus::init spews an error that I *cannot*, for the life of me, figure out how to suppress, so
|
6
|
+
// we'll just have to suppress it globally and remember to write docs where appropriate
|
7
|
+
#![allow(missing_docs)]
|
8
|
+
|
1
9
|
mod field;
|
2
10
|
mod root;
|
3
11
|
mod root_key;
|
4
12
|
|
13
|
+
/// Tell Ruby to initialise everything
|
5
14
|
#[magnus::init]
|
6
15
|
fn init() -> Result<(), magnus::Error> {
|
7
16
|
let base_mod = magnus::define_module("Enquo")?;
|
8
17
|
|
9
|
-
root::init(
|
10
|
-
root_key::init(
|
11
|
-
field::init(
|
18
|
+
root::init(base_mod)?;
|
19
|
+
root_key::init(base_mod)?;
|
20
|
+
field::init(base_mod)?;
|
12
21
|
|
13
22
|
Ok(())
|
14
23
|
}
|
15
24
|
|
25
|
+
/// Dig up the Enquo exception class
|
16
26
|
fn enquo_exception() -> Result<magnus::ExceptionClass, magnus::Error> {
|
17
27
|
magnus::ExceptionClass::from_value(magnus::eval("::Enquo::Error")?).ok_or_else(|| {
|
18
28
|
magnus::Error::new(
|
@@ -22,6 +32,8 @@ fn enquo_exception() -> Result<magnus::ExceptionClass, magnus::Error> {
|
|
22
32
|
})
|
23
33
|
}
|
24
34
|
|
35
|
+
/// Check if the value passed in is an error, and if so, turn it into something that Magnus will
|
36
|
+
/// recognise as an Enquo exception to be raised.
|
25
37
|
fn maybe_raise<T, E: std::error::Error>(
|
26
38
|
r: Result<T, E>,
|
27
39
|
s: Option<&str>,
|
@@ -38,3 +50,16 @@ fn maybe_raise<T, E: std::error::Error>(
|
|
38
50
|
)
|
39
51
|
})
|
40
52
|
}
|
53
|
+
|
54
|
+
/// Turn an `RString`'s contents into a Vec<u8>
|
55
|
+
///
|
56
|
+
/// Useful when the string's contents aren't UTF-8 text, or we just want to muck around with it in
|
57
|
+
/// some low-levelish way. Strange that Magnus doesn't seem to have a safe function already to do
|
58
|
+
/// this.
|
59
|
+
fn string_to_bytes(s: magnus::RString) -> Vec<u8> {
|
60
|
+
#[allow(unsafe_code)]
|
61
|
+
// SAFETY: we don't let Ruby GC while we hold the ref
|
62
|
+
unsafe {
|
63
|
+
s.as_slice().to_owned()
|
64
|
+
}
|
65
|
+
}
|
data/ext/enquo/src/root.rs
CHANGED
@@ -1,8 +1,13 @@
|
|
1
|
+
//! The home of the `Enquo::Root` class
|
2
|
+
//!
|
3
|
+
|
4
|
+
use enquo_core::KeyProvider;
|
1
5
|
use magnus::{class, function, method, prelude::*, RModule};
|
2
|
-
use std::ops::Deref;
|
6
|
+
use std::{ops::Deref, sync::Arc};
|
3
7
|
|
4
8
|
use crate::{field::Field, maybe_raise, root_key::RootKey};
|
5
9
|
|
10
|
+
/// Wrapper struct for the enquo_core struct of the same name
|
6
11
|
#[magnus::wrap(class = "Enquo::Root")]
|
7
12
|
struct Root(enquo_core::Root);
|
8
13
|
|
@@ -15,13 +20,16 @@ impl Deref for Root {
|
|
15
20
|
}
|
16
21
|
|
17
22
|
impl Root {
|
23
|
+
/// Create a new root from a root key
|
18
24
|
fn new(k: &RootKey) -> Result<Self, magnus::Error> {
|
19
25
|
Ok(Self(maybe_raise(
|
20
|
-
enquo_core::Root::new(
|
26
|
+
enquo_core::Root::new(Arc::<dyn KeyProvider>::clone(&**k)),
|
21
27
|
None,
|
22
28
|
)?))
|
23
29
|
}
|
24
30
|
|
31
|
+
/// Spawn a new `Enquo::Field`
|
32
|
+
#[allow(clippy::needless_pass_by_value)] // Magnus is not friends with &str args
|
25
33
|
fn field(&self, relation: String, name: String) -> Result<Field, magnus::Error> {
|
26
34
|
Ok(Field(maybe_raise(
|
27
35
|
self.0.field(relation.as_bytes(), name.as_bytes()),
|
@@ -30,7 +38,8 @@ impl Root {
|
|
30
38
|
}
|
31
39
|
}
|
32
40
|
|
33
|
-
|
41
|
+
/// Wire up everything for `Enquo::Root`
|
42
|
+
pub(crate) fn init(base: RModule) -> Result<(), magnus::Error> {
|
34
43
|
let class = base.define_class("Root", class::object())?;
|
35
44
|
|
36
45
|
class.define_singleton_method("new", function!(Root::new, 1))?;
|
data/ext/enquo/src/root_key.rs
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
+
//! The `Enquo::RootKey` Ruby module
|
2
|
+
//!
|
3
|
+
|
1
4
|
use enquo_core::{key_provider, key_provider::KeyProvider};
|
2
5
|
use magnus::{class, encoding, exception, function, prelude::*, RModule};
|
3
6
|
use std::ops::Deref;
|
4
7
|
use std::sync::Arc;
|
5
8
|
|
9
|
+
use crate::{maybe_raise, string_to_bytes};
|
10
|
+
|
11
|
+
/// The key provided to the Root from which all other keys are derived
|
6
12
|
#[magnus::wrap(class = "Enquo::RootKey")]
|
7
|
-
pub struct RootKey(Arc<dyn KeyProvider>);
|
13
|
+
pub(crate) struct RootKey(Arc<dyn KeyProvider>);
|
8
14
|
|
9
15
|
impl Deref for RootKey {
|
10
16
|
type Target = Arc<dyn KeyProvider>;
|
@@ -14,12 +20,13 @@ impl Deref for RootKey {
|
|
14
20
|
}
|
15
21
|
}
|
16
22
|
|
23
|
+
/// Creates a `RootKey::Static` instance from the key provided
|
17
24
|
fn new_static_root_key(k_str: magnus::RString) -> Result<RootKey, magnus::Error> {
|
18
25
|
let encindex = k_str.enc_get();
|
19
26
|
|
20
27
|
let k: &[u8] = &if encindex == encoding::Index::ascii8bit() {
|
21
28
|
if k_str.len() == 32 {
|
22
|
-
Ok(
|
29
|
+
Ok(string_to_bytes(k_str))
|
23
30
|
} else {
|
24
31
|
Err(magnus::Error::new(
|
25
32
|
exception::arg_error(),
|
@@ -28,14 +35,12 @@ fn new_static_root_key(k_str: magnus::RString) -> Result<RootKey, magnus::Error>
|
|
28
35
|
}
|
29
36
|
} else if encindex == encoding::Index::utf8() || encindex == encoding::Index::usascii() {
|
30
37
|
if k_str.len() == 64 {
|
31
|
-
Ok(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
})?
|
38
|
-
})
|
38
|
+
Ok(hex::decode(string_to_bytes(k_str)).map_err(|e| {
|
39
|
+
magnus::Error::new(
|
40
|
+
exception::arg_error(),
|
41
|
+
format!("hex key must only contain valid hex characters: {e}"),
|
42
|
+
)
|
43
|
+
})?)
|
39
44
|
} else {
|
40
45
|
Err(magnus::Error::new(
|
41
46
|
exception::arg_error(),
|
@@ -52,10 +57,17 @@ fn new_static_root_key(k_str: magnus::RString) -> Result<RootKey, magnus::Error>
|
|
52
57
|
))
|
53
58
|
}?;
|
54
59
|
|
55
|
-
|
60
|
+
let mut key: [u8; 32] = Default::default();
|
61
|
+
key.copy_from_slice(k);
|
62
|
+
|
63
|
+
Ok(RootKey(Arc::new(maybe_raise(
|
64
|
+
key_provider::Static::new(&key),
|
65
|
+
None,
|
66
|
+
)?)))
|
56
67
|
}
|
57
68
|
|
58
|
-
|
69
|
+
/// Create the `Enquo::RootKey` class and wire in its methods
|
70
|
+
pub(crate) fn init(base: RModule) -> Result<(), magnus::Error> {
|
59
71
|
let base_class = base.define_class("RootKey", class::object())?;
|
60
72
|
|
61
73
|
{
|
data/lib/2.7/enquo.bundle
CHANGED
Binary file
|
data/lib/3.0/enquo.bundle
CHANGED
Binary file
|
data/lib/3.1/enquo.bundle
CHANGED
Binary file
|
data/lib/3.2/enquo.bundle
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: enquo-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.0.
|
4
|
+
version: 0.8.0.5.gdc04874
|
5
5
|
platform: x86_64-darwin
|
6
6
|
authors:
|
7
7
|
- Matt Palmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-05-
|
11
|
+
date: 2023-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|