e3db 2.0.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -41,6 +41,7 @@ module E3DB
41
41
  attribute :client_id, Types::String
42
42
  attribute :api_key_id, Types::String
43
43
  attribute :api_secret, Types::String
44
+ attribute :client_email, Types::String
44
45
  attribute :public_key, Types::String
45
46
  attribute :private_key, Types::String
46
47
  attribute :api_url, Types::String.default(DEFAULT_API_URL)
@@ -57,6 +58,7 @@ module E3DB
57
58
  # "client_id": "UUID",
58
59
  # "api_key_id": "API_KEY",
59
60
  # "api_secret": "API_SECRET",
61
+ # "client_email": "CLIENT_EMAIL",
60
62
  # "public_key": "PUBLIC_KEY",
61
63
  # "private_key": "PRIVATE_KEY",
62
64
  # "api_url": "URL",
@@ -5,142 +5,66 @@
5
5
  # All Rights Reserved.
6
6
  #
7
7
 
8
-
9
8
  module E3DB
10
- class Client
9
+ module Crypto
11
10
  private
12
- def decrypt_record(record)
13
- writer_id = record.meta.writer_id
14
- user_id = record.meta.user_id
15
- type = record.meta.type
16
- ak = get_access_key(writer_id, user_id, @config.client_id, type)
17
- decrypt_record_with_key(record, ak)
18
- end
19
-
20
- def decrypt_record_with_key(encrypted_record, ak)
21
- record = Record.new(meta: encrypted_record.meta.clone, data: Hash.new)
22
-
23
- encrypted_record.data.each do |k, v|
24
- fields = v.split('.', 4)
25
-
26
- edk = Crypto.base64decode(fields[0])
27
- edkN = Crypto.base64decode(fields[1])
28
- ef = Crypto.base64decode(fields[2])
29
- efN = Crypto.base64decode(fields[3])
30
-
31
- dk = RbNaCl::SecretBox.new(ak).decrypt(edkN, edk)
32
- pv = RbNaCl::SecretBox.new(dk).decrypt(efN, ef)
33
-
34
- record.data[k] = pv
35
- end
36
-
37
- record
38
- end
39
-
40
- def encrypt_record(plaintext_record)
41
- record = Record.new(meta: plaintext_record.meta.clone, data: Hash.new)
42
-
43
- writer_id = record.meta.writer_id
44
- user_id = record.meta.user_id
45
- type = record.meta.type
46
-
47
- begin
48
- ak = get_access_key(writer_id, user_id, @config.client_id, type)
49
- rescue Faraday::ResourceNotFound
50
- ak = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes)
51
- put_access_key(writer_id, user_id, @config.client_id, type, ak)
52
- end
53
-
54
- plaintext_record.data.each do |k, v|
55
- dk = Crypto.secret_box_random_key
56
- efN = Crypto.secret_box_random_nonce
57
- ef = RbNaCl::SecretBox.new(dk).encrypt(efN, v)
58
- edkN = Crypto.secret_box_random_nonce
59
- edk = RbNaCl::SecretBox.new(ak).encrypt(edkN, dk)
60
-
61
- record.data[k] = sprintf('%s.%s.%s.%s',
62
- Crypto.base64encode(edk), Crypto.base64encode(edkN),
63
- Crypto.base64encode(ef), Crypto.base64encode(efN))
64
- end
65
-
66
- record
67
- end
68
-
69
- def decrypt_eak(json)
70
- k = json[:authorizer_public_key][:curve25519]
71
- authorizer_pubkey = Crypto.decode_public_key(k)
72
-
73
- fields = json[:eak].split('.', 2)
74
- ciphertext = Crypto.base64decode(fields[0])
75
- nonce = Crypto.base64decode(fields[1])
76
- box = RbNaCl::Box.new(authorizer_pubkey, @private_key)
77
-
78
- box.decrypt(nonce, ciphertext)
79
- end
80
-
81
- def get_access_key(writer_id, user_id, reader_id, type)
82
- ak_cache_key = [writer_id, user_id, type]
83
- if @ak_cache.key? ak_cache_key
84
- return @ak_cache[ak_cache_key]
85
- end
86
11
 
87
- url = get_url('v1', 'storage', 'access_keys', writer_id, user_id, reader_id, type)
88
- resp = @conn.get(url)
89
- json = JSON.parse(resp.body, symbolize_names: true)
90
-
91
- ak = decrypt_eak(json)
92
- @ak_cache[ak_cache_key] = ak
93
- ak
94
- end
95
-
96
- def put_access_key(writer_id, user_id, reader_id, type, ak)
97
- ak_cache_key = [writer_id, user_id, type]
98
- @ak_cache[ak_cache_key] = ak
99
-
100
- reader_key = client_key(reader_id)
101
- nonce = RbNaCl::Random.random_bytes(RbNaCl::Box.nonce_bytes)
102
- eak = RbNaCl::Box.new(reader_key, @private_key).encrypt(nonce, ak)
103
-
104
- encoded_eak = sprintf('%s.%s', Crypto.base64encode(eak), Crypto.base64encode(nonce))
105
-
106
- url = get_url('v1', 'storage', 'access_keys', writer_id, user_id, reader_id, type)
107
- @conn.put(url, { :eak => encoded_eak })
12
+ # Create a new, random access key. Returns a
13
+ # string of bytes representing the key.
14
+ def new_access_key
15
+ RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes)
108
16
  end
109
17
 
110
- end
18
+ alias :new_data_key :new_access_key
111
19
 
112
- class Crypto
113
- def self.decode_public_key(s)
20
+ def decode_public_key(s)
114
21
  RbNaCl::PublicKey.new(base64decode(s))
115
22
  end
116
23
 
117
- def self.encode_public_key(k)
24
+ def encode_public_key(k)
118
25
  base64encode(k.to_bytes)
119
26
  end
120
27
 
121
- def self.decode_private_key(s)
28
+ def decode_private_key(s)
122
29
  RbNaCl::PrivateKey.new(base64decode(s))
123
30
  end
124
31
 
125
- def self.encode_private_key(k)
32
+ def encode_private_key(k)
126
33
  base64encode(k.to_bytes)
127
34
  end
128
35
 
129
- def self.secret_box_random_key
130
- RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes)
36
+ def box_random_nonce
37
+ RbNaCl::Random.random_bytes(RbNaCl::Box.nonce_bytes)
131
38
  end
132
39
 
133
- def self.secret_box_random_nonce
40
+ def secret_box_random_nonce
134
41
  RbNaCl::Random.random_bytes(RbNaCl::SecretBox.nonce_bytes)
135
42
  end
136
43
 
137
- def self.base64encode(x)
44
+ def base64encode(x)
138
45
  Base64.urlsafe_encode64(x, padding: false)
139
46
  end
140
47
 
141
- def self.base64decode(x)
48
+ def base64decode(x)
142
49
  Base64.urlsafe_decode64(x)
143
50
  end
51
+
52
+ def decrypt_box(encrypted, pub, priv)
53
+ pub = decode_public_key(pub) unless pub.is_a? RbNaCl::PublicKey
54
+ priv = decode_private_key(priv) unless priv.is_a? RbNaCl::PrivateKey
55
+
56
+ ciphertext, nonce = encrypted.split('.', 2).map { |f| base64decode(f) }
57
+ RbNaCl::Box.new(pub, priv).decrypt(nonce, ciphertext)
58
+ end
59
+
60
+ def encrypt_box(plain, pub, priv)
61
+ pub = decode_public_key(pub) unless pub.is_a? RbNaCl::PublicKey
62
+ priv = decode_private_key(priv) unless priv.is_a? RbNaCl::PrivateKey
63
+
64
+ nonce = box_random_nonce
65
+ encrypted = RbNaCl::Box.new(pub, priv).encrypt(nonce, plain)
66
+ [encrypted, nonce].map { |f| base64encode(f) }.join(".")
67
+ end
144
68
  end
145
69
 
146
70
  private_constant :Crypto
@@ -1,3 +1,3 @@
1
1
  module E3DB
2
- VERSION = "2.0.0"
2
+ VERSION = "2.1.1"
3
3
  end
@@ -21,4 +21,22 @@ cat > "$HOME/.tozny/integration-test/e3db.json" <<EOT
21
21
  "public_key":"${PUBLIC_KEY}",
22
22
  "private_key":"${PRIVATE_KEY}"
23
23
  }
24
+ EOT
25
+
26
+ # Check if the config is already set
27
+ if [ ! -d "$HOME/.tozny/integration-test-share" ]; then
28
+ mkdir -p "$HOME/.tozny/integration-test-share"
29
+ fi
30
+
31
+ cat > "$HOME/.tozny/integration-test-share/e3db.json" <<EOT
32
+ {
33
+ "version":1,
34
+ "api_url":"${API_URL_2}",
35
+ "api_key_id":"${API_KEY_ID_2}",
36
+ "api_secret":"${API_SECRET_2}",
37
+ "client_id":"${CLIENT_ID_2}",
38
+ "client_email":"${CLIENT_EMAIL_2}",
39
+ "public_key":"${PUBLIC_KEY_2}",
40
+ "private_key":"${PRIVATE_KEY_2}"
41
+ }
24
42
  EOT
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: e3db
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tozny, LLC
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-11 00:00:00.000000000 Z
11
+ date: 2017-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -188,12 +188,13 @@ files:
188
188
  - ".travis.yml"
189
189
  - ".yardopts"
190
190
  - Gemfile
191
- - LICENSE.txt
191
+ - LICENSE.md
192
192
  - README.md
193
193
  - Rakefile
194
194
  - bin/console
195
195
  - bin/setup
196
196
  - e3db.gemspec
197
+ - examples/registration.rb
197
198
  - examples/simple.rb
198
199
  - lib/e3db.rb
199
200
  - lib/e3db/client.rb
@@ -223,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
223
224
  version: '0'
224
225
  requirements: []
225
226
  rubyforge_project:
226
- rubygems_version: 2.6.8
227
+ rubygems_version: 2.6.13
227
228
  signing_key:
228
229
  specification_version: 4
229
230
  summary: e3db client SDK
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (C) 2017, Tozny, LLC.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.