Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Firebase SCrypt in Ruby. This file is Ruby version for this code:
require 'base64'
require 'scrypt'
def generate_derived_key password, salt, salt_separator, rounds, mem_cost
# Generates derived key from known parameters
n = 2 ** mem_cost
p = 1
r = rounds
# We're only using first 32 bytes of the derived key to match expected key length.
derived_key_length = 32
user_salt = Base64.decode64(salt).b
salt_separator = Base64.decode64(salt_separator).b
password = password.b
SCrypt::Engine.scrypt(password, (user_salt + salt_separator), n, r, p, derived_key_length)
def encrypt signer_key, derived_key
iv = 0.chr * 16
cipher = :CTR
cipher.iv = iv
cipher.key = derived_key
cipher.update(signer_key) +
def verify_password password, known_hash, salt, salt_separator, signer_key, rounds, mem_cost
derived_key = generate_derived_key password, salt, salt_separator, rounds, mem_cost
signer_key = Base64.decode64(signer_key).b
result = encrypt(signer_key, derived_key)
# We use `strict_encode64` instead of `encode64` to ignore new line in result
password_hash = Base64.strict_encode64(result).encode('utf-8')
# Please change this line to `Rack::Utils.secure_compare(a, b)` or `ActiveSupport::SecurityUtils.secure_compare(a, b)`
# If we use `==` method, it could lead to timing attacks.
password_hash == known_hash
# Testing
salt_separator = "Bw=="
signer_key = "jxspr8Ki0RYycVU8zykbdLGjFQ3McFUH0uiiTvC8pVMXAn210wjLNmdZJzxUECKbm0QsEmYUSDzZvpjeJ9WmXA=="
rounds= 8
password = "user1password"
salt = "42xEC+ixf3L2lw=="
is_valid = verify_password(password, password_hash, salt, salt_separator, signer_key, rounds, mem_cost)
puts is_valid
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment