enveloperb 0.1.1-x86_64-linux
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 +7 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/CONTRIBUTING.md +10 -0
- data/Cargo.toml +17 -0
- data/LICENCE +674 -0
- data/README.md +126 -0
- data/enveloperb.gemspec +40 -0
- data/ext/Rakefile +5 -0
- data/lib/enveloperb/awskms.rb +58 -0
- data/lib/enveloperb/encrypted_record.rb +31 -0
- data/lib/enveloperb/simple.rb +35 -0
- data/lib/enveloperb.rb +9 -0
- data/src/lib.rs +195 -0
- data/target/release/deps/libasync_trait-d616c5275efb3885.so +0 -0
- data/target/release/deps/libenveloperb.so +0 -0
- data/target/release/deps/libfutures_macro-0f8ad5ae6e34b161.so +0 -0
- data/target/release/deps/libpin_project_internal-ef8d149cf28b24bc.so +0 -0
- data/target/release/deps/libserde_derive-3653e4229ae528ef.so +0 -0
- data/target/release/deps/libthiserror_impl-c49e7233e0f6f247.so +0 -0
- data/target/release/deps/libtracing_attributes-ae844bddcb3f978b.so +0 -0
- data/target/release/libenveloperb.so +0 -0
- metadata +223 -0
data/README.md
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
Ruby bindings for the [envelopers](https://github.com/cipherstash/enveloper) envelope encryption library.
|
2
|
+
|
3
|
+
Envelope encryption is a mechanism by which a plaintext is encrypted into a ciphertext using a single-use key (known as the "data key"), and then that data key is encrypted with a second key (known as the "wrapping key", or "key-encryption key", or sometimes "KEK").
|
4
|
+
The encrypted data key is then stored alongside the ciphertext, so that all that is needed for decryption is the key-encryption key and the ciphertext/encrypted data key bundle.
|
5
|
+
|
6
|
+
The benefits of this mechanism are:
|
7
|
+
|
8
|
+
1. Compromise of the key used to encrypt a plaintext (say, by short-term penetration of a process performing decryption) does not compromise all data;
|
9
|
+
|
10
|
+
2. The key-encryption key can be stored securely and entirely separate from any plaintext data, in an HSM (Hardware Security Module) or other hardened environment;
|
11
|
+
|
12
|
+
3. The entity operating the key-encryption key environment never has (direct) access to plaintexts (as would be the case if you sent the plaintext to the HSM for encryption);
|
13
|
+
|
14
|
+
4. Large volumes of data can be encrypted efficiently on a local machine, and only the small data key needs to be sent over a slow network link to be encrypted.
|
15
|
+
|
16
|
+
As you can see, the benefits of envelope encryption mostly center around environments where KEK material is HSM-managed.
|
17
|
+
Except for testing purposes, it is not common to use envelope encryption in situations where the KEK is provided directly to the envelope encryption system.
|
18
|
+
|
19
|
+
|
20
|
+
# Installation
|
21
|
+
|
22
|
+
In order to build the `enveloperb` gem, you must have Rust 1.31.0 or later installed.
|
23
|
+
On an ARM-based platform, you must use Rust nightly, for SIMD intrinsics support.
|
24
|
+
|
25
|
+
With that available, you should be able to install it like any other gem:
|
26
|
+
|
27
|
+
gem install enveloperb
|
28
|
+
|
29
|
+
There's also the wonders of [the Gemfile](http://bundler.io):
|
30
|
+
|
31
|
+
gem 'enveloperb'
|
32
|
+
|
33
|
+
If you're the sturdy type that likes to run from git:
|
34
|
+
|
35
|
+
bundle install
|
36
|
+
rake install
|
37
|
+
|
38
|
+
Or, if you've eschewed the convenience of Rubygems entirely, then you
|
39
|
+
presumably know what to do already.
|
40
|
+
|
41
|
+
|
42
|
+
# Usage
|
43
|
+
|
44
|
+
First off, load the library:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
require "enveloperb"
|
48
|
+
```
|
49
|
+
|
50
|
+
Then create a new cryptography engine, using your choice of wrapping key provider.
|
51
|
+
For this example, we'll use the "simple" key provider, which takes a 16 byte *binary* string as the key-encryption-key.
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
require "securerandom"
|
55
|
+
kek = SecureRandom.bytes(16)
|
56
|
+
|
57
|
+
engine = Enveloperb::Simple.new(kek)
|
58
|
+
```
|
59
|
+
|
60
|
+
Now you can encrypt whatever data you like:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
ct = engine.encrypt("This is a super-important secret")
|
64
|
+
```
|
65
|
+
|
66
|
+
This produces an `Enveloperb::EncryptedRecord`, which can be turned into a (binary) string very easily:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
File.binwrite("/tmp/ciphertext", ct1.to_s)
|
70
|
+
```
|
71
|
+
|
72
|
+
To turn a binary string back into a ciphertext, just create a new `EncryptedRecord` with it:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
ct_new = Enveloperb::EncryptedRecord.new(File.binread("/tmp/ciphertext"))
|
76
|
+
```
|
77
|
+
|
78
|
+
Then you can decrypt it again:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
engine.decrypt(ct_new) # => "This ia super-important secret"
|
82
|
+
```
|
83
|
+
|
84
|
+
|
85
|
+
## AWS KMS Key Provider
|
86
|
+
|
87
|
+
When using a locally-managed wrapping key, the benefits over direct encryption aren't significant.
|
88
|
+
The real benefits come when using a secured key provider for the wrapping key, such as AWS KMS.
|
89
|
+
|
90
|
+
To use an AWS KMS key as the wrapping key, you use an `Enveloperb::AWSKMS` instance as the cryptography engine, like so:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
engine = Enveloperb::AWSKMS.key(keyid, profile: "example", region: "xx-example-1", credentials: { ... })
|
94
|
+
```
|
95
|
+
|
96
|
+
While `keyid` is mandatory, `profile`, `region` and `credentials` are all optional.
|
97
|
+
If not specified, they will be extracted from the usual places (environment, metadata service, etc) as specified in [the AWS SDK for Rust documentation](https://docs.aws.amazon.com/sdk-for-rust/latest/dg/credentials.html).
|
98
|
+
Yes, the Rust SDK -- `enveloperb` is just a thin wrapper around a Rust library.
|
99
|
+
We are truly living in the future.
|
100
|
+
|
101
|
+
Once you have your AWS KMS cryptography engine, its usage is the familiar `#encrypt` / `#decrypt` cycle.
|
102
|
+
|
103
|
+
|
104
|
+
# Contributing
|
105
|
+
|
106
|
+
Please see [CONTRIBUTING.md](CONTRIBUTING.md).
|
107
|
+
|
108
|
+
|
109
|
+
# Licence
|
110
|
+
|
111
|
+
Unless otherwise stated, everything in this repo is covered by the following
|
112
|
+
copyright notice:
|
113
|
+
|
114
|
+
Copyright (C) 2022 CipherStash Inc.
|
115
|
+
|
116
|
+
This program is free software: you can redistribute it and/or modify it
|
117
|
+
under the terms of the GNU General Public License version 3, as
|
118
|
+
published by the Free Software Foundation.
|
119
|
+
|
120
|
+
This program is distributed in the hope that it will be useful,
|
121
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
122
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
123
|
+
GNU General Public License for more details.
|
124
|
+
|
125
|
+
You should have received a copy of the GNU General Public License
|
126
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/enveloperb.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
begin
|
2
|
+
require 'git-version-bump'
|
3
|
+
rescue LoadError
|
4
|
+
nil
|
5
|
+
end
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "enveloperb"
|
9
|
+
|
10
|
+
s.version = GVB.version rescue "0.0.0.1.NOGVB"
|
11
|
+
s.date = GVB.date rescue Time.now.strftime("%Y-%m-%d")
|
12
|
+
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
|
15
|
+
s.summary = "Ruby bindings for the envelopers envelope encryption library"
|
16
|
+
|
17
|
+
s.authors = ["Matt Palmer"]
|
18
|
+
s.email = ["matt@cipherstash.com"]
|
19
|
+
s.homepage = "https://github.com/cipherstash/enveloperb"
|
20
|
+
|
21
|
+
s.files = `git ls-files -z`.split("\0").reject { |f| f =~ /^(\.|G|spec|Rakefile)/ }
|
22
|
+
|
23
|
+
s.extensions = ["ext/Rakefile"]
|
24
|
+
s.require_paths = ["lib", "target"]
|
25
|
+
|
26
|
+
s.required_ruby_version = ">= 2.7.0"
|
27
|
+
|
28
|
+
s.add_runtime_dependency "rutie", "~> 0.0.4"
|
29
|
+
|
30
|
+
s.add_development_dependency 'bundler'
|
31
|
+
s.add_development_dependency 'gem-compiler'
|
32
|
+
s.add_development_dependency 'github-release'
|
33
|
+
s.add_development_dependency 'guard-rspec'
|
34
|
+
s.add_development_dependency 'rake', '~> 10.4', '>= 10.4.2'
|
35
|
+
s.add_development_dependency 'rb-inotify', '~> 0.9'
|
36
|
+
s.add_development_dependency 'redcarpet'
|
37
|
+
s.add_development_dependency 'rspec'
|
38
|
+
s.add_development_dependency 'simplecov'
|
39
|
+
s.add_development_dependency 'yard'
|
40
|
+
end
|
data/ext/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
module Enveloperb
|
2
|
+
# An Enveloperb cryptography engine using AWS KMS as a wrapping key provider.
|
3
|
+
#
|
4
|
+
class AWSKMS
|
5
|
+
def self.new(keyid, aws_access_key_id: nil, aws_secret_access_key: nil, aws_session_token: nil, aws_region: nil)
|
6
|
+
unless keyid.is_a?(String) && keyid.encoding == Encoding::find("UTF-8") && keyid.valid_encoding?
|
7
|
+
raise ArgumentError, "Key ID must be a valid UTF-8 string"
|
8
|
+
end
|
9
|
+
|
10
|
+
unless aws_access_key_id.nil? && aws_secret_access_key.nil? && aws_session_token.nil? && aws_region.nil?
|
11
|
+
validate_string(aws_access_key_id, :aws_access_key_id)
|
12
|
+
validate_string(aws_secret_access_key, :aws_secret_access_key)
|
13
|
+
validate_string(aws_region, :aws_region)
|
14
|
+
validate_string(aws_session_token, :aws_session_token, allow_nil: true)
|
15
|
+
end
|
16
|
+
|
17
|
+
_new(
|
18
|
+
keyid,
|
19
|
+
{
|
20
|
+
access_key_id: aws_access_key_id,
|
21
|
+
secret_access_key: aws_secret_access_key,
|
22
|
+
session_token: aws_session_token,
|
23
|
+
region: aws_region,
|
24
|
+
}
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def encrypt(s)
|
29
|
+
unless s.is_a?(String)
|
30
|
+
raise ArgumentError, "Can only encrypt strings"
|
31
|
+
end
|
32
|
+
|
33
|
+
_encrypt(s)
|
34
|
+
end
|
35
|
+
|
36
|
+
def decrypt(er)
|
37
|
+
unless er.is_a?(EncryptedRecord)
|
38
|
+
raise ArgumentError, "Can only decrypt EncryptedRecord objects; you can make one from a string with EncryptedRecord.new"
|
39
|
+
end
|
40
|
+
|
41
|
+
_decrypt(er)
|
42
|
+
end
|
43
|
+
|
44
|
+
class << self
|
45
|
+
private
|
46
|
+
|
47
|
+
def validate_string(s, var, allow_nil: false)
|
48
|
+
if s.nil? && !allow_nil
|
49
|
+
raise ArgumentError, "#{var.inspect} option to Enveloperb::AWSKMS.new() cannot be nil"
|
50
|
+
end
|
51
|
+
|
52
|
+
unless s.is_a?(String) && s.encoding == Encoding.find("UTF-8") && s.valid_encoding?
|
53
|
+
raise ArgumentError, "#{var.inspect} option passed to Enveloperb::AWSKMS.new() must be a valid UTF-8 string"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Enveloperb
|
2
|
+
# An envelope encrypted record.
|
3
|
+
class EncryptedRecord
|
4
|
+
# Create an encrypted record from a serialized form.
|
5
|
+
#
|
6
|
+
# Encrypted records can be serialized (using #to_s), and then deserialized by passing them into this constructor.
|
7
|
+
#
|
8
|
+
# @param s [String] the serialized encrypted record.
|
9
|
+
# This must be a `BINARY` encoded string.
|
10
|
+
#
|
11
|
+
# @raises [ArgumentError] if something other than a binary string is provided, or if the string passed as the serialized encrypted record is not valid.
|
12
|
+
#
|
13
|
+
def self.new(s)
|
14
|
+
unless s.is_a?(String) && s.encoding == Encoding::BINARY
|
15
|
+
raise ArgumentError, "Serialized encrypted record must be a binary string"
|
16
|
+
end
|
17
|
+
|
18
|
+
_new(s)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Serialize an encrypted record into a string.
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
#
|
25
|
+
# @raise [RuntimeError] if something goes spectacularly wrong with the serialization process.
|
26
|
+
#
|
27
|
+
def to_s
|
28
|
+
_serialize
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Enveloperb
|
2
|
+
# An Enveloperb cryptography engine using an unprotected string as the wrapping key.
|
3
|
+
#
|
4
|
+
# @note this class is not intended for general-purpose use.
|
5
|
+
#
|
6
|
+
class Simple
|
7
|
+
def self.new(k)
|
8
|
+
unless k.is_a?(String) && k.encoding == Encoding::BINARY
|
9
|
+
raise ArgumentError, "Key must be a binary string"
|
10
|
+
end
|
11
|
+
|
12
|
+
unless k.bytesize == 16
|
13
|
+
raise ArgumentError, "Key must be 16 bytes"
|
14
|
+
end
|
15
|
+
|
16
|
+
_new(k)
|
17
|
+
end
|
18
|
+
|
19
|
+
def encrypt(s)
|
20
|
+
unless s.is_a?(String)
|
21
|
+
raise ArgumentError, "Can only encrypt strings"
|
22
|
+
end
|
23
|
+
|
24
|
+
_encrypt(s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def decrypt(er)
|
28
|
+
unless er.is_a?(EncryptedRecord)
|
29
|
+
raise ArgumentError, "Can only decrypt EncryptedRecord objects; you can make one from a string with EncryptedRecord.new"
|
30
|
+
end
|
31
|
+
|
32
|
+
_decrypt(er)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/enveloperb.rb
ADDED
data/src/lib.rs
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
#[macro_use]
|
2
|
+
extern crate rutie;
|
3
|
+
|
4
|
+
#[macro_use]
|
5
|
+
extern crate lazy_static;
|
6
|
+
|
7
|
+
// I have deliberately not used more-specific symbols inside the aws_* crates because the
|
8
|
+
// names are quite generic, and in the near future when we have more providers, we'll
|
9
|
+
// almost certainly end up with naming clashes.
|
10
|
+
use aws_config;
|
11
|
+
use aws_sdk_kms;
|
12
|
+
use aws_types;
|
13
|
+
use enveloper::{EncryptedRecord, EnvelopeCipher, KMSKeyProvider, SimpleKeyProvider};
|
14
|
+
use std::borrow::Cow;
|
15
|
+
use tokio::runtime::Runtime;
|
16
|
+
use rutie::{Class, Encoding, Hash, Module, Object, RString, Symbol, VerifiedObject, VM};
|
17
|
+
|
18
|
+
module!(Enveloperb);
|
19
|
+
class!(EnveloperbSimple);
|
20
|
+
class!(EnveloperbAWSKMS);
|
21
|
+
class!(EnveloperbEncryptedRecord);
|
22
|
+
|
23
|
+
impl VerifiedObject for EnveloperbEncryptedRecord {
|
24
|
+
fn is_correct_type<T: Object>(object: &T) -> bool {
|
25
|
+
let klass = Module::from_existing("Enveloperb").get_nested_class("EncryptedRecord");
|
26
|
+
klass.case_equals(object)
|
27
|
+
}
|
28
|
+
|
29
|
+
fn error_message() -> &'static str {
|
30
|
+
"Error converting to Enveloperb::EncryptedRecord"
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
pub struct SimpleCipher {
|
35
|
+
cipher: EnvelopeCipher<SimpleKeyProvider>,
|
36
|
+
runtime: Runtime,
|
37
|
+
}
|
38
|
+
|
39
|
+
pub struct AWSKMSCipher {
|
40
|
+
cipher: EnvelopeCipher<KMSKeyProvider>,
|
41
|
+
runtime: Runtime,
|
42
|
+
}
|
43
|
+
|
44
|
+
wrappable_struct!(SimpleCipher, SimpleCipherWrapper, SIMPLE_CIPHER_WRAPPER);
|
45
|
+
wrappable_struct!(AWSKMSCipher, AWSKMSCipherWrapper, AWSKMS_CIPHER_WRAPPER);
|
46
|
+
wrappable_struct!(EncryptedRecord, EncryptedRecordWrapper, ENCRYPTED_RECORD_WRAPPER);
|
47
|
+
|
48
|
+
methods!(
|
49
|
+
EnveloperbSimple,
|
50
|
+
rbself,
|
51
|
+
|
52
|
+
fn enveloperb_simple_new(rbkey: RString) -> EnveloperbSimple {
|
53
|
+
let mut key: [u8; 16] = Default::default();
|
54
|
+
|
55
|
+
key.clone_from_slice(rbkey.unwrap().to_bytes_unchecked());
|
56
|
+
|
57
|
+
let provider = SimpleKeyProvider::init(key);
|
58
|
+
let cipher = EnvelopeCipher::init(provider);
|
59
|
+
|
60
|
+
let klass = Module::from_existing("Enveloperb").get_nested_class("Simple");
|
61
|
+
return klass.wrap_data(SimpleCipher{ cipher: cipher, runtime: Runtime::new().unwrap() }, &*SIMPLE_CIPHER_WRAPPER);
|
62
|
+
}
|
63
|
+
|
64
|
+
fn enveloperb_simple_encrypt(rbtext: RString) -> EnveloperbEncryptedRecord {
|
65
|
+
let cipher = rbself.get_data(&*SIMPLE_CIPHER_WRAPPER);
|
66
|
+
let er_r = cipher.runtime.block_on(async {
|
67
|
+
cipher.cipher.encrypt(rbtext.unwrap().to_bytes_unchecked()).await
|
68
|
+
});
|
69
|
+
let er = er_r.map_err(|e| VM::raise(Class::from_existing("RuntimeError"), &format!("Failed to perform encryption: {:?}", e))).unwrap();
|
70
|
+
|
71
|
+
let klass = Module::from_existing("Enveloperb").get_nested_class("EncryptedRecord");
|
72
|
+
return klass.wrap_data(er, &*ENCRYPTED_RECORD_WRAPPER);
|
73
|
+
}
|
74
|
+
|
75
|
+
fn enveloperb_simple_decrypt(rbrecord: EnveloperbEncryptedRecord) -> RString {
|
76
|
+
let cipher = rbself.get_data(&*SIMPLE_CIPHER_WRAPPER);
|
77
|
+
let e_record = rbrecord.unwrap();
|
78
|
+
let record = e_record.get_data(&*ENCRYPTED_RECORD_WRAPPER);
|
79
|
+
|
80
|
+
let vec_r = cipher.runtime.block_on(async {
|
81
|
+
cipher.cipher.decrypt(record).await
|
82
|
+
});
|
83
|
+
let vec = vec_r.map_err(|e| VM::raise(Class::from_existing("RuntimeError"), &format!("Failed to perform decryption: {:?}", e))).unwrap();
|
84
|
+
|
85
|
+
return RString::from_bytes(&vec, &Encoding::find("BINARY").unwrap());
|
86
|
+
}
|
87
|
+
);
|
88
|
+
|
89
|
+
methods!(
|
90
|
+
EnveloperbAWSKMS,
|
91
|
+
rbself,
|
92
|
+
|
93
|
+
fn enveloperb_awskms_new(rbkey: RString, rbcreds: Hash) -> EnveloperbAWSKMS {
|
94
|
+
let raw_creds = rbcreds.unwrap();
|
95
|
+
let rt = Runtime::new().unwrap();
|
96
|
+
|
97
|
+
let kmsclient_config = if raw_creds.at(&Symbol::new("access_key_id")).is_nil() {
|
98
|
+
rt.block_on(async {
|
99
|
+
aws_config::load_from_env().await
|
100
|
+
})
|
101
|
+
} else {
|
102
|
+
let rbregion = raw_creds.at(&Symbol::new("region")).try_convert_to::<RString>().unwrap();
|
103
|
+
let region = Some(aws_types::region::Region::new(rbregion.to_str().to_owned()));
|
104
|
+
|
105
|
+
let rbkey_id = raw_creds.at(&Symbol::new("access_key_id")).try_convert_to::<RString>().unwrap();
|
106
|
+
let key_id = rbkey_id.to_str();
|
107
|
+
|
108
|
+
let rbsecret = raw_creds.at(&Symbol::new("secret_access_key")).try_convert_to::<RString>().unwrap();
|
109
|
+
let secret = rbsecret.to_str();
|
110
|
+
|
111
|
+
let token = match raw_creds.at(&Symbol::new("session_token")).try_convert_to::<RString>() {
|
112
|
+
Ok(str) => Some(str.to_string()),
|
113
|
+
Err(_) => None
|
114
|
+
};
|
115
|
+
|
116
|
+
let aws_creds = aws_types::Credentials::from_keys(key_id, secret, token);
|
117
|
+
let creds_provider = aws_types::credentials::SharedCredentialsProvider::new(aws_creds);
|
118
|
+
|
119
|
+
aws_types::sdk_config::SdkConfig::builder().region(region).credentials_provider(creds_provider).build()
|
120
|
+
};
|
121
|
+
|
122
|
+
let kmsclient = aws_sdk_kms::Client::new(&kmsclient_config);
|
123
|
+
let provider = KMSKeyProvider::new(kmsclient, rbkey.unwrap().to_string());
|
124
|
+
let cipher = EnvelopeCipher::init(provider);
|
125
|
+
|
126
|
+
let klass = Module::from_existing("Enveloperb").get_nested_class("AWSKMS");
|
127
|
+
return klass.wrap_data(AWSKMSCipher{ cipher: cipher, runtime: rt }, &*AWSKMS_CIPHER_WRAPPER);
|
128
|
+
}
|
129
|
+
|
130
|
+
fn enveloperb_awskms_encrypt(rbtext: RString) -> EnveloperbEncryptedRecord {
|
131
|
+
let cipher = rbself.get_data(&*AWSKMS_CIPHER_WRAPPER);
|
132
|
+
let er_r = cipher.runtime.block_on(async {
|
133
|
+
cipher.cipher.encrypt(rbtext.unwrap().to_bytes_unchecked()).await
|
134
|
+
});
|
135
|
+
let er = er_r.map_err(|e| VM::raise(Class::from_existing("RuntimeError"), &format!("Failed to perform encryption: {:?}", e))).unwrap();
|
136
|
+
|
137
|
+
let klass = Module::from_existing("Enveloperb").get_nested_class("EncryptedRecord");
|
138
|
+
return klass.wrap_data(er, &*ENCRYPTED_RECORD_WRAPPER);
|
139
|
+
}
|
140
|
+
|
141
|
+
fn enveloperb_awskms_decrypt(rbrecord: EnveloperbEncryptedRecord) -> RString {
|
142
|
+
let cipher = rbself.get_data(&*AWSKMS_CIPHER_WRAPPER);
|
143
|
+
let e_record = rbrecord.unwrap();
|
144
|
+
let record = e_record.get_data(&*ENCRYPTED_RECORD_WRAPPER);
|
145
|
+
|
146
|
+
let vec_r = cipher.runtime.block_on(async {
|
147
|
+
cipher.cipher.decrypt(record).await
|
148
|
+
});
|
149
|
+
let vec = vec_r.map_err(|e| VM::raise(Class::from_existing("RuntimeError"), &format!("Failed to perform decryption: {:?}", e))).unwrap();
|
150
|
+
|
151
|
+
return RString::from_bytes(&vec, &Encoding::find("BINARY").unwrap());
|
152
|
+
}
|
153
|
+
);
|
154
|
+
|
155
|
+
methods!(
|
156
|
+
EnveloperbEncryptedRecord,
|
157
|
+
rbself,
|
158
|
+
|
159
|
+
fn enveloperb_encrypted_record_new(serialized_record: RString) -> EnveloperbEncryptedRecord {
|
160
|
+
let s = serialized_record.unwrap().to_vec_u8_unchecked();
|
161
|
+
let ct = EncryptedRecord::from_vec(s).map_err(|e| VM::raise(Class::from_existing("ArgumentError"), &format!("Failed to decode encrypted record: {:?}", e))).unwrap();
|
162
|
+
|
163
|
+
let klass = Module::from_existing("Enveloperb").get_nested_class("EncryptedRecord");
|
164
|
+
return klass.wrap_data(ct, &*ENCRYPTED_RECORD_WRAPPER);
|
165
|
+
}
|
166
|
+
|
167
|
+
fn enveloperb_encrypted_record_serialize() -> RString {
|
168
|
+
let record = rbself.get_data(&*ENCRYPTED_RECORD_WRAPPER);
|
169
|
+
|
170
|
+
return RString::from_bytes(&record.to_vec().map_err(|e| VM::raise(Class::from_existing("RuntimeError"), &format!("Failed to encode encrypted record: {:?}", e))).unwrap(), &Encoding::find("BINARY").unwrap());
|
171
|
+
}
|
172
|
+
);
|
173
|
+
|
174
|
+
#[allow(non_snake_case)]
|
175
|
+
#[no_mangle]
|
176
|
+
pub extern "C" fn Init_enveloperb() {
|
177
|
+
Module::from_existing("Enveloperb").define(|envmod| {
|
178
|
+
envmod.define_nested_class("Simple", None).define(|klass| {
|
179
|
+
klass.singleton_class().def_private("_new", enveloperb_simple_new);
|
180
|
+
klass.def_private("_encrypt", enveloperb_simple_encrypt);
|
181
|
+
klass.def_private("_decrypt", enveloperb_simple_decrypt);
|
182
|
+
});
|
183
|
+
|
184
|
+
envmod.define_nested_class("AWSKMS", None).define(|klass| {
|
185
|
+
klass.singleton_class().def_private("_new", enveloperb_awskms_new);
|
186
|
+
klass.def_private("_encrypt", enveloperb_awskms_encrypt);
|
187
|
+
klass.def_private("_decrypt", enveloperb_awskms_decrypt);
|
188
|
+
});
|
189
|
+
|
190
|
+
envmod.define_nested_class("EncryptedRecord", None).define(|klass| {
|
191
|
+
klass.singleton_class().def_private("_new", enveloperb_encrypted_record_new);
|
192
|
+
klass.def_private("_serialize", enveloperb_encrypted_record_serialize);
|
193
|
+
});
|
194
|
+
});
|
195
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|