• Stars
    star
    1,290
  • Rank 34,929 (Top 0.8 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 5 years ago
  • Updated 11 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Modern encryption for Ruby and Rails

Lockbox

📦 Modern encryption for Ruby and Rails

  • Works with database fields, files, and strings
  • Maximizes compatibility with existing code and libraries
  • Makes migrating existing data and key rotation easy
  • Has zero dependencies and many integrations

Learn the principles behind it, how to secure emails with Devise, and how to secure sensitive data in Rails.

Build Status

Installation

Add this line to your application’s Gemfile:

gem "lockbox"

Key Generation

Generate a key

Lockbox.generate_key

Store the key with your other secrets. This is typically Rails credentials or an environment variable (dotenv is great for this). Be sure to use different keys in development and production.

Set the following environment variable with your key (you can use this one in development)

LOCKBOX_MASTER_KEY=0000000000000000000000000000000000000000000000000000000000000000

or add it to your credentials for each environment (rails credentials:edit --environment <env> for Rails 6+)

lockbox:
  master_key: "0000000000000000000000000000000000000000000000000000000000000000"

or create config/initializers/lockbox.rb with something like

Lockbox.master_key = Rails.application.credentials.lockbox[:master_key]

Then follow the instructions below for the data you want to encrypt.

Database Fields

Files

Other

Active Record

Create a migration with:

class AddEmailCiphertextToUsers < ActiveRecord::Migration[7.1]
  def change
    add_column :users, :email_ciphertext, :text
  end
end

Add to your model:

class User < ApplicationRecord
  has_encrypted :email
end

You can use email just like any other attribute.

User.create!(email: "[email protected]")

If you need to query encrypted fields, check out Blind Index.

Multiple Fields

You can specify multiple fields in single line.

class User < ApplicationRecord
  has_encrypted :email, :phone, :city
end

Types

Fields are strings by default. Specify the type of a field with:

class User < ApplicationRecord
  has_encrypted :birthday, type: :date
  has_encrypted :signed_at, type: :datetime
  has_encrypted :opens_at, type: :time
  has_encrypted :active, type: :boolean
  has_encrypted :salary, type: :integer
  has_encrypted :latitude, type: :float
  has_encrypted :longitude, type: :decimal
  has_encrypted :video, type: :binary
  has_encrypted :properties, type: :json
  has_encrypted :settings, type: :hash
  has_encrypted :messages, type: :array
  has_encrypted :ip, type: :inet
end

Note: Use a text column for the ciphertext in migrations, regardless of the type

Lockbox automatically works with serialized fields for maximum compatibility with existing code and libraries.

class User < ApplicationRecord
  serialize :properties, JSON
  store :settings, accessors: [:color, :homepage]
  attribute :configuration, CustomType.new

  has_encrypted :properties, :settings, :configuration
end

For Active Record Store, encrypt the column rather than individual accessors.

For StoreModel, use:

class User < ApplicationRecord
  has_encrypted :configuration, type: Configuration.to_type

  after_initialize do
    self.configuration ||= {}
  end
end

Validations

Validations work as expected with the exception of uniqueness. Uniqueness validations require a blind index.

Fixtures

You can use encrypted attributes in fixtures with:

test_user:
  email_ciphertext: <%= User.generate_email_ciphertext("secret").inspect %>

Be sure to include the inspect at the end or it won’t be encoded properly in YAML.

Migrating Existing Data

Lockbox makes it easy to encrypt an existing column without downtime.

Add a new column for the ciphertext, then add to your model:

class User < ApplicationRecord
  has_encrypted :email, migrating: true
end

Backfill the data in the Rails console:

Lockbox.migrate(User)

Then update the model to the desired state:

class User < ApplicationRecord
  has_encrypted :email

  # remove this line after dropping email column
  self.ignored_columns += ["email"]
end

Finally, drop the unencrypted column.

If adding blind indexes, mark them as migrating during this process as well.

class User < ApplicationRecord
  blind_index :email, migrating: true
end

Model Changes

If tracking changes to model attributes, be sure to remove or redact encrypted attributes.

PaperTrail

class User < ApplicationRecord
  # for an encrypted history (still tracks ciphertext changes)
  has_paper_trail skip: [:email]

  # for no history (add blind indexes as well)
  has_paper_trail skip: [:email, :email_ciphertext]
end

Audited

class User < ApplicationRecord
  # for an encrypted history (still tracks ciphertext changes)
  audited except: [:email]

  # for no history (add blind indexes as well)
  audited except: [:email, :email_ciphertext]
end

Decryption

To decrypt data outside the model, use:

User.decrypt_email_ciphertext(user.email_ciphertext)

Action Text

Note: Action Text uses direct uploads for files, which cannot be encrypted with application-level encryption like Lockbox. This only encrypts the database field.

Create a migration with:

class AddBodyCiphertextToRichTexts < ActiveRecord::Migration[7.1]
  def change
    add_column :action_text_rich_texts, :body_ciphertext, :text
  end
end

Create config/initializers/lockbox.rb with:

Lockbox.encrypts_action_text_body(migrating: true)

Migrate existing data:

Lockbox.migrate(ActionText::RichText)

Update the initializer:

Lockbox.encrypts_action_text_body

And drop the unencrypted column.

Options

You can pass any Lockbox options to the encrypts_action_text_body method.

Mongoid

Add to your model:

class User
  field :email_ciphertext, type: String

  has_encrypted :email
end

You can use email just like any other attribute.

User.create!(email: "[email protected]")

If you need to query encrypted fields, check out Blind Index.

You can migrate existing data similarly to Active Record.

Active Storage

Add to your model:

class User < ApplicationRecord
  has_one_attached :license
  encrypts_attached :license
end

Works with multiple attachments as well.

class User < ApplicationRecord
  has_many_attached :documents
  encrypts_attached :documents
end

There are a few limitations to be aware of:

  • Variants and previews aren’t supported when encrypted
  • Metadata like image width and height aren’t extracted when encrypted
  • Direct uploads can’t be encrypted with application-level encryption like Lockbox, but can use server-side encryption

To serve encrypted files, use a controller action.

def license
  user = User.find(params[:id])
  send_data user.license.download, type: user.license.content_type
end

Use filename to specify a filename or disposition: "inline" to show inline.

Migrating Existing Files

Lockbox makes it easy to encrypt existing files without downtime.

Add to your model:

class User < ApplicationRecord
  encrypts_attached :license, migrating: true
end

Migrate existing files:

Lockbox.migrate(User)

Then update the model to the desired state:

class User < ApplicationRecord
  encrypts_attached :license
end

CarrierWave

Add to your uploader:

class LicenseUploader < CarrierWave::Uploader::Base
  encrypt
end

Encryption is applied to all versions after processing.

You can mount the uploader as normal. With Active Record, this involves creating a migration:

class AddLicenseToUsers < ActiveRecord::Migration[7.1]
  def change
    add_column :users, :license, :string
  end
end

And updating the model:

class User < ApplicationRecord
  mount_uploader :license, LicenseUploader
end

To serve encrypted files, use a controller action.

def license
  user = User.find(params[:id])
  send_data user.license.read, type: user.license.content_type
end

Use filename to specify a filename or disposition: "inline" to show inline.

Migrating Existing Files

Encrypt existing files without downtime. Create a new encrypted uploader:

class LicenseV2Uploader < CarrierWave::Uploader::Base
  encrypt key: Lockbox.attribute_key(table: "users", attribute: "license")
end

Add a new column for the uploader, then add to your model:

class User < ApplicationRecord
  mount_uploader :license_v2, LicenseV2Uploader

  before_save :migrate_license, if: :license_changed?

  def migrate_license
    self.license_v2 = license
  end
end

Migrate existing files:

User.find_each do |user|
  if user.license? && !user.license_v2?
    user.migrate_license
    user.save!
  end
end

Then update the model to the desired state:

class User < ApplicationRecord
  mount_uploader :license, LicenseV2Uploader, mount_on: :license_v2
end

Finally, delete the unencrypted files and drop the column for the original uploader. You can also remove the key option from the uploader.

Shrine

Models

Include the attachment as normal:

class User < ApplicationRecord
  include LicenseUploader::Attachment(:license)
end

And encrypt in a controller (or background job, etc) with:

license = params.require(:user).fetch(:license)
lockbox = Lockbox.new(key: Lockbox.attribute_key(table: "users", attribute: "license"))
user.license = lockbox.encrypt_io(license)

To serve encrypted files, use a controller action.

def license
  user = User.find(params[:id])
  lockbox = Lockbox.new(key: Lockbox.attribute_key(table: "users", attribute: "license"))
  send_data lockbox.decrypt(user.license.read), type: user.license.mime_type
end

Use filename to specify a filename or disposition: "inline" to show inline.

Non-Models

Generate a key

key = Lockbox.generate_key

Create a lockbox

lockbox = Lockbox.new(key: key)

Encrypt files before passing them to Shrine

LicenseUploader.upload(lockbox.encrypt_io(file), :store)

And decrypt them after reading

lockbox.decrypt(uploaded_file.read)

Local Files

Generate a key

key = Lockbox.generate_key

Create a lockbox

lockbox = Lockbox.new(key: key)

Encrypt

ciphertext = lockbox.encrypt(File.binread("file.txt"))

Decrypt

lockbox.decrypt(ciphertext)

Strings

Generate a key

key = Lockbox.generate_key

Create a lockbox

lockbox = Lockbox.new(key: key, encode: true)

Encrypt

ciphertext = lockbox.encrypt("hello")

Decrypt

lockbox.decrypt(ciphertext)

Use decrypt_str get the value as UTF-8

Key Rotation

To make key rotation easy, you can pass previous versions of keys that can decrypt.

Create config/initializers/lockbox.rb with:

Lockbox.default_options[:previous_versions] = [{master_key: previous_key}]

To rotate existing Active Record & Mongoid records, use:

Lockbox.rotate(User, attributes: [:email])

To rotate existing Action Text records, use:

Lockbox.rotate(ActionText::RichText, attributes: [:body])

To rotate existing Active Storage files, use:

User.with_attached_license.find_each do |user|
  user.license.rotate_encryption!
end

To rotate existing CarrierWave files, use:

User.find_each do |user|
  user.license.rotate_encryption!
  # or for multiple files
  user.licenses.map(&:rotate_encryption!)
end

Once everything is rotated, you can remove previous_versions from the initializer.

Individual Fields & Files

You can also pass previous versions to individual fields and files.

class User < ApplicationRecord
  has_encrypted :email, previous_versions: [{master_key: previous_key}]
end

Local Files & Strings

To rotate local files and strings, use:

Lockbox.new(key: key, previous_versions: [{key: previous_key}])

Auditing

It’s a good idea to track user and employee access to sensitive data. Lockbox provides a convenient way to do this with Active Record, but you can use a similar pattern to write audits to any location.

rails generate lockbox:audits
rails db:migrate

Then create an audit wherever a user can view data:

class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])

    LockboxAudit.create!(
      subject: @user,
      viewer: current_user,
      data: ["name", "email"],
      context: "#{controller_name}##{action_name}",
      ip: request.remote_ip
    )
  end
end

Query audits with:

LockboxAudit.last(100)

Note: This approach is not intended to be used in the event of a breach or insider attack, as it’s trivial for someone with access to your infrastructure to bypass.

Algorithms

AES-GCM

This is the default algorithm. It’s:

Lockbox uses 256-bit keys.

For users who do a lot of encryptions: You should rotate an individual key after 2 billion encryptions to minimize the chance of a nonce collision, which will expose the authentication key. Each database field and file uploader use a different key (derived from the master key) to extend this window.

XSalsa20

You can also use XSalsa20, which uses an extended nonce so you don’t have to worry about nonce collisions. First, install Libsodium. It comes preinstalled on Heroku. For Homebrew, use:

brew install libsodium

And for Ubuntu, use:

sudo apt-get install libsodium23

Then add to your Gemfile:

gem "rbnacl"

And add to your model:

class User < ApplicationRecord
  has_encrypted :email, algorithm: "xsalsa20"
end

Make it the default with:

Lockbox.default_options[:algorithm] = "xsalsa20"

You can also pass an algorithm to previous_versions for key rotation.

Hybrid Cryptography

Hybrid cryptography allows servers to encrypt data without being able to decrypt it.

Follow the instructions above for installing Libsodium and including rbnacl in your Gemfile.

Generate a key pair with:

Lockbox.generate_key_pair

Store the keys with your other secrets. Then use:

class User < ApplicationRecord
  has_encrypted :email, algorithm: "hybrid", encryption_key: encryption_key, decryption_key: decryption_key
end

Make sure decryption_key is nil on servers that shouldn’t decrypt.

This uses X25519 for key exchange and XSalsa20 for encryption.

Key Configuration

Lockbox supports a few different ways to set keys for database fields and files.

  1. Master key
  2. Per field/uploader
  3. Per record

Master Key

By default, the master key is used to generate unique keys for each field/uploader. This technique comes from CipherSweet. The table name and column/uploader name are both used in this process.

You can get an individual key with:

Lockbox.attribute_key(table: "users", attribute: "email_ciphertext")

To rename a table with encrypted columns/uploaders, use:

class User < ApplicationRecord
  has_encrypted :email, key_table: "original_table"
end

To rename an encrypted column itself, use:

class User < ApplicationRecord
  has_encrypted :email, key_attribute: "original_column"
end

Per Field/Uploader

To set a key for an individual field/uploader, use a string:

class User < ApplicationRecord
  has_encrypted :email, key: ENV["USER_EMAIL_ENCRYPTION_KEY"]
end

Or a proc:

class User < ApplicationRecord
  has_encrypted :email, key: -> { code }
end

Per Record

To use a different key for each record, use a symbol:

class User < ApplicationRecord
  has_encrypted :email, key: :some_method
end

Or a proc:

class User < ApplicationRecord
  has_encrypted :email, key: -> { some_method }
end

Key Management

You can use a key management service to manage your keys with KMS Encrypted.

For Active Record and Mongoid, use:

class User < ApplicationRecord
  has_encrypted :email, key: :kms_key
end

For Action Text, use:

ActiveSupport.on_load(:action_text_rich_text) do
  ActionText::RichText.has_kms_key
end

Lockbox.encrypts_action_text_body(key: :kms_key)

For Active Storage, use:

class User < ApplicationRecord
  encrypts_attached :license, key: :kms_key
end

For CarrierWave, use:

class LicenseUploader < CarrierWave::Uploader::Base
  encrypt key: -> { model.kms_key }
end

Note: KMS Encrypted’s key rotation does not know to rotate encrypted files, so avoid calling record.rotate_kms_key! on models with file uploads for now.

Data Leakage

While encryption hides the content of a message, an attacker can still get the length of the message (since the length of the ciphertext is the length of the message plus a constant number of bytes).

Let’s say you want to encrypt the status of a candidate’s background check. Valid statuses are clear, consider, and fail. Even with the data encrypted, it’s trivial to map the ciphertext to a status.

lockbox = Lockbox.new(key: key)
lockbox.encrypt("fail").bytesize      # 32
lockbox.encrypt("clear").bytesize     # 33
lockbox.encrypt("consider").bytesize  # 36

Add padding to conceal the exact length of messages.

lockbox = Lockbox.new(key: key, padding: true)
lockbox.encrypt("fail").bytesize      # 44
lockbox.encrypt("clear").bytesize     # 44
lockbox.encrypt("consider").bytesize  # 44

The block size for padding is 16 bytes by default. Lockbox uses ISO/IEC 7816-4 padding, which uses at least one byte, so if we have a status larger than 15 bytes, it will have a different length than the others.

box.encrypt("length15status!").bytesize   # 44
box.encrypt("length16status!!").bytesize  # 60

Change the block size with:

Lockbox.new(padding: 32) # bytes

Associated Data

You can pass extra context during encryption to make sure encrypted data isn’t moved to a different context.

lockbox = Lockbox.new(key: key)
ciphertext = lockbox.encrypt(message, associated_data: "somecontext")

Without the same context, decryption will fail.

lockbox.decrypt(ciphertext, associated_data: "somecontext")  # success
lockbox.decrypt(ciphertext, associated_data: "othercontext") # fails

You can also use it with database fields and files.

class User < ApplicationRecord
  has_encrypted :email, associated_data: -> { code }
end

Binary Columns

You can use binary columns for the ciphertext instead of text columns.

class AddEmailCiphertextToUsers < ActiveRecord::Migration[7.1]
  def change
    add_column :users, :email_ciphertext, :binary
  end
end

Disable Base64 encoding to save space.

class User < ApplicationRecord
  has_encrypted :email, encode: false
end

or set it globally:

Lockbox.encode_attributes = false

Compatibility

It’s easy to read encrypted data in another language if needed.

For AES-GCM, the format is:

  • nonce (IV) - 12 bytes
  • ciphertext - variable length
  • authentication tag - 16 bytes

Here are some examples.

For XSalsa20, use the appropriate Libsodium library.

Migrating from Another Library

Lockbox makes it easy to migrate from another library without downtime. The example below uses attr_encrypted but the same approach should work for any library.

Let’s suppose your model looks like this:

class User < ApplicationRecord
  attr_encrypted :name, key: key
  attr_encrypted :email, key: key
end

Create a migration with:

class MigrateToLockbox < ActiveRecord::Migration[7.1]
  def change
    add_column :users, :name_ciphertext, :text
    add_column :users, :email_ciphertext, :text
  end
end

And add has_encrypted to your model with the migrating option:

class User < ApplicationRecord
  has_encrypted :name, :email, migrating: true
end

Then run:

Lockbox.migrate(User)

Once all records are migrated, remove the migrating option and the previous model code (the attr_encrypted methods in this example).

class User < ApplicationRecord
  has_encrypted :name, :email
end

Then remove the previous gem from your Gemfile and drop its columns.

class RemovePreviousEncryptedColumns < ActiveRecord::Migration[7.1]
  def change
    remove_column :users, :encrypted_name, :text
    remove_column :users, :encrypted_name_iv, :text
    remove_column :users, :encrypted_email, :text
    remove_column :users, :encrypted_email_iv, :text
  end
end

Upgrading

1.0.0

encrypts is now deprecated in favor of has_encrypted to avoid conflicting with Active Record encryption.

class User < ApplicationRecord
  has_encrypted :email
end

0.6.0

0.6.0 adds encrypted: true to Active Storage metadata for new files. This field is informational, but if you prefer to add it to existing files, use:

User.with_attached_license.find_each do |user|
  next unless user.license.attached?

  metadata = user.license.metadata
  unless metadata["encrypted"]
    user.license.blob.update!(metadata: metadata.merge("encrypted" => true))
  end
end

History

View the changelog

Contributing

Everyone is encouraged to help improve this project. Here are a few ways you can help:

To get started with development, install Libsodium and run:

git clone https://github.com/ankane/lockbox.git
cd lockbox
bundle install
bundle exec rake test

For security issues, send an email to the address on this page.

More Repositories

1

pghero

A performance dashboard for Postgres
Ruby
7,123
star
2

searchkick

Intelligent search made easy
Ruby
6,257
star
3

chartkick

Create beautiful JavaScript charts with one line of Ruby
Ruby
6,157
star
4

blazer

Business intelligence made simple
Ruby
4,351
star
5

ahoy

Simple, powerful, first-party analytics for Rails
Ruby
3,872
star
6

strong_migrations

Catch unsafe migrations in development
Ruby
3,662
star
7

groupdate

The simplest way to group temporal data
Ruby
3,617
star
8

pgsync

Sync data from one Postgres database to another
Ruby
2,787
star
9

the-ultimate-guide-to-ruby-timeouts

Timeouts for popular Ruby gems
Ruby
2,212
star
10

production_rails

Best practices for running Rails in production
1,975
star
11

dexter

The automatic indexer for Postgres
Ruby
1,491
star
12

chartkick.js

Create beautiful charts with one line of JavaScript
JavaScript
1,211
star
13

react-chartkick

Create beautiful JavaScript charts with one line of React
JavaScript
1,183
star
14

pretender

Log in as another user in Rails
Ruby
1,124
star
15

ahoy_email

First-party email analytics for Rails
Ruby
1,051
star
16

secure_rails

Rails security best practices
954
star
17

pgslice

Postgres partitioning as easy as pie
Ruby
953
star
18

mailkick

Email subscriptions for Rails
Ruby
847
star
19

vue-chartkick

Create beautiful JavaScript charts with one line of Vue
JavaScript
747
star
20

eps

Machine learning for Ruby
Ruby
609
star
21

awesome-legal

Awesome free legal documents for companies
589
star
22

searchjoy

Search analytics made easy
Ruby
579
star
23

polars-ruby

Blazingly fast DataFrames for Ruby
Ruby
563
star
24

torch.rb

Deep learning for Ruby, powered by LibTorch
Ruby
552
star
25

blind_index

Securely search encrypted database fields
Ruby
470
star
26

safely

Rescue and report exceptions in non-critical code
Ruby
470
star
27

authtrail

Track Devise login activity
Ruby
466
star
28

ahoy.js

Simple, powerful JavaScript analytics
JavaScript
463
star
29

multiverse

Multiple databases for Rails 🎉
Ruby
463
star
30

hightop

A nice shortcut for group count queries
Ruby
462
star
31

field_test

A/B testing for Rails
Ruby
460
star
32

s3tk

A security toolkit for Amazon S3
Python
439
star
33

disco

Recommendations for Ruby and Rails using collaborative filtering
Ruby
431
star
34

active_median

Median and percentile for Active Record, Mongoid, arrays, and hashes
Ruby
427
star
35

informers

State-of-the-art natural language processing for Ruby
Ruby
417
star
36

notable

Track notable requests and background jobs
Ruby
402
star
37

shorts

Short, random tutorials and posts
379
star
38

tensorflow-ruby

Deep learning for Ruby
Ruby
350
star
39

distribute_reads

Scale database reads to replicas in Rails
Ruby
328
star
40

slowpoke

Rack::Timeout enhancements for Rails
Ruby
327
star
41

prophet-ruby

Time series forecasting for Ruby
Ruby
321
star
42

rover

Simple, powerful data frames for Ruby
Ruby
311
star
43

groupdate.sql

The simplest way to group temporal data
PLpgSQL
280
star
44

kms_encrypted

Simple, secure key management for Lockbox and attr_encrypted
Ruby
235
star
45

jetpack

A friendly package manager for R
R
234
star
46

neighbor

Nearest neighbor search for Rails and Postgres
Ruby
230
star
47

rollup

Rollup time-series data in Rails
Ruby
230
star
48

hypershield

Shield sensitive data in Postgres and MySQL
Ruby
227
star
49

logstop

Keep personal data out of your logs
Ruby
218
star
50

pdscan

Scan your data stores for unencrypted personal data (PII)
Go
213
star
51

delete_in_batches

Fast batch deletes for Active Record and Postgres
Ruby
202
star
52

vega-ruby

Interactive charts for Ruby, powered by Vega and Vega-Lite
Ruby
192
star
53

mapkick

Create beautiful JavaScript maps with one line of Ruby
Ruby
173
star
54

dbx

A fast, easy-to-use database library for R
R
171
star
55

fastText-ruby

Efficient text classification and representation learning for Ruby
Ruby
162
star
56

autosuggest

Autocomplete suggestions based on what your users search
Ruby
162
star
57

swipeout

Swipe-to-delete goodness for the mobile web
JavaScript
159
star
58

pghero.sql

Postgres insights made easy
PLpgSQL
154
star
59

mainstreet

Address verification for Ruby and Rails
Ruby
149
star
60

or-tools-ruby

Operations research tools for Ruby
Ruby
139
star
61

mapkick.js

Create beautiful, interactive maps with one line of JavaScript
JavaScript
138
star
62

trend-ruby

Anomaly detection and forecasting for Ruby
Ruby
128
star
63

mitie-ruby

Named-entity recognition for Ruby
Ruby
122
star
64

barkick

Barcodes made easy
Ruby
120
star
65

ownership

Code ownership for Rails
Ruby
111
star
66

anomaly

Easy-to-use anomaly detection for Ruby
Ruby
98
star
67

errbase

Common exception reporting for a variety of services
Ruby
87
star
68

tokenizers-ruby

Fast state-of-the-art tokenizers for Ruby
Rust
81
star
69

ip_anonymizer

IP address anonymizer for Ruby and Rails
Ruby
79
star
70

str_enum

String enums for Rails
Ruby
75
star
71

faiss-ruby

Efficient similarity search and clustering for Ruby
C++
73
star
72

trend-api

Anomaly detection and forecasting API
R
71
star
73

archer

Rails console history for Heroku, Docker, and more
Ruby
70
star
74

onnxruntime-ruby

Run ONNX models in Ruby
Ruby
70
star
75

xgboost-ruby

High performance gradient boosting for Ruby
Ruby
69
star
76

secure-spreadsheet

Encrypt and password protect sensitive CSV and XLSX files
JavaScript
66
star
77

active_hll

HyperLogLog for Rails and Postgres
Ruby
66
star
78

guess

Statistical gender detection for Ruby
Ruby
60
star
79

morph

An encrypted, in-memory, key-value store
C++
59
star
80

lightgbm

High performance gradient boosting for Ruby
Ruby
56
star
81

midas-ruby

Edge stream anomaly detection for Ruby
Ruby
54
star
82

moves

Ruby client for Moves
Ruby
54
star
83

blingfire-ruby

High speed text tokenization for Ruby
Ruby
54
star
84

vowpalwabbit-ruby

Fast online machine learning for Ruby
Ruby
52
star
85

xlearn-ruby

High performance factorization machines for Ruby
Ruby
51
star
86

tomoto-ruby

High performance topic modeling for Ruby
C++
51
star
87

trove

Deploy machine learning models in Ruby (and Rails)
Ruby
50
star
88

ahoy_events

Simple, powerful event tracking for Rails
Ruby
42
star
89

mapkick-static

Create beautiful static maps with one line of Ruby
Ruby
42
star
90

practical-search

Let’s make search a better experience for our users
40
star
91

breakout-ruby

Breakout detection for Ruby
Ruby
40
star
92

plu

Price look-up codes made easy
Ruby
40
star
93

ngt-ruby

High-speed approximate nearest neighbors for Ruby
Ruby
39
star
94

gindex

Concurrent index migrations for Rails
Ruby
39
star
95

clockwork_web

A web interface for Clockwork
Ruby
38
star
96

ahoy_guide

A foundation of knowledge and libraries for solid analytics
38
star
97

notable_web

A web interface for Notable
HTML
36
star
98

AnomalyDetection.rb

Time series anomaly detection for Ruby
Ruby
34
star
99

khiva-ruby

High-performance time series algorithms for Ruby
Ruby
34
star
100

immudb-ruby

Ruby client for immudb, the immutable database
Ruby
34
star