Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MessagePackMessageSerializer for binary data #51102

Merged

Conversation

djmb
Copy link
Contributor

@djmb djmb commented Feb 16, 2024

Motivation / Background

ActiveRecord::Encryption::MessageSerializer creates serialized JSON. The JSON values are Base64 encoded to ensure that the data can stored in text database columns without encoding issues.

Binary columns however can store arbitrary data, so won't have the encoding issues. By using a MessagePack based serializer we can store data more efficiently without the Base64 overhead (about 33%).

Detail

Add a new serializer ActiveRecord::Encryption::MessagePackMessageSerializer that serializes encrypted data to the MessagePack format, for efficient storage in binary columns.

To prevent it being used with text columns, validate that we only try to store binary data in binary columns.

The serializer is not autoloaded, because it relies on the optional msgpack gem.

Usage:

require "activerecord/encryption/message_pack_message_serializer`

class Foo < ApplicationRecord
  encrypts :bar, message_serializer: ActiveRecord::Encryption::MessagePackMessageSerializer.new
end

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one change. Changes that are unrelated should be opened in separate PRs.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Tests are added or updated if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

@djmb djmb force-pushed the encryption-message-pack-message-serialization branch 2 times, most recently from 10e5e7a to 27f683c Compare February 16, 2024 13:36
Serialize data to the MessagePack format, for efficient storage in
binary columns.

The binary encoding requires around 30% less space than the base64
encoding used by the default serializer.

To prevent it being used with text columns, validate that we only try
to store binary data in binary columns.
@djmb djmb force-pushed the encryption-message-pack-message-serialization branch from 27f683c to 16ef895 Compare February 16, 2024 13:51
Copy link
Member

@jeremy jeremy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent!

@jeremy jeremy added this to the 7.2.0 milestone Feb 16, 2024
@jeremy jeremy merged commit 50e3229 into rails:main Feb 16, 2024
4 checks passed
Ridhwana pushed a commit to Ridhwana/rails that referenced this pull request Mar 7, 2024
viralpraxis pushed a commit to viralpraxis/rails that referenced this pull request Mar 24, 2024
encryptor.encrypt(value, **encryption_options)
encryptor.encrypt(value, **encryption_options).tap do |encrypted|
if !cast_type.binary? && encrypted.encoding == Encoding::BINARY
raise Errors::Encoding, "Binary encoded data can only be stored in binary columns"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@djmb @jeremy Should this be raising if the value wasn't encrypted? See #51412.

fractaledmind pushed a commit to fractaledmind/rails that referenced this pull request May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants