pubnub 5.2.2 → 5.3.0
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 +4 -4
- data/.github/CODEOWNERS +2 -2
- data/.pubnub.yml +11 -4
- data/.tool-versions +1 -1
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +6 -6
- data/LICENSE +29 -0
- data/VERSION +1 -1
- data/features/step_definitions/access_steps.rb +0 -2
- data/features/step_definitions/crypto_steps.rb +99 -0
- data/features/support/cryptor.rb +58 -0
- data/features/support/hooks.rb +0 -1
- data/lib/pubnub/client.rb +30 -1
- data/lib/pubnub/error.rb +3 -0
- data/lib/pubnub/event.rb +13 -5
- data/lib/pubnub/events/add_message_action.rb +2 -2
- data/lib/pubnub/events/grant_token.rb +1 -1
- data/lib/pubnub/events/history.rb +18 -6
- data/lib/pubnub/events/publish.rb +7 -3
- data/lib/pubnub/events/remove_channel_members.rb +3 -3
- data/lib/pubnub/events/remove_channel_metadata.rb +1 -1
- data/lib/pubnub/events/remove_memberships.rb +3 -3
- data/lib/pubnub/events/remove_uuid_metadata.rb +1 -1
- data/lib/pubnub/events/set_channel_members.rb +3 -3
- data/lib/pubnub/events/set_channel_metadata.rb +2 -2
- data/lib/pubnub/events/set_memberships.rb +3 -3
- data/lib/pubnub/events/set_uuid_metadata.rb +2 -2
- data/lib/pubnub/events/signal.rb +1 -1
- data/lib/pubnub/events/subscribe.rb +5 -0
- data/lib/pubnub/formatter.rb +22 -11
- data/lib/pubnub/modules/crypto/crypto_module.rb +159 -0
- data/lib/pubnub/modules/crypto/crypto_provider.rb +31 -0
- data/lib/pubnub/modules/crypto/cryptor.rb +73 -0
- data/lib/pubnub/modules/crypto/cryptor_header.rb +251 -0
- data/lib/pubnub/modules/crypto/cryptors/aes_cbc_cryptor.rb +67 -0
- data/lib/pubnub/modules/crypto/cryptors/legacy_cryptor.rb +84 -0
- data/lib/pubnub/modules/crypto/module.rb +8 -0
- data/lib/pubnub/subscribe_event/formatter.rb +8 -8
- data/lib/pubnub/version.rb +1 -1
- data/pubnub.gemspec +2 -2
- metadata +16 -5
- data/LICENSE.txt +0 -30
- data/lib/pubnub/crypto.rb +0 -70
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Pubnub
|
4
|
+
module Crypto
|
5
|
+
# AES-256-CBC cryptor.
|
6
|
+
#
|
7
|
+
# The cryptor provides _encryption_ and _decryption_ using <i>AES-256</i> in
|
8
|
+
# <i>CBC</i> mode with a cipher key and random initialization vector.
|
9
|
+
# When it is registered as a secondary with other cryptors, it will provide
|
10
|
+
# backward compatibility with previously encrypted data.
|
11
|
+
class AesCbcCryptor < Cryptor
|
12
|
+
# AES-128 CBC block size.
|
13
|
+
BLOCK_SIZE = 16
|
14
|
+
|
15
|
+
# Create AES-256-CBC cryptor instance.
|
16
|
+
#
|
17
|
+
# @param cipher_key [String] Key for data <i>encryption</i> and
|
18
|
+
# <i>decryption</i>.
|
19
|
+
def initialize(cipher_key)
|
20
|
+
@cipher_key = Digest::SHA256.digest(cipher_key)
|
21
|
+
@alg = 'AES-256-CBC'
|
22
|
+
super()
|
23
|
+
end
|
24
|
+
|
25
|
+
def identifier
|
26
|
+
'ACRH'
|
27
|
+
end
|
28
|
+
|
29
|
+
def encrypt(data)
|
30
|
+
if data.nil? || data.empty?
|
31
|
+
puts 'Pubnub :: ENCRYPTION ERROR: Empty data for encryption'
|
32
|
+
return nil
|
33
|
+
end
|
34
|
+
|
35
|
+
iv = OpenSSL::Random.random_bytes BLOCK_SIZE
|
36
|
+
cipher = OpenSSL::Cipher.new(@alg).encrypt
|
37
|
+
cipher.key = @cipher_key
|
38
|
+
cipher.iv = iv
|
39
|
+
|
40
|
+
encoded_message = cipher.update data
|
41
|
+
encoded_message << cipher.final
|
42
|
+
Crypto::EncryptedData.new(encoded_message, iv)
|
43
|
+
rescue StandardError => e
|
44
|
+
puts "Pubnub :: ENCRYPTION ERROR: #{e}"
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def decrypt(data)
|
49
|
+
if data.metadata.length != BLOCK_SIZE
|
50
|
+
puts "Pubnub :: DECRYPTION ERROR: Unexpected initialization vector length:
|
51
|
+
#{data.metadata.length} bytes (#{BLOCK_SIZE} bytes is expected)"
|
52
|
+
return nil
|
53
|
+
end
|
54
|
+
|
55
|
+
cipher = OpenSSL::Cipher.new(@alg).decrypt
|
56
|
+
cipher.key = @cipher_key
|
57
|
+
cipher.iv = data.metadata
|
58
|
+
|
59
|
+
decrypted = cipher.update data.data
|
60
|
+
decrypted << cipher.final
|
61
|
+
rescue StandardError => e
|
62
|
+
puts "Pubnub :: DECRYPTION ERROR: #{e}"
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Pubnub
|
2
|
+
module Crypto
|
3
|
+
# Legacy cryptor.
|
4
|
+
#
|
5
|
+
# The cryptor provides _encryption_ and _decryption_ using <i>`AES-256</i> in
|
6
|
+
# <i>CBC</i> mode with a cipher key and configurable initialization vector
|
7
|
+
# randomness.
|
8
|
+
# When it is registered as a secondary with other cryptors, it will provide
|
9
|
+
# backward compatibility with previously encrypted data.
|
10
|
+
#
|
11
|
+
# <b>Important</b>: It has been reported that the digest from cipherKey has
|
12
|
+
# low entropy, and it is suggested to use <i>AesCbcCryptor</i> instead.
|
13
|
+
class LegacyCryptor < Cryptor
|
14
|
+
# AES-128 CBC block size.
|
15
|
+
BLOCK_SIZE = 16
|
16
|
+
|
17
|
+
# Create legacy cryptor instance.
|
18
|
+
#
|
19
|
+
# @param cipher_key [String] Key for data <i>encryption</i> and
|
20
|
+
# <i>decryption</i>.
|
21
|
+
# @param use_random_iv [Boolean] Whether random IV should be used.
|
22
|
+
def initialize(cipher_key, use_random_iv = true)
|
23
|
+
@alg = 'AES-256-CBC'
|
24
|
+
@original_cipher_key = cipher_key
|
25
|
+
@cipher_key = Digest::SHA256.hexdigest(cipher_key.to_s).slice(0, 32)
|
26
|
+
@iv = use_random_iv ? nil : '0123456789012345'
|
27
|
+
super()
|
28
|
+
end
|
29
|
+
|
30
|
+
def identifier
|
31
|
+
'\x00\x00\x00\x00'
|
32
|
+
end
|
33
|
+
|
34
|
+
def encrypt(data)
|
35
|
+
if data.nil? || data.empty?
|
36
|
+
puts 'Pubnub :: ENCRYPTION ERROR: Empty data for encryption'
|
37
|
+
return nil
|
38
|
+
end
|
39
|
+
|
40
|
+
iv = @iv || OpenSSL::Random.random_bytes(BLOCK_SIZE)
|
41
|
+
cipher = OpenSSL::Cipher.new(@alg).encrypt
|
42
|
+
cipher.key = @cipher_key
|
43
|
+
cipher.iv = iv
|
44
|
+
|
45
|
+
encoded_message = ''
|
46
|
+
encoded_message << iv if @iv.nil? && iv
|
47
|
+
encoded_message << cipher.update(data)
|
48
|
+
encoded_message << cipher.final
|
49
|
+
Crypto::EncryptedData.new(encoded_message)
|
50
|
+
rescue StandardError => e
|
51
|
+
puts "Pubnub :: ENCRYPTION ERROR: #{e}"
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def decrypt(data)
|
56
|
+
encrypted_data = data.data
|
57
|
+
iv = if @iv.nil? && encrypted_data.length >= BLOCK_SIZE
|
58
|
+
encrypted_data.slice!(0..(BLOCK_SIZE - 1)) if encrypted_data.length >= BLOCK_SIZE
|
59
|
+
else
|
60
|
+
@iv
|
61
|
+
end
|
62
|
+
if iv.length != BLOCK_SIZE
|
63
|
+
puts "Pubnub :: DECRYPTION ERROR: Unexpected initialization vector length: #{data.metadata.length} bytes (#{BLOCK_SIZE} bytes is expected)"
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
|
67
|
+
unless encrypted_data.length.positive?
|
68
|
+
puts 'Pubnub :: DECRYPTION ERROR: Empty data for decryption'
|
69
|
+
return nil
|
70
|
+
end
|
71
|
+
|
72
|
+
cipher = OpenSSL::Cipher.new(@alg).decrypt
|
73
|
+
cipher.key = @cipher_key
|
74
|
+
cipher.iv = iv
|
75
|
+
|
76
|
+
decrypted = cipher.update encrypted_data
|
77
|
+
decrypted << cipher.final
|
78
|
+
rescue StandardError => e
|
79
|
+
puts "Pubnub :: DECRYPTION ERROR: #{e}"
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pubnub/modules/crypto/cryptor'
|
4
|
+
require 'pubnub/modules/crypto/cryptors/aes_cbc_cryptor'
|
5
|
+
require 'pubnub/modules/crypto/cryptors/legacy_cryptor'
|
6
|
+
require 'pubnub/modules/crypto/crypto_provider'
|
7
|
+
require 'pubnub/modules/crypto/cryptor_header'
|
8
|
+
require 'pubnub/modules/crypto/crypto_module'
|
@@ -33,13 +33,12 @@ module Pubnub
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def decipher_payload(message)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
rescue StandardError
|
36
|
+
# TODO: Uncomment code below when cryptor implementations will be added.
|
37
|
+
return message[:payload] if message[:channel].end_with?('-pnpres') || crypto_module.nil?
|
38
|
+
|
39
|
+
encrypted_message = Base64.decode64(message[:payload])
|
40
|
+
JSON.parse(crypto_module.decrypt(encrypted_message), quirks_mode: true)
|
41
|
+
rescue StandardError, UnknownCryptorError
|
43
42
|
message[:payload]
|
44
43
|
end
|
45
44
|
|
@@ -51,7 +50,8 @@ module Pubnub
|
|
51
50
|
# STATUS
|
52
51
|
envelopes = if messages.empty?
|
53
52
|
[plain_envelope(req_res_objects, timetoken)]
|
54
|
-
else
|
53
|
+
else
|
54
|
+
# RESULT
|
55
55
|
messages.map do |message|
|
56
56
|
encrypted_envelope(req_res_objects, message, timetoken)
|
57
57
|
end
|
data/lib/pubnub/version.rb
CHANGED
data/pubnub.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.email = ['support@pubnub.com']
|
10
10
|
spec.summary = 'PubNub Official Ruby gem.'
|
11
11
|
spec.description = 'Ruby anywhere in the world in 250ms with PubNub!'
|
12
|
-
spec.homepage = '
|
13
|
-
spec.
|
12
|
+
spec.homepage = 'https://github.com/pubnub/ruby'
|
13
|
+
spec.licenses = %w[MIT LicenseRef-LICENSE]
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0").grep_v(/^(test|spec|fixtures)/)
|
16
16
|
spec.executables = spec.files.grep(%r{^bin\/}) { |f| File.basename(f) }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pubnub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- PubNub
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -143,7 +143,7 @@ files:
|
|
143
143
|
- CHANGELOG.md
|
144
144
|
- Gemfile
|
145
145
|
- Gemfile.lock
|
146
|
-
- LICENSE
|
146
|
+
- LICENSE
|
147
147
|
- Pubnub Ruby SDK upgrade guide.md
|
148
148
|
- README.md
|
149
149
|
- Rakefile
|
@@ -151,6 +151,8 @@ files:
|
|
151
151
|
- config/cucumber.yml
|
152
152
|
- docs.md
|
153
153
|
- features/step_definitions/access_steps.rb
|
154
|
+
- features/step_definitions/crypto_steps.rb
|
155
|
+
- features/support/cryptor.rb
|
154
156
|
- features/support/env.rb
|
155
157
|
- features/support/helper.rb
|
156
158
|
- features/support/hooks.rb
|
@@ -171,7 +173,6 @@ files:
|
|
171
173
|
- lib/pubnub/client/paged_history.rb
|
172
174
|
- lib/pubnub/configuration.rb
|
173
175
|
- lib/pubnub/constants.rb
|
174
|
-
- lib/pubnub/crypto.rb
|
175
176
|
- lib/pubnub/envelope.rb
|
176
177
|
- lib/pubnub/error.rb
|
177
178
|
- lib/pubnub/error_envelope.rb
|
@@ -222,6 +223,13 @@ files:
|
|
222
223
|
- lib/pubnub/format.rb
|
223
224
|
- lib/pubnub/formatter.rb
|
224
225
|
- lib/pubnub/heart.rb
|
226
|
+
- lib/pubnub/modules/crypto/crypto_module.rb
|
227
|
+
- lib/pubnub/modules/crypto/crypto_provider.rb
|
228
|
+
- lib/pubnub/modules/crypto/cryptor.rb
|
229
|
+
- lib/pubnub/modules/crypto/cryptor_header.rb
|
230
|
+
- lib/pubnub/modules/crypto/cryptors/aes_cbc_cryptor.rb
|
231
|
+
- lib/pubnub/modules/crypto/cryptors/legacy_cryptor.rb
|
232
|
+
- lib/pubnub/modules/crypto/module.rb
|
225
233
|
- lib/pubnub/origin_manager.rb
|
226
234
|
- lib/pubnub/pam.rb
|
227
235
|
- lib/pubnub/schemas/envelope_schema.rb
|
@@ -281,9 +289,10 @@ files:
|
|
281
289
|
- lib/pubnub/validators/where_now.rb
|
282
290
|
- lib/pubnub/version.rb
|
283
291
|
- pubnub.gemspec
|
284
|
-
homepage:
|
292
|
+
homepage: https://github.com/pubnub/ruby
|
285
293
|
licenses:
|
286
294
|
- MIT
|
295
|
+
- LicenseRef-LICENSE
|
287
296
|
metadata: {}
|
288
297
|
post_install_message:
|
289
298
|
rdoc_options: []
|
@@ -306,6 +315,8 @@ specification_version: 4
|
|
306
315
|
summary: PubNub Official Ruby gem.
|
307
316
|
test_files:
|
308
317
|
- features/step_definitions/access_steps.rb
|
318
|
+
- features/step_definitions/crypto_steps.rb
|
319
|
+
- features/support/cryptor.rb
|
309
320
|
- features/support/env.rb
|
310
321
|
- features/support/helper.rb
|
311
322
|
- features/support/hooks.rb
|
data/LICENSE.txt
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
|
2
|
-
Copyright (c) 2013-2014 PubNub Inc.
|
3
|
-
http://www.pubnub.com/
|
4
|
-
http://www.pubnub.com/terms
|
5
|
-
|
6
|
-
MIT License
|
7
|
-
|
8
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
9
|
-
a copy of this software and associated documentation files (the
|
10
|
-
"Software"), to deal in the Software without restriction, including
|
11
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
12
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
-
permit persons to whom the Software is furnished to do so, subject to
|
14
|
-
the following conditions:
|
15
|
-
|
16
|
-
The above copyright notice and this permission notice shall be
|
17
|
-
included in all copies or substantial portions of the Software.
|
18
|
-
|
19
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
20
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
22
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
23
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
24
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
25
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
26
|
-
|
27
|
-
PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
|
28
|
-
Copyright (c) 2013-2014 PubNub Inc.
|
29
|
-
http://www.pubnub.com/
|
30
|
-
http://www.pubnub.com/terms
|
data/lib/pubnub/crypto.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
# Toplevel Pubnub module.
|
2
|
-
module Pubnub
|
3
|
-
# Internal Crypto class used for message encryption and decryption
|
4
|
-
class Crypto
|
5
|
-
def initialize(cipher_key, use_random_iv)
|
6
|
-
@alg = 'AES-256-CBC'
|
7
|
-
sha256_key = Digest::SHA256.hexdigest(cipher_key.to_s)
|
8
|
-
@key = sha256_key.slice(0, 32)
|
9
|
-
@using_random_iv = use_random_iv
|
10
|
-
@iv = @using_random_iv == true ? random_iv : '0123456789012345'
|
11
|
-
end
|
12
|
-
|
13
|
-
def encrypt(message)
|
14
|
-
aes = OpenSSL::Cipher.new(@alg)
|
15
|
-
aes.encrypt
|
16
|
-
aes.key = @key
|
17
|
-
aes.iv = @iv
|
18
|
-
|
19
|
-
json_message = message.to_json
|
20
|
-
cipher = @using_random_iv == true ? @iv : ''
|
21
|
-
cipher << aes.update(json_message)
|
22
|
-
cipher << aes.final
|
23
|
-
|
24
|
-
Base64.strict_encode64(cipher)
|
25
|
-
end
|
26
|
-
|
27
|
-
def decrypt(cipher_text)
|
28
|
-
undecoded_text = Base64.decode64(cipher_text)
|
29
|
-
iv = @iv
|
30
|
-
|
31
|
-
if cipher_text.length > 16 && @using_random_iv == true
|
32
|
-
iv = undecoded_text.slice!(0..15)
|
33
|
-
end
|
34
|
-
|
35
|
-
decode_cipher = OpenSSL::Cipher.new(@alg).decrypt
|
36
|
-
decode_cipher.key = @key
|
37
|
-
decode_cipher.iv = iv
|
38
|
-
|
39
|
-
plain_text = decryption(undecoded_text, decode_cipher)
|
40
|
-
load_json(plain_text)
|
41
|
-
|
42
|
-
Pubnub.logger.debug('Pubnub') { 'Finished decrypting' }
|
43
|
-
|
44
|
-
plain_text
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def decryption(cipher_text, decode_cipher)
|
50
|
-
plain_text = decode_cipher.update(cipher_text)
|
51
|
-
plain_text << decode_cipher.final
|
52
|
-
rescue StandardError => e
|
53
|
-
Pubnub.error('Pubnub') { "DECRYPTION ERROR #{e}" }
|
54
|
-
'"DECRYPTION ERROR"'
|
55
|
-
end
|
56
|
-
|
57
|
-
def load_json(plain_text)
|
58
|
-
JSON.load(plain_text)
|
59
|
-
rescue JSON::ParserError
|
60
|
-
JSON.load("[#{plain_text}]")[0]
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def random_iv
|
66
|
-
random_bytes = Random.new.bytes(16).unpack('NnnnnN')
|
67
|
-
format('%08x%04x%04x', *random_bytes)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|