asherah 0.1.0.beta.1-aarch64-linux → 0.3.0-aarch64-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: 34d923ebd19903e064dbb021dc188b42a20e3ea26dfc387b8eebd27faecf8124
4
- data.tar.gz: 9ef0178a5b6d440a40ce470097e73b4c88b286ed5ef5743b14438554da56ced2
3
+ metadata.gz: ef6d062e4ed676c66a72dba500d4376801b33199da28e69eb2e62f34dae62a40
4
+ data.tar.gz: 2909ca407f9d1954e68232122373baa30c3a33095d65b890d996061902bcc136
5
5
  SHA512:
6
- metadata.gz: 2a66d75b94988ec99bae8c7f9563dbfa3be4ec811926758a51f878b584efe971986c1cb5ac37b42bd54724491d343541ac9da64686b64d09fd4500a193109093
7
- data.tar.gz: b408f29b7332e26fdb42d38486048a66769f0ff0fa2972a11eabf9f68f59b367cf108f3430f8f73cb4a198f9e0333ae4f999cc9d4f4e7b81af022e4f5a725cb8
6
+ metadata.gz: 888f1d7c7534919bd79c70def643abd712e01b06808a78b4fc7017e0a0e0e841c267921635cf8beacf0bc7e99b986aa64e7258d2313728c02784c878d0cc5502
7
+ data.tar.gz: 18d76b1c06ed638fa06f15dbfbed49cca82c2ae19d31d0c5ff1968da854dce4b43b724cc267638e422c02db0b1692fd255deb360531418ac571e30b7a91a6d07
data/.rubocop.yml CHANGED
@@ -4,6 +4,7 @@ AllCops:
4
4
  SuggestExtensions: false
5
5
  Exclude:
6
6
  - 'vendor/**/*' # Github Actions
7
+ - 'tmp/**/*'
7
8
 
8
9
  Layout/LineLength:
9
10
  Max: 120
@@ -26,14 +27,8 @@ Style/MultilineBlockChain:
26
27
  Style/BlockDelimiters:
27
28
  Enabled: false
28
29
 
29
- Style/HashAsLastArrayItem:
30
- Enabled: false
31
-
32
30
  Metrics/AbcSize:
33
31
  Enabled: false
34
32
 
35
- Metrics/ParameterLists:
36
- Enabled: false
37
-
38
- Metrics/ModuleLength:
33
+ Style/GuardClause:
39
34
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0] - 2022-03-02
3
+ ## [0.3.0] - 2022-03-22
4
4
 
5
- - Initial release
5
+ - Free up cobhan buffers after encrypt/decrypt to prevent growing heap memory
6
+ - Use local `estimate_buffer` calculation instead of FFI call
7
+ - Upgrade to use asherah-cobhan v0.4.3
8
+
9
+ ## [0.2.0] - 2022-03-21
10
+
11
+ - Implement versioning for asherah-cobhan binaries
12
+ - Upgrade to use asherah-cobhan v0.3.1
13
+ - Add BadConfig error and expose error codes
14
+ - Remove DRR methods and use JSON exclusively
15
+ - Cross language testing using Asherah Go
16
+
17
+ ## [0.1.0] - 2022-03-14
18
+
19
+ - First official release
20
+
21
+ ## [0.1.0.beta2] - 2022-03-14
22
+
23
+ - Add smoke tests for native gems
24
+ - Change to use `SetupJson` instead of `Setup`
25
+ - Update config options to make them consistent with Asherah Go
26
+ - Add `shutdown`
27
+ - Add `encrypt_to_json` and `decrypt_from_json`
28
+ - Add coverage report
29
+
30
+ ## [0.1.0.beta1] - 2022-03-07
31
+
32
+ - Initial proof of concept
data/Gemfile CHANGED
@@ -7,6 +7,4 @@ gemspec
7
7
 
8
8
  gem 'rake', '~> 13.0'
9
9
 
