enquo-core 0.8.0.1.gff74b4f-x86_64-linux → 0.8.0.5.gdc04874-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e96584ab8a8bee97716e269d29f11e6f428c607d88ec4674510538021aff5ae4
4
- data.tar.gz: 75ed79996fbf26041fd3be3bae1a0e786568b233865a1013a6c559d8a79d7f30
3
+ metadata.gz: 816d52a4c9ede05cf9b0caa05fa75009ea9f3cdbecdc5812011e6f6d2f1b723c
4
+ data.tar.gz: 07dd05d23b984c816a726b349d89213175904bae24f9646c49e776914ac1f9e6
5
5
  SHA512:
6
- metadata.gz: 7e15b35fbc5477dff9841e7fe7e0150900f2027f9d169673d91e91ae1656bc858a1180a091728402b8caa457bcae2adc337440329fc49956f4c569189fcdc2e2
7
- data.tar.gz: b178aee4e3cb1b62aacd906c0307ed239cb4b30c70094e6152aaed7d77ae7d80d2998e616628f936e9b7e89132dcb7ec07e4e8f4482f68b7eb4467771bc57fde
6
+ metadata.gz: 9e114a4d18e5bf297027ed08906dec17ae537dbbdc2313c2b9828ea933fe6e86b874d0baaee7254448ecd188fe00b5ff9fd4fdd397adbc8cf5ed569ff2a5d293
7
+ data.tar.gz: 3c911fb3bac62b8ee5a4289bad23e2eddf595c332d2c51c4f5bc606e67863d54c5df6e723972a255cfdfd89c93f91a25c84acca86a9aa951d6f194870972d1fe
data/ext/enquo/Cargo.lock CHANGED
@@ -228,17 +228,17 @@ dependencies = [
228
228
 
229
229
  [[package]]
230
230
  name = "cretrit"
231
- version = "0.4.1"
231
+ version = "0.5.0"
232
232
  source = "registry+https://github.com/rust-lang/crates.io-index"
233
- checksum = "0b424f56a53c945d026954e4b431c9d8bd3cd8c431574c8f4b77f59e860c366a"
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
- "sha2",
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"
@@ -1,4 +1,10 @@
1
- use enquo_core::{Boolean, Date, Error, Text, I64};
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
- // Safe because we immediately copy away the value
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
- .expect("CAN'T HAPPEN: got None from strict_bool(Some(opts.input)) !!!");
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
- pub fn init(base: &RModule) -> Result<(), magnus::Error> {
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(&base_mod)?;
10
- root_key::init(&base_mod)?;
11
- field::init(&base_mod)?;
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
+ }
@@ -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(k.deref().clone()),
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
- pub fn init(base: &RModule) -> Result<(), magnus::Error> {
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))?;
@@ -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(unsafe { (*k_str.as_slice()).to_vec() })
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(unsafe {
32
- hex::decode(k_str.as_slice()).map_err(|e| {
33
- magnus::Error::new(
34
- exception::arg_error(),
35
- format!("hex key must only contain valid hex characters: {e}"),
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
- Ok(RootKey(Arc::new(key_provider::Static::new(k))))
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
- pub fn init(base: &RModule) -> Result<(), magnus::Error> {
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.so CHANGED
Binary file
data/lib/3.0/enquo.so CHANGED
Binary file
data/lib/3.1/enquo.so CHANGED
Binary file
data/lib/3.2/enquo.so CHANGED
Binary file
data/lib/enquo.so 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.1.gff74b4f
4
+ version: 0.8.0.5.gdc04874
5
5
  platform: x86_64-linux
6
6
  authors:
7
7
  - Matt Palmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-04 00:00:00.000000000 Z
11
+ date: 2023-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler