lib/blind_index.rb in blind_index-0.2.1 vs lib/blind_index.rb in blind_index-0.3.0
- old
+ new
@@ -6,24 +6,64 @@
require "blind_index/version"
module BlindIndex
class Error < StandardError; end
- def self.generate_bidx(value, key:, iterations:, expression: nil, **options)
- key = key.call if key.respond_to?(:call)
+ class << self
+ attr_accessor :default_options
+ end
+ self.default_options = {
+ iterations: 10000,
+ algorithm: :pbkdf2_hmac,
+ insecure_key: false,
+ encode: true
+ }
- raise BlindIndex::Error, "Missing key for blind index" unless key
+ def self.generate_bidx(value, key:, **options)
+ options = default_options.merge(options)
# apply expression
- value = expression.call(value) if expression
+ value = options[:expression].call(value) if options[:expression]
unless value.nil?
- # generate hash
- digest = OpenSSL::Digest::SHA256.new
- value = OpenSSL::PKCS5.pbkdf2_hmac(value.to_s, key, iterations, digest.digest_length, digest)
+ algorithm = options[:algorithm].to_sym
- # encode
- [value].pack("m")
+ key = key.call if key.respond_to?(:call)
+ raise BlindIndex::Error, "Missing key for blind index" unless key
+
+ key = key.to_s
+ unless options[:insecure_key] && algorithm == :pbkdf2_hmac
+ raise BlindIndex::Error, "Key must use binary encoding" if key.encoding != Encoding::BINARY
+ # raise BlindIndex::Error, "Key must not be ASCII" if key.bytes.all? { |b| b < 128 }
+ raise BlindIndex::Error, "Key must be 32 bytes" if key.bytesize != 32
+ end
+
+ # gist to compare algorithm results
+ # https://gist.github.com/ankane/fe3ac63fbf1c4550ee12554c664d2b8c
+ value =
+ case algorithm
+ when :scrypt
+ # n, p (keep r at 8)
+ SCrypt::Engine.scrypt(value.to_s, key, 4096, 8, 1, 32)
+ when :argon2
+ # t_cost, m_cost
+ [Argon2::Engine.hash_argon2i(value.to_s, key, 2, 12)].pack("H*")
+ when :pbkdf2_hmac
+ OpenSSL::PKCS5.pbkdf2_hmac(value.to_s, key, options[:iterations], 32, "sha256")
+ else
+ raise BlindIndex::Error, "Unknown algorithm"
+ end
+
+ encode = options[:encode]
+ if encode
+ if encode.respond_to?(:call)
+ encode.call(value)
+ else
+ [value].pack("m")
+ end
+ else
+ value
+ end
end
end
end
ActiveSupport.on_load(:active_record) do