10
- gem 'rspec', '~> 3.0'
11
-
12
- gem 'rubocop', '~> 1.21'
10
+ gem 'cucumber', '~> 7.1.0'
data/README.md CHANGED
@@ -1,8 +1,14 @@
1
1
  # Asherah
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/asherah`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Asherah is a Ruby wrapper around [Asherah Go](https://github.com/godaddy/asherah) application-layer encryption SDK that provides advanced encryption features and defense in depth against compromise. It uses a technique known as "envelope encryption" and supports cloud-agnostic data storage and key management.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ Check out the following documentation to get more familiar with its concepts:
6
+
7
+ - [Design and Architecture](https://github.com/godaddy/asherah/blob/master/docs/DesignAndArchitecture.md)
8
+ - [Key Caching](https://github.com/godaddy/asherah/blob/master/docs/KeyCaching.md)
9
+ - [Key Management Service](https://github.com/godaddy/asherah/blob/master/docs/KeyManagementService.md)
10
+ - [Metastore](https://github.com/godaddy/asherah/blob/master/docs/Metastore.md)
11
+ - [System Requirements](https://github.com/godaddy/asherah/blob/master/docs/SystemRequirements.md)
6
12
 
7
13
  ## Installation
8
14
 
@@ -12,17 +18,44 @@ Add this line to your application's Gemfile:
12
18
  gem 'asherah'
13
19
  ```
14
20
 
15
- And then execute:
16
-
17
- $ bundle install
21
+ ```bash
22
+ bundle install
23
+ ```
18
24
 
19
25
  Or install it yourself as:
20
26
 
21
- $ gem install asherah
27
+ ```bash
28
+ gem install asherah
29
+ ```
22
30
 
23
31
  ## Usage
24
32
 
25
- TODO: Write usage instructions here
33
+ Configure Asherah:
34
+
35
+ ```ruby
36
+ Asherah.configure do |config|
37
+ config.kms = 'static'
38
+ config.metastore = 'memory'
39
+ config.service_name = 'service'
40
+ config.product_id = 'product'
41
+ end
42
+ ```
43
+
44
+ Encrypt some data for a `partition_id`
45
+
46
+ ```ruby
47
+ partition_id = 'user_1'
48
+ data = 'Some PII data'
49
+ data_row_record_json = Asherah.encrypt(partition_id, data)
50
+ puts data_row_record_json
51
+ ```
52
+
53
+ Decrypt `data_row_record_json`
54
+
55
+ ```ruby
56
+ decrypted_data = Asherah.decrypt(partition_id, data_row_record_json)
57
+ puts decrypted_data
58
+ ```
26
59
 
27
60
  ## Development
28
61
 
@@ -32,8 +65,19 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
65
 
33
66
  ## Contributing
34
67
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/asherah.
68
+ Bug reports and pull requests are welcome on GitHub at https://github.com/godaddy/asherah-ruby.
69
+
70
+ ## Releasing new gem version
71
+
72
+ ```
73
+ # Create and push a version tag
74
+ git tag -a v$(rake version) -m "Version $(rake version)"
75
+ git push origin v$(rake version)
76
+
77
+ # Create a release in Github to trigger .github/workflows/publish.yml workflow
78
+ echo "Version $(rake version)"
79
+ ```
36
80
 
37
81
  ## License
38
82
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
83
+ The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
data/Rakefile CHANGED
@@ -3,7 +3,6 @@
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
5
  require 'rubygems/package'
6
- require "open-uri"
7
6
 
8
7
  RSpec::Core::RakeTask.new(:spec)
9
8
 
@@ -13,12 +12,26 @@ RuboCop::RakeTask.new
13
12
 
14
13
  task default: %i[spec rubocop]
15
14
 
15
+ ASHERAH_BIN = 'bin/download-asherah.sh'
16
16
  DISTRIBUTIONS = {
17
17
  'x86_64-linux' => ['libasherah-x64.so'],
18
18
  'x86_64-darwin' => ['libasherah-x64.dylib'],
19
19
  'aarch64-linux' => ['libasherah-arm64.so'],
20
20
  'arm64-darwin' => ['libasherah-arm64.dylib']
21
- }
21
+ }.freeze
22
+
23
+ def current_filename
24
+ @current_filename ||=
25
+ begin
26
+ require 'cobhan'
27
+ Class.new.extend(Cobhan).library_file_name('libasherah')
28
+ end
29
+ end
30
+
31
+ def current_platform
32
+ @distribution ||= DISTRIBUTIONS.detect { |_k, v| v.include?(current_filename) }
33
+ @distribution.first
34
+ end
22
35
 
23
36
  def native_build(platform, native_files)
24
37
  puts "Building gem for #{platform}"
@@ -32,14 +45,14 @@ def native_build(platform, native_files)
32
45
 
33
46
  # Copy files to tmp gem dir
34
47
  gemspec = Bundler.load_gemspec('asherah.gemspec')
35
- gemspec.files.each do |file|
48
+ (gemspec.files + [ASHERAH_BIN]).each do |file|
36
49
  dir = File.dirname(file)
37
50
  filename = File.basename(file)
38
51
  FileUtils.mkdir_p(File.join(tmp_gem_dir, dir))
39
52
  FileUtils.copy_file(file, File.join(tmp_gem_dir, dir, filename))
40
53
  end
41
54
 
42
- # Set platform for native gem build and remove extentions
55
+ # Set platform for native gem build
43
56
  gemspec.platform = Gem::Platform.new(platform)
44
57
 
45
58
  native_dir = 'lib/asherah/native'
@@ -47,30 +60,29 @@ def native_build(platform, native_files)
47
60
  FileUtils.mkdir_p(native_dir)
48
61
  native_files.each do |native_file|
49
62
  native_file_path = File.join(native_dir, native_file)
50
- gemspec.files << native_file_path
51
63
 
52
- URI.open(native_file_path, 'wb') do |file|
53
- url = "https://github.com/godaddy/asherah-cobhan/releases/download/current/#{native_file}"
54
- puts "Downloading #{url}"
55
- file << URI.open(url).read
56
- end
64
+ # Download native file
65
+ download_asherah_path = File.join(tmp_gem_dir, ASHERAH_BIN)
66
+ system("#{download_asherah_path} #{native_file}")
67
+
68
+ # Add native file in gemspec
69
+ gemspec.files << native_file_path
57
70
  end
58
71
 
59
- package = Gem::Package.build gemspec
72
+ package = Gem::Package.build(gemspec)
60
73
  FileUtils.mv package, File.join(pkg_dir, package)
61
74
  end
62
75
  end
63
76
 
64
-
65
77
  namespace :native do
66
- namespace :build do
67
- desc "Build all native gems"
68
- task :all do
69
- DISTRIBUTIONS.each do |platform, native_files|
70
- native_build(platform, native_files)
71
- end
78
+ desc 'Build all native gems'
79
+ task :build do
80
+ DISTRIBUTIONS.each do |platform, native_files|
81
+ native_build(platform, native_files)
72
82
  end
83
+ end
73
84
 
85
+ namespace :build do
74
86
  DISTRIBUTIONS.each do |platform, native_files|
75
87
  desc "Build native gem for #{platform}"
76
88
  task :"#{platform}" do
@@ -79,19 +91,31 @@ namespace :native do
79
91
  end
80
92
  end
81
93
 
82
- namespace :smoke do
83
- require 'cobhan'
94
+ namespace :current do
95
+ desc 'Download asherah binary for current platform'
96
+ task :download do
97
+ download_asherah_path = File.join(__dir__, ASHERAH_BIN)
98
+ system("#{download_asherah_path} #{current_filename}")
99
+ end
84
100
 
85
- filename = Class.new.extend(Cobhan).library_file_name('libasherah')
86
- platform, _ = DISTRIBUTIONS.detect { |k, v| v.include?(filename) }
101
+ desc 'Build native gem for current platform'
102
+ task :build do
103
+ native_build(current_platform, DISTRIBUTIONS[current_platform])
104
+ end
87
105
 
88
- desc "Smoke test native gem on #{platform} platform"
89
- task :"#{platform}" => :"build:#{platform}" do
106
+ desc 'Smoke test native gem for current platform'
107
+ task smoke: :build do
108
+ platform = current_platform
90
109
  gemspec = Bundler.load_gemspec('asherah.gemspec')
91
110
  gemspec.platform = Gem::Platform.new(platform)
92
111
 
112
+ sh('gem uninstall asherah')
93
113
  sh("gem install pkg/#{gemspec.file_name}")
94
- sh("ruby spec/smoke_test.rb")
114
+ sh('ruby spec/smoke_test.rb')
95
115
  end
96
116
  end
97
117
  end
118
+
119
+ task :version do
120
+ puts Asherah::VERSION
121
+ end
data/asherah.gemspec CHANGED
@@ -34,5 +34,10 @@ Gem::Specification.new do |spec|
34
34
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
35
35
  spec.require_paths = ['lib']
36
36
 
37
- spec.add_dependency 'cobhan', '~> 0.1.2'
37
+ spec.add_dependency 'cobhan', '~> 0.2.0'
38
+ spec.add_development_dependency 'dotenv', '~> 2.7.6'
39
+ spec.add_development_dependency 'rspec', '~> 3.10.0'
40
+ spec.add_development_dependency 'rubocop', '~> 1.7'
41
+ spec.add_development_dependency 'simplecov', '~> 0.21.2'
42
+ spec.add_development_dependency 'simplecov-console', '~> 0.9.1'
38
43
  end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Asherah
6
+ # @attr [String] service_name, The name of this service
7
+ # @attr [String] product_id, The name of the product that owns this service
8
+ # @attr [String] kms, The master key management service (static or aws)
9
+ # @attr [String] metastore, The type of metastore for persisting keys (rdbms, dynamodb, memory)
10
+ # @attr [String] connection_string, The database connection string (required when metastore is rdbms)
11
+ # @attr [String] replica_read_consistency, For Aurora sessions using write forwarding (eventual, global, session)
12
+ # @attr [String] dynamo_db_endpoint, An optional endpoint URL (for dynamodb metastore)
13
+ # @attr [String] dynamo_db_region, The AWS region for DynamoDB requests (for dynamodb metastore)
14
+ # @attr [String] dynamo_db_table_name, The table name for DynamoDB (for dynamodb metastore)
15
+ # @attr [Boolean] enable_region_suffix, Configure the metastore to use regional suffixes (for dynamodb metastore)
16
+ # @attr [String] region_map, List of key-value pairs in the form of REGION1=ARN1[,REGION2=ARN2] (required for aws kms)
17
+ # @attr [String] preferred_region, The preferred AWS region (required for aws kms)
18
+ # @attr [Integer] session_cache_max_size, The maximum number of sessions to cache
19
+ # @attr [Integer] session_cache_duration, The amount of time in seconds a session will remain cached
20
+ # @attr [Integer] expire_after, The amount of time in seconds a key is considered valid
21
+ # @attr [Integer] check_interval, The amount of time in seconds before cached keys are considered stale
22
+ # @attr [Boolean] enable_session_caching, Enable shared session caching
23
+ # @attr [Boolean] verbose, Enable verbose logging output
24
+ class Config
25
+ MAPPING = {
26
+ service_name: :ServiceName,
27
+ product_id: :ProductID,
28
+ kms: :KMS,
29
+ metastore: :Metastore,
30
+ connection_string: :ConnectionString,
31
+ replica_read_consistency: :ReplicaReadConsistency,
32
+ dynamo_db_endpoint: :DynamoDBEndpoint,
33
+ dynamo_db_region: :DynamoDBRegion,
34
+ dynamo_db_table_name: :DynamoDBTableName,
35
+ enable_region_suffix: :EnableRegionSuffix,
36
+ region_map: :RegionMap,
37
+ preferred_region: :PreferredRegion,
38
+ session_cache_max_size: :SessionCacheMaxSize,
39
+ session_cache_duration: :SessionCacheDuration,
40
+ enable_session_caching: :EnableSessionCaching,
41
+ expire_after: :ExpireAfter,
42
+ check_interval: :CheckInterval,
43
+ verbose: :Verbose
44
+ }.freeze
45
+
46
+ KMS_TYPES = ['static', 'aws'].freeze
47
+ METASTORE_TYPES = ['rdbms', 'dynamodb', 'memory'].freeze
48
+
49
+ attr_accessor(*MAPPING.keys)
50
+
51
+ def validate!
52
+ validate_service_name
53
+ validate_product_id
54
+ validate_kms
55
+ validate_metastore
56
+ validate_kms_attributes
57
+ end
58
+
59
+ def to_json(*args)
60
+ config = {}.tap do |c|
61
+ MAPPING.each_pair do |our_key, their_key|
62
+ value = public_send(our_key)
63
+ c[their_key] = value unless value.nil?
64
+ end
65
+ end
66
+
67
+ JSON.generate(config, *args)
68
+ end
69
+
70
+ private
71
+
72
+ def validate_service_name
73
+ raise Error::ConfigError, 'config.service_name not set' if service_name.nil?
74
+ end
75
+
76
+ def validate_product_id
77
+ raise Error::ConfigError, 'config.product_id not set' if product_id.nil?
78
+ end
79
+
80
+ def validate_kms
81
+ raise Error::ConfigError, 'config.kms not set' if kms.nil?
82
+ unless KMS_TYPES.include?(kms)
83
+ raise Error::ConfigError, "config.kms must be one of these: #{KMS_TYPES.join(', ')}"
84
+ end
85
+ end
86
+
87
+ def validate_metastore
88
+ raise Error::ConfigError, 'config.metastore not set' if metastore.nil?
89
+ unless METASTORE_TYPES.include?(metastore)
90
+ raise Error::ConfigError, "config.metastore must be one of these: #{METASTORE_TYPES.join(', ')}"
91
+ end
92
+ end
93
+
94
+ def validate_kms_attributes
95
+ if kms == 'aws'
96
+ raise Error::ConfigError, 'config.region_map not set' if region_map.nil?
97
+ raise Error::ConfigError, 'config.region_map must be a Hash' unless region_map.is_a?(Hash)
98
+ raise Error::ConfigError, 'config.preferred_region not set' if preferred_region.nil?
99
+ end
100
+ end
101
+ end
102
+ end
data/lib/asherah/error.rb CHANGED
@@ -1,21 +1,30 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Asherah
4
+ # Asherah Error converts the error code to error message
3
5
  module Error
4
- ResultError = Class.new(StandardError)
6
+ ConfigError = Class.new(StandardError)
7
+ NotInitialized = Class.new(StandardError)
8
+ AlreadyInitialized = Class.new(StandardError)
9
+ GetSessionFailed = Class.new(StandardError)
10
+ EncryptFailed = Class.new(StandardError)
11
+ DecryptFailed = Class.new(StandardError)
12
+ BadConfig = Class.new(StandardError)
5
13
 
6
14
  CODES = {
7
- -100 => 'not initialized',
8
- -101 => 'already initialized',
9
- -102 => 'get session failed',
10
- -103 => 'encrypt failed',
11
- -104 => 'eecrypt failed'
12
- }
15
+ -100 => NotInitialized,
16
+ -101 => AlreadyInitialized,
17
+ -102 => GetSessionFailed,
18
+ -103 => EncryptFailed,
19
+ -104 => DecryptFailed,
20
+ -105 => BadConfig
21
+ }.freeze
13
22
 
14
- def self.check_result!(scope, result)
15
- if result.negative?
16
- error_message = Error::CODES.fetch(result) { 'unrecognized' }
17
- raise Error::ResultError.new("#{scope} failed: #{error_message}")
18
- end
23
+ def self.check_result!(result, message)
24
+ return unless result.negative?
25
+
26
+ error_class = Error::CODES.fetch(result, StandardError)
27
+ raise error_class, "#{message} (#{result})"
19
28
  end
20
29
  end
21
30
  end
Binary file
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Asherah
4
- VERSION = '0.1.0.beta.1'
4
+ VERSION = '0.3.0'
5
5
  end
data/lib/asherah.rb CHANGED
@@ -1,187 +1,102 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'asherah/version'
4
+ require 'asherah/config'
4
5
  require 'asherah/error'
5
6
  require 'cobhan'
6
7
 
7
- # Asherah uses the following data structures: `data_row_record`, `envelope_key_record`, and `key_meta`.
8
- #
9
- # `data_row_record` contains the encrypted key and provided data, as well as the information
10
- # required to decrypt the key encryption key. This struct should be stored in your
11
- # data persistence as it's required to decrypt data.
12
- #
13
- # data_row_record [Hash]
14
- # key [Hash], envelope_key_record
15
- # data [String]
16
- #
17
- # `envelope_key_record` represents an encrypted key and is the data structure used
18
- # to persist the key in our key table. It also contains the meta data
19
- # of the key used to encrypt it.
20
- #
21
- # envelope_key_record [Hash]
22
- # created [Integer]
23
- # encrypted_key [String]
24
- # parent_key_meta [Hash], key_meta
25
- #
26
- # `key_meta` contains the `id` and `created` timestamp for an encryption key.
27
- #
28
- # key_meta [Hash]
29
- # id [String]
30
- # created [Integer]
8
+ # Asherah is a Ruby wrapper around Asherah Go application-layer encryption SDK.
31
9
  module Asherah
32
10
  extend Cobhan
33
11
 
34
12
  LIB_ROOT_PATH = File.expand_path('asherah/native', __dir__)
35
13
  load_library(LIB_ROOT_PATH, 'libasherah', [
36
- [
37
- :Setup,
38
- [
39
- :pointer, :pointer, :pointer, :pointer, :pointer, :pointer, :int32,
40
- :pointer, :pointer, :pointer, :pointer, :int32, :int32, :int32
41
- ],
42
- :int32
43
- ],
44
- [:Encrypt, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int32],
45
- [:Decrypt, [:pointer, :pointer, :pointer, :int64, :pointer, :int64, :pointer], :int32]
14
+ [:SetupJson, [:pointer], :int32],
15
+ [:EncryptToJson, [:pointer, :pointer, :pointer], :int32],
16
+ [:DecryptFromJson, [:pointer, :pointer, :pointer], :int32],
17
+ [:Shutdown, [], :void]
46
18
  ].freeze)
47
19
 
20
+ ESTIMATED_ENCRYPTION_OVERHEAD = 48
21
+ ESTIMATED_ENVELOPE_OVERHEAD = 185
22
+ BASE64_OVERHEAD = 1.34
23
+
48
24
  class << self
49
- # Initializes Asherah encryption session
25
+ # Configures Asherah
50
26
  #
51
- # @param kms_type [String]
52
- # @param metastore [String]
53
- # @param service_name [String]
54
- # @param product_id [String]
55
- # @param rdbms_connection_string [String]
56
- # @param dynamo_db_endpoint [String]
57
- # @param dynamo_db_region [String]
58
- # @param dynamo_db_table_name [String]
59
- # @param enable_region_suffix [Boolean]
60
- # @param preferred_region [String]
61
- # @param region_map [String]
62
- # @param verbose [Boolean]
63
- # @param session_cache [Boolean]
64
- # @param debug_output [Boolean]
65
- def setup(
66
- kms_type:,
67
- metastore:,
68
- service_name:,
69
- product_id:,
70
- rdbms_connection_string: '',
71
- dynamo_db_endpoint: '',
72
- dynamo_db_region: '',
73
- dynamo_db_table_name: '',
74
- enable_region_suffix: false,
75
- preferred_region: '',
76
- region_map: '',
77
- verbose: false,
78
- session_cache: false,
79
- debug_output: false
80
- )
81
- kms_type_buffer = string_to_cbuffer(kms_type)
82
- metastore_buffer = string_to_cbuffer(metastore)
83
- rdbms_connection_string_buffer = string_to_cbuffer(rdbms_connection_string)
84
- dynamo_db_endpoint_buffer = string_to_cbuffer(dynamo_db_endpoint)
85
- dynamo_db_region_buffer = string_to_cbuffer(dynamo_db_region)
86
- dynamo_db_table_name_buffer = string_to_cbuffer(dynamo_db_table_name)
87
- enable_region_suffix_int = enable_region_suffix ? 1 : 0
88
- service_name_buffer = string_to_cbuffer(service_name)
89
- product_id_buffer = string_to_cbuffer(product_id)
90
- preferred_region_buffer = string_to_cbuffer(preferred_region)
91
- region_map_buffer = string_to_cbuffer(region_map)
92
- verbose_int = verbose ? 1 : 0
93
- session_cache_int = session_cache ? 1 : 0
94
- debug_output_int = debug_output ? 1 : 0
95
-
96
- result = Setup(
97
- kms_type_buffer,
98
- metastore_buffer,
99
- rdbms_connection_string_buffer,
100
- dynamo_db_endpoint_buffer,
101
- dynamo_db_region_buffer,
102
- dynamo_db_table_name_buffer,
103
- enable_region_suffix_int,
104
- service_name_buffer,
105
- product_id_buffer,
106
- preferred_region_buffer,
107
- region_map_buffer,
108
- verbose_int,
109
- session_cache_int,
110
- debug_output_int
111
- )
112
-
113
- Error.check_result!('setup', result)
27
+ # @yield [Config]
28
+ # @return [void]
29
+ def configure
30
+ config = Config.new
31
+ yield config
32
+ config.validate!
33
+ @intermediated_key_overhead_bytesize = config.product_id.bytesize + config.service_name.bytesize
34
+
35
+ config_buffer = string_to_cbuffer(config.to_json)
36
+
37
+ result = SetupJson(config_buffer)
38
+ Error.check_result!(result, 'SetupJson failed')
114
39
  end
115
40
 
116
- # Encrypts data for a given partition_id
41
+ # Encrypts data for a given partition_id and returns DataRowRecord in JSON format.
42
+ #
43
+ # DataRowRecord contains the encrypted key and data, as well as the information
44
+ # required to decrypt the key encryption key. This object data should be stored
45
+ # in your data persistence as it's required to decrypt data.
46
+ #
47
+ # EnvelopeKeyRecord represents an encrypted key and is the data structure used
48
+ # to persist the key in the key table. It also contains the meta data
49
+ # of the key used to encrypt it.
50
+ #
51
+ # KeyMeta contains the `id` and `created` timestamp for an encryption key.
117
52
  #
118
53
  # @param partition_id [String]
119
54
  # @param data [String]
120
- # @return [Hash], data_row_record
55
+ # @return [String], DataRowRecord in JSON format
121
56
  def encrypt(partition_id, data)
122
57
  partition_id_buffer = string_to_cbuffer(partition_id)
123
58
  data_buffer = string_to_cbuffer(data)
124
- output_encrypted_data_buffer = allocate_cbuffer(data.length + 256)
125
- output_encrypted_key_buffer = allocate_cbuffer(256)
126
- output_created_buffer = int_to_buffer(0)
127
- output_parent_key_id_buffer = allocate_cbuffer(256)
128
- output_parent_key_created_buffer = int_to_buffer(0)
129
-
130
- result = Encrypt(
131
- partition_id_buffer,
132
- data_buffer,
133
- output_encrypted_data_buffer,
134
- output_encrypted_key_buffer,
135
- output_created_buffer,
136
- output_parent_key_id_buffer,
137
- output_parent_key_created_buffer
138
- )
139
-
140
- Error.check_result!('encrypt', result)
141
-
142
- parent_key_id = cbuffer_to_string(output_parent_key_id_buffer)
143
-
144
- {
145
- data: cbuffer_to_string(output_encrypted_data_buffer),
146
- key: {
147
- encrypted_key: cbuffer_to_string(output_encrypted_key_buffer),
148
- created: buffer_to_int(output_created_buffer),
149
- parent_key_meta: {
150
- id: parent_key_id,
151
- created: buffer_to_int(output_parent_key_created_buffer)
152
- }
153
- }
154
- }
59
+ estimated_buffer_bytesize = estimate_buffer(data.bytesize, partition_id.bytesize)
60
+ output_buffer = allocate_cbuffer(estimated_buffer_bytesize)
61
+
62
+ result = EncryptToJson(partition_id_buffer, data_buffer, output_buffer)
63
+ Error.check_result!(result, 'EncryptToJson failed')
64
+
65
+ cbuffer_to_string(output_buffer)
66
+ ensure
67
+ [partition_id_buffer, data_buffer, output_buffer].map(&:free)
155
68
  end
156
69
 
157
- # Decrypts a data_row_record for a partition_id
70
+ # Decrypts a DataRowRecord in JSON format for a partition_id and returns decrypted data.
158
71
  #
159
72
  # @param partition_id [String]
160
- # @param data_row_record [Hash], data_row_record
161
- # @return [String]
162
- def decrypt(partition_id, data_row_record)
73
+ # @param json [String], DataRowRecord in JSON format
74
+ # @return [String], Decrypted data
75
+ def decrypt(partition_id, json)
163
76
  partition_id_buffer = string_to_cbuffer(partition_id)
164
- encrypted_data_buffer = string_to_cbuffer(data_row_record[:data])
165
- encrypted_key_buffer = string_to_cbuffer(data_row_record[:key][:encrypted_key])
166
- created = data_row_record[:key][:created]
167
- parent_key_id_buffer = string_to_cbuffer(data_row_record[:key][:parent_key_meta][:id])
168
- parent_key_created = data_row_record[:key][:parent_key_meta][:created]
169
-
170
- output_data_buffer = allocate_cbuffer(encrypted_data_buffer.size + 256)
171
-
172
- result = Decrypt(
173
- partition_id_buffer,
174
- encrypted_data_buffer,
175
- encrypted_key_buffer,
176
- created,
177
- parent_key_id_buffer,
178
- parent_key_created,
179
- output_data_buffer
180
- )
181
-
182
- Error.check_result!('decrypt', result)
183
-
184
- cbuffer_to_string(output_data_buffer)
77
+ data_buffer = string_to_cbuffer(json)
78
+ output_buffer = allocate_cbuffer(json.bytesize)
79
+
80
+ result = DecryptFromJson(partition_id_buffer, data_buffer, output_buffer)
81
+ Error.check_result!(result, 'DecryptFromJson failed')
82
+
83
+ cbuffer_to_string(output_buffer)
84
+ ensure
85
+ [partition_id_buffer, data_buffer, output_buffer].map(&:free)
86
+ end
87
+
88
+ # Stop the Asherah instance
89
+ def shutdown
90
+ Shutdown()
91
+ end
92
+
93
+ private
94
+
95
+ def estimate_buffer(data_bytesize, partition_bytesize)
96
+ ESTIMATED_ENVELOPE_OVERHEAD +
97
+ @intermediated_key_overhead_bytesize +
98
+ partition_bytesize +
99
+ ((data_bytesize + ESTIMATED_ENCRYPTION_OVERHEAD) * BASE64_OVERHEAD)
185
100
  end
186
101
  end
187
102
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asherah
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.beta.1
4
+ version: 0.3.0
5
5
  platform: aarch64-linux
6
6
  authors:
7
7
  - GoDaddy
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-07 00:00:00.000000000 Z
11
+ date: 2022-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cobhan
@@ -16,14 +16,84 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.2
19
+ version: 0.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.2
26
+ version: 0.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: dotenv
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.7.6
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.7.6
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.10.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.10.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.21.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.21.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov-console
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.9.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.9.1
27
97
  description: |
28
98
  Asherah is an application-layer encryption SDK that provides advanced
29
99
  encryption features and defense in depth against compromise.
@@ -46,6 +116,7 @@ files:
46
116
  - SECURITY.md
47
117
  - asherah.gemspec
48
118
  - lib/asherah.rb
119
+ - lib/asherah/config.rb
49
120
  - lib/asherah/error.rb
50
121
  - lib/asherah/native/libasherah-arm64.so
51
122
  - lib/asherah/version.rb
@@ -57,7 +128,7 @@ metadata:
57
128
  source_code_uri: https://github.com/godaddy/asherah-ruby
58
129
  changelog_uri: https://github.com/godaddy/asherah-ruby/blob/main/CHANGELOG.md
59
130
  rubygems_mfa_required: 'true'
60
- post_install_message:
131
+ post_install_message:
61
132
  rdoc_options: []
62
133
  require_paths:
63
134
  - lib
@@ -68,12 +139,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
68
139
  version: 2.5.0
69
140
  required_rubygems_version: !ruby/object:Gem::Requirement
70
141
  requirements:
71
- - - ">"
142
+ - - ">="
72
143
  - !ruby/object:Gem::Version
73
- version: 1.3.1
144
+ version: '0'
74
145
  requirements: []
75
- rubygems_version: 3.3.3
76
- signing_key:
146
+ rubygems_version: 3.3.7
147
+ signing_key:
77
148
  specification_version: 4
78
149
  summary: Application Layer Encryption SDK
79
150
  test_files: []