enquo-core 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ [package]
2
+ name = "enquo"
3
+ version = "0.0.0"
4
+ edition = "2021"
5
+
6
+ [dependencies]
7
+ enquo-core = { path = "../../../rust" }
8
+ lazy_static = "1.0"
9
+ serde_json = "1.0"
10
+ rb-sys = "0.8"
11
+ rutie = { git = "https://github.com/mpalmer/rutie", branch = "rb_sys" }
12
+
13
+ [lib]
14
+ crate-type = ["cdylib"]
@@ -0,0 +1,4 @@
1
+ require "mkmf"
2
+ require "rb_sys/mkmf"
3
+
4
+ create_rust_makefile("enquo/enquo")
@@ -0,0 +1,139 @@
1
+ #[macro_use]
2
+ extern crate rutie;
3
+
4
+ use enquo_core::{Field, Root, I64};
5
+ use rutie::{Class, Integer, Module, Object, RString, VerifiedObject, VM};
6
+
7
+ class!(EnquoRoot);
8
+ class!(EnquoRootKeyStatic);
9
+ class!(EnquoField);
10
+
11
+ type StaticRootKey = Vec<u8>;
12
+
13
+ wrappable_struct!(Root<'static>, RootWrapper, ROOT_WRAPPER);
14
+ wrappable_struct!(StaticRootKey, StaticRootKeyWrapper, STATIC_ROOT_KEY_WRAPPER);
15
+ wrappable_struct!(Field, FieldWrapper, FIELD_WRAPPER);
16
+
17
+ fn maybe_raise<T, E: std::error::Error>(r: Result<T, E>, s: &str) -> T {
18
+ r.map_err(|e| {
19
+ VM::raise(
20
+ Class::from_existing("Enquo").get_nested_class("Error"),
21
+ &format!("{}: {}", s, e),
22
+ )
23
+ })
24
+ .unwrap()
25
+ }
26
+
27
+ methods!(
28
+ EnquoRoot,
29
+ rbself,
30
+ fn enquo_root_new_from_static_root_key(root_key_obj: EnquoRootKeyStatic) -> EnquoRoot {
31
+ let root_key = root_key_obj.unwrap();
32
+ // Not so needless after all, Clippy...
33
+ #[allow(clippy::needless_borrow)]
34
+ let rk = root_key.get_data(&*STATIC_ROOT_KEY_WRAPPER);
35
+ let root = maybe_raise(Root::new(rk), "Failed to create Enquo::Root");
36
+
37
+ let klass = Module::from_existing("Enquo").get_nested_class("Root");
38
+ klass.wrap_data(root, &*ROOT_WRAPPER)
39
+ },
40
+ fn enquo_root_field(relation: RString, name: RString) -> EnquoField {
41
+ let root = rbself.get_data(&*ROOT_WRAPPER);
42
+
43
+ let field = maybe_raise(
44
+ root.field(
45
+ &relation.unwrap().to_vec_u8_unchecked(),
46
+ &name.unwrap().to_vec_u8_unchecked(),
47
+ ),
48
+ "Failed to create Enquo::Field",
49
+ );
50
+
51
+ let klass = Module::from_existing("Enquo").get_nested_class("Field");
52
+ klass.wrap_data(field, &*FIELD_WRAPPER)
53
+ }
54
+ );
55
+
56
+ methods!(
57
+ EnquoRootKeyStatic,
58
+ _rbself,
59
+ fn enquo_root_key_static_new(root_key: RString) -> EnquoRootKeyStatic {
60
+ let k = root_key.unwrap().to_vec_u8_unchecked();
61
+ let klass = Module::from_existing("Enquo")
62
+ .get_nested_class("RootKey")
63
+ .get_nested_class("Static");
64
+ klass.wrap_data(k, &*STATIC_ROOT_KEY_WRAPPER)
65
+ },
66
+ );
67
+
68
+ impl VerifiedObject for EnquoRootKeyStatic {
69
+ fn is_correct_type<T: Object>(object: &T) -> bool {
70
+ let klass = Module::from_existing("Enquo")
71
+ .get_nested_class("RootKey")
72
+ .get_nested_class("Static");
73
+ klass.case_equals(object)
74
+ }
75
+
76
+ fn error_message() -> &'static str {
77
+ "Provided object is not an Enquo::RootKey::Static instance"
78
+ }
79
+ }
80
+
81
+ methods!(
82
+ EnquoField,
83
+ rbself,
84
+ fn enquo_field_encrypt_i64(value: Integer, context: RString) -> RString {
85
+ let i = value.unwrap().to_i64();
86
+ let field = rbself.get_data(&*FIELD_WRAPPER);
87
+
88
+ let res = maybe_raise(
89
+ field.i64(i, &context.unwrap().to_vec_u8_unchecked()),
90
+ "Failed to create encrypted i64",
91
+ );
92
+ RString::new_utf8(&serde_json::to_string(&res).unwrap())
93
+ },
94
+ fn enquo_field_decrypt_i64(ciphertext: RString, context: RString) -> Integer {
95
+ let ct_r = ciphertext.unwrap();
96
+ let ct = ct_r.to_str_unchecked();
97
+ let e_value: I64 =
98
+ maybe_raise(serde_json::from_str(ct), "Failed to deserialize ciphertext");
99
+
100
+ let field = rbself.get_data(&*FIELD_WRAPPER);
101
+
102
+ let value = maybe_raise(
103
+ e_value.decrypt(&context.unwrap().to_vec_u8_unchecked(), field),
104
+ "Failed to decrypt i64 value",
105
+ );
106
+ Integer::from(value)
107
+ }
108
+ );
109
+
110
+ #[allow(non_snake_case)]
111
+ #[no_mangle]
112
+ pub extern "C" fn Init_enquo() {
113
+ Module::from_existing("Enquo").define(|topmod| {
114
+ topmod
115
+ .define_nested_class("Root", None)
116
+ .define(|rootklass| {
117
+ rootklass.singleton_class().def_private(
118
+ "_new_from_static_root_key",
119
+ enquo_root_new_from_static_root_key,
120
+ );
121
+ rootklass.def_private("_field", enquo_root_field);
122
+ });
123
+ topmod
124
+ .define_nested_class("Field", None)
125
+ .define(|fieldklass| {
126
+ fieldklass.def_private("_encrypt_i64", enquo_field_encrypt_i64);
127
+ fieldklass.def_private("_decrypt_i64", enquo_field_decrypt_i64);
128
+ });
129
+ topmod.define_nested_module("RootKey").define(|rkmod| {
130
+ rkmod
131
+ .define_nested_class("Static", None)
132
+ .define(|statickeyklass| {
133
+ statickeyklass
134
+ .singleton_class()
135
+ .def_private("_new", enquo_root_key_static_new);
136
+ });
137
+ });
138
+ });
139
+ }
@@ -0,0 +1,39 @@
1
+ module Enquo
2
+ class Field
3
+ def self.new(*_)
4
+ raise RuntimeError, "Enquo::Field cannot be instantiated directly; use Enquo::Crypto#field instead"
5
+ end
6
+
7
+ def encrypt_i64(i, ctx)
8
+ unless i.is_a?(Integer)
9
+ raise ArgumentError, "Enquo::Field#encrypt_i64 can only encrypt integers"
10
+ end
11
+
12
+ unless i >= -2 ** 63 || i < 2 ** 63
13
+ raise ArgumentError, "Enquo::Field#encrypt_i64 can only encrypt integers between -2^63 and 2^63-1 (got #{i})"
14
+ end
15
+
16
+ unless ctx.is_a?(String)
17
+ raise ArgumentError, "Encryption context must be a string (got a #{ctx.class})"
18
+ end
19
+
20
+ _encrypt_i64(i, ctx)
21
+ end
22
+
23
+ def decrypt_i64(data, ctx)
24
+ unless data.is_a?(String)
25
+ raise ArgumentError, "Enquo::Field#decrypt_i64 can only decrypt from a string (got #{data.class})"
26
+ end
27
+
28
+ unless data.encoding == Encoding::UTF_8 && data.valid_encoding?
29
+ raise ArgumentError, "Enquo::Field#decrypt_i64 can only decrypt validly-encoded UTF-8 strings (got #{data.encoding})"
30
+ end
31
+
32
+ unless ctx.is_a?(String)
33
+ raise ArgumentError, "Encryption context must be a string (got a #{ctx.class})"
34
+ end
35
+
36
+ _decrypt_i64(data, ctx)
37
+ end
38
+ end
39
+ end
data/lib/enquo/root.rb ADDED
@@ -0,0 +1,24 @@
1
+ module Enquo
2
+ class Root
3
+ def self.new(key)
4
+ case key
5
+ when RootKey::Static
6
+ _new_from_static_root_key(key)
7
+ else
8
+ raise ArgumentError, "key must be a root key provider object (got a #{key.class})"
9
+ end
10
+ end
11
+
12
+ def field(relation, name)
13
+ if relation.is_a?(Symbol)
14
+ relation = relation.to_s
15
+ end
16
+
17
+ if name.is_a?(Symbol)
18
+ name = name.to_s
19
+ end
20
+
21
+ _field(relation, name)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ module Enquo
2
+ module RootKey
3
+ class Static
4
+ def self.new(k)
5
+ unless k.is_a?(String)
6
+ raise ArgumentError, "An Enquo static root key must be passed a string"
7
+ end
8
+
9
+ key = if k.encoding == Encoding::BINARY
10
+ unless k.bytesize == 32
11
+ raise ArgumentError, "An Enquo static root key must be a 32 byte binary string"
12
+ end
13
+
14
+ k
15
+ else
16
+ unless k =~ /\A\h{64}\z/
17
+ raise ArgumentError, "An Enquo static root key must be a 64 byte hex string"
18
+ end
19
+
20
+ [k].pack("H*")
21
+ end
22
+
23
+ _new(key)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1 @@
1
+ require_relative "./root_key/static"
data/lib/enquo.rb ADDED
@@ -0,0 +1,18 @@
1
+ module Enquo
2
+ class Error < StandardError; end
3
+ end
4
+
5
+ begin
6
+ RUBY_VERSION =~ /(\d+\.\d+)/
7
+ require_relative "./#{$1}/enquo"
8
+ rescue LoadError
9
+ begin
10
+ require_relative "./enquo.#{RbConfig::CONFIG["DLEXT"]}"
11
+ rescue LoadError
12
+ raise LoadError, "Failed to load enquo.#{RbConfig::CONFIG["DLEXT"]}; either it hasn't been built, or was built incorrectly for your system"
13
+ end
14
+ end
15
+
16
+ require_relative "./enquo/root"
17
+ require_relative "./enquo/root_key"
18
+ require_relative "./enquo/field"
metadata ADDED
@@ -0,0 +1,198 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enquo-core
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Matt Palmer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-10-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: github-release
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake-compiler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake-compiler-dock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rb_sys
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.1'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: redcarpet
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description:
154
+ email:
155
+ - matt@enquo.org
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - ".gitignore"
161
+ - enquo-core.gemspec
162
+ - ext/enquo/.gitignore
163
+ - ext/enquo/Cargo.lock
164
+ - ext/enquo/Cargo.toml
165
+ - ext/enquo/extconf.rb
166
+ - ext/enquo/src/lib.rs
167
+ - lib/enquo.rb
168
+ - lib/enquo/field.rb
169
+ - lib/enquo/root.rb
170
+ - lib/enquo/root_key.rb
171
+ - lib/enquo/root_key/static.rb
172
+ homepage: https://enquo.org/active_enquo
173
+ licenses: []
174
+ metadata:
175
+ homepage_uri: https://enquo.org/active_enquo
176
+ source_code_uri: https://github.com/enquo/enquo-core
177
+ changelog_uri: https://github.com/enquo/enquo-core/releases
178
+ bug_tracker_uri: https://github.com/enquo/enquo-core/issues
179
+ post_install_message:
180
+ rdoc_options: []
181
+ require_paths:
182
+ - lib
183
+ required_ruby_version: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: 2.7.0
188
+ required_rubygems_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ requirements: []
194
+ rubygems_version: 3.1.6
195
+ signing_key:
196
+ specification_version: 4
197
+ summary: Core library for encrypted querying operations
198
+ test_files: []