Skip to content

Instantly share code, notes, and snippets.

@joeljunstrom
Last active May 13, 2020 07:11
Show Gist options
  • Save joeljunstrom/42b04802e4391a7f5c9dd98d77e03ff7 to your computer and use it in GitHub Desktop.
Save joeljunstrom/42b04802e4391a7f5c9dd98d77e03ff7 to your computer and use it in GitHub Desktop.
# app/models/user.rb
class User < ApplicationRecord
attribute :otp_secret, :encrypted
attribute :otp_recovery_secret, :encrypted
end
# lib/types/encrypted_type.rb
require "crypter"
class EncryptedType < ActiveRecord::Type::Value
class << self
memoize def crypter(secret: Rails.application.secret_key_base)
Crypter.new(secret)
end
end
def type
:string
end
def cast(value)
value.to_s.presence
end
def deserialize(value)
EncryptedType.crypter.decrypt(value) if value.present?
end
def serialize(value)
EncryptedType.crypter.encrypt(value) if value.present?
end
end
# crypter.rb
require "rbnacl"
class Crypter
include Comparable
attr_reader :secret_key
def initialize(secret_key)
@secret_key = secret_key
end
def encrypt(value)
Base64.strict_encode64(engine.encrypt(value))
end
def decrypt(cipher)
engine.decrypt(Base64.strict_decode64(cipher))
end
def == other
other.is_a?(self.class) && other.secret_key == secret_key
end
memoize def engine
RbNaCl::SimpleBox.from_secret_key(
RbNaCl::Hash.sha256(secret_key)
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment