Skip to content

Commit 6a060b8

Browse files
committed
Support UTF-8 data when using the JSON serializer (#39)
* Replace all instance of 'BINARY' with `Encoding::BINARY`
1 parent 8ce0146 commit 6a060b8

3 files changed

Lines changed: 17 additions & 5 deletions

File tree

lib/rack/session/encryptor.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ module Serializable
3232
def serialize_payload(message)
3333
serialized_data = serializer.dump(message)
3434

35-
return "#{[0].pack('v')}#{serialized_data}" if @options[:pad_size].nil?
35+
return "#{[0].pack('v')}#{serialized_data.force_encoding(Encoding::BINARY)}" if @options[:pad_size].nil?
3636

3737
padding_bytes = @options[:pad_size] - (2 + serialized_data.size) % @options[:pad_size]
3838
padding_data = SecureRandom.random_bytes(padding_bytes)
3939

40-
"#{[padding_bytes].pack('v')}#{padding_data}#{serialized_data}"
40+
"#{[padding_bytes].pack('v')}#{padding_data}#{serialized_data.force_encoding(Encoding::BINARY)}"
4141
end
4242

4343
# Return the deserialized message. The first 2 bytes will be read as the
@@ -103,7 +103,7 @@ def initialize(secret, opts = {})
103103
serialize_json: false, pad_size: 32, purpose: nil
104104
}.update(opts)
105105

106-
@hmac_secret = secret.dup.force_encoding('BINARY')
106+
@hmac_secret = secret.dup.force_encoding(Encoding::BINARY)
107107
@cipher_secret = @hmac_secret.slice!(0, 32)
108108

109109
@hmac_secret.freeze
@@ -250,7 +250,7 @@ def initialize(secret, opts = {})
250250
}.update(opts)
251251
@options[:serialize_json] = true # Enforce JSON serialization
252252

253-
@cipher_secret = secret.dup.force_encoding('BINARY').slice!(0, 32)
253+
@cipher_secret = secret.dup.force_encoding(Encoding::BINARY).slice!(0, 32)
254254
@cipher_secret.freeze
255255
end
256256

test/spec_session_cookie.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ def decode(str); @calls << :decode; JSON.parse(str); end
212212
response.body.must_equal ({"counter"=>1}.to_s)
213213
identity.calls.must_equal [:encode]
214214

215-
response = response_for(app: [incrementor, { coder: identity }], :cookie=>response["Set-Cookie"].split(';', 2).first)
215+
response_for(app: [incrementor, { coder: identity }], cookie: response["Set-Cookie"].split(';', 2).first)
216216
identity.calls.must_equal [:encode, :decode, :encode]
217217
end
218218

test/spec_session_encryptor.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ def self.included(_base)
5858
encryptor.decrypt(message).must_equal({ 'foo' => 'bar' })
5959
end
6060

61+
# The V1 encryptor defaults to the Marshal serializer, while the V2
62+
# encryptor always uses the JSON serializer. This means that we are
63+
# indirectly covering both serializers.
64+
it 'decrypts an encrypted message with UTF-8 data' do
65+
encryptor = encryptor_class.new(@secret)
66+
67+
encrypted_message = encryptor.encrypt({ 'foo' => 'bar 😀' })
68+
decrypted_message = encryptor.decrypt(encrypted_message)
69+
70+
decrypted_message.must_equal({ 'foo' => 'bar 😀' })
71+
end
72+
6173
it 'decrypts raises InvalidSignature without purpose' do
6274
encryptor = encryptor_class.new(@secret, purpose: 'testing')
6375
other_encryptor = encryptor_class.new(@secret)

0 commit comments

Comments
 (0)