module Pubnub
module Crypto
# Legacy cryptor.
#
# The cryptor provides _encryption_ and _decryption_ using `AES-256 in
# CBC mode with a cipher key and configurable initialization vector
# randomness.
# When it is registered as a secondary with other cryptors, it will provide
# backward compatibility with previously encrypted data.
#
# Important: It has been reported that the digest from cipherKey has
# low entropy, and it is suggested to use AesCbcCryptor instead.
class LegacyCryptor < Cryptor
# AES-128 CBC block size.
BLOCK_SIZE = 16
# Create legacy cryptor instance.
#
# @param cipher_key [String] Key for data encryption and
# decryption.
# @param use_random_iv [Boolean] Whether random IV should be used.
def initialize(cipher_key, use_random_iv = true)
@alg = 'AES-256-CBC'
@original_cipher_key = cipher_key
@cipher_key = Digest::SHA256.hexdigest(cipher_key.to_s).slice(0, 32)
@iv = use_random_iv ? nil : '0123456789012345'
super()
end
def identifier
'\x00\x00\x00\x00'
end
def encrypt(data)
if data.nil? || data.empty?
puts 'Pubnub :: ENCRYPTION ERROR: Empty data for encryption'
return nil
end
iv = @iv || OpenSSL::Random.random_bytes(BLOCK_SIZE)
cipher = OpenSSL::Cipher.new(@alg).encrypt
cipher.key = @cipher_key
cipher.iv = iv
encoded_message = ''
encoded_message << iv if @iv.nil? && iv
encoded_message << cipher.update(data)
encoded_message << cipher.final
Crypto::EncryptedData.new(encoded_message)
rescue StandardError => e
puts "Pubnub :: ENCRYPTION ERROR: #{e}"
nil
end
def decrypt(data)
encrypted_data = data.data
iv = if @iv.nil? && encrypted_data.length >= BLOCK_SIZE
encrypted_data.slice!(0..(BLOCK_SIZE - 1)) if encrypted_data.length >= BLOCK_SIZE
else
@iv
end
if iv.length != BLOCK_SIZE
puts "Pubnub :: DECRYPTION ERROR: Unexpected initialization vector length: #{data.metadata.length} bytes (#{BLOCK_SIZE} bytes is expected)"
return nil
end
unless encrypted_data.length.positive?
puts 'Pubnub :: DECRYPTION ERROR: Empty data for decryption'
return nil
end
cipher = OpenSSL::Cipher.new(@alg).decrypt
cipher.key = @cipher_key
cipher.iv = iv
decrypted = cipher.update encrypted_data
decrypted << cipher.final
rescue StandardError => e
puts "Pubnub :: DECRYPTION ERROR: #{e}"
nil
end
end
end
end