-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathasherah.rb
More file actions
135 lines (112 loc) · 4.36 KB
/
asherah.rb
File metadata and controls
135 lines (112 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# frozen_string_literal: true
require_relative 'asherah/version'
require 'asherah/config'
require 'asherah/error'
require 'cobhan'
# Asherah is a Ruby wrapper around Asherah Go application-layer encryption SDK.
module Asherah
extend Cobhan
LIB_ROOT_PATH = File.expand_path('asherah/native', __dir__)
load_library(LIB_ROOT_PATH, 'libasherah', [
[:SetEnv, [:pointer], :int32],
[:SetupJson, [:pointer], :int32],
[:EncryptToJson, [:pointer, :pointer, :pointer], :int32],
[:DecryptFromJson, [:pointer, :pointer, :pointer], :int32],
[:Shutdown, [], :void]
].freeze)
ESTIMATED_ENCRYPTION_OVERHEAD = 48
ESTIMATED_ENVELOPE_OVERHEAD = 185
BASE64_OVERHEAD = 1.34
class << self
# Set environment variables needed by Asherah dependencies for when
# Go os.Getenv() doesn't see variables set by C.setenv().
# References:
# https://github.com/golang/go/wiki/cgo#environmental-variables
# https://github.com/golang/go/issues/44108
#
# @yield [Config]
# @param env [Hash], Key-value pairs to set Asherah ENV
# @return [void]
def set_env(env = {})
env_buffer = string_to_cbuffer(env.to_json)
result = SetEnv(env_buffer)
Error.check_result!(result, 'SetEnv failed')
ensure
env_buffer&.free
end
# Configures Asherah
#
# @yield [Config]
# @return [void]
def configure
raise Asherah::Error::AlreadyInitialized if @initialized
config = Config.new
yield config
config.validate!
@intermediated_key_overhead_bytesize = config.product_id.bytesize + config.service_name.bytesize
config_buffer = string_to_cbuffer(config.to_json)
result = SetupJson(config_buffer)
Error.check_result!(result, 'SetupJson failed')
@initialized = true
ensure
config_buffer&.free
end
# Encrypts data for a given partition_id and returns DataRowRecord in JSON format.
#
# DataRowRecord contains the encrypted key and data, as well as the information
# required to decrypt the key encryption key. This object data should be stored
# in your data persistence as it's required to decrypt data.
#
# EnvelopeKeyRecord represents an encrypted key and is the data structure used
# to persist the key in the key table. It also contains the meta data
# of the key used to encrypt it.
#
# KeyMeta contains the `id` and `created` timestamp for an encryption key.
#
# @param partition_id [String]
# @param data [String]
# @return [String], DataRowRecord in JSON format
def encrypt(partition_id, data)
raise Asherah::Error::NotInitialized unless @initialized
partition_id_buffer = string_to_cbuffer(partition_id)
data_buffer = string_to_cbuffer(data)
estimated_buffer_bytesize = estimate_buffer(data.bytesize, partition_id.bytesize)
output_buffer = allocate_cbuffer(estimated_buffer_bytesize)
result = EncryptToJson(partition_id_buffer, data_buffer, output_buffer)
Error.check_result!(result, 'EncryptToJson failed')
cbuffer_to_string(output_buffer)
ensure
[partition_id_buffer, data_buffer, output_buffer].compact.each(&:free)
end
# Decrypts a DataRowRecord in JSON format for a partition_id and returns decrypted data.
#
# @param partition_id [String]
# @param json [String], DataRowRecord in JSON format
# @return [String], Decrypted data
def decrypt(partition_id, json)
raise Asherah::Error::NotInitialized unless @initialized
partition_id_buffer = string_to_cbuffer(partition_id)
data_buffer = string_to_cbuffer(json)
output_buffer = allocate_cbuffer(json.bytesize)
result = DecryptFromJson(partition_id_buffer, data_buffer, output_buffer)
Error.check_result!(result, 'DecryptFromJson failed')
cbuffer_to_string(output_buffer)
ensure
[partition_id_buffer, data_buffer, output_buffer].compact.each(&:free)
end
# Stop the Asherah instance
def shutdown
raise Asherah::Error::NotInitialized unless @initialized
Shutdown()
@initialized = false
end
private
def estimate_buffer(data_bytesize, partition_bytesize)
est_data_len = (((data_bytesize + ESTIMATED_ENCRYPTION_OVERHEAD) * BASE64_OVERHEAD).to_i + 1)
ESTIMATED_ENVELOPE_OVERHEAD +
@intermediated_key_overhead_bytesize +
partition_bytesize +
est_data_len
end
end
end