Skip to content

Instantly share code, notes, and snippets.

@kyledrake
Created March 13, 2013 00:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kyledrake/5148363 to your computer and use it in GitHub Desktop.
Save kyledrake/5148363 to your computer and use it in GitHub Desktop.
Idea for storing an SSN (or CC#, or anything confidential) on a database, preventing an attacker from looking at it by hiding the private key on an offline machine using rbnacl.
require 'rbnacl'
# Idea for storing an SSN (or CC#, or anything confidential) on a database, preventing an attacker from looking at it by hiding the private key on an offline machine.
# Private key would be generated somewhere other than the web application.
private_key = Crypto::PrivateKey.generate
# Given to a web application:
public_key = private_key.public_key
crypto_box = Crypto::Box.new public_key, private_key # <- how do I not require the private key here? is it needed to encrypt?
nonce = Crypto::Random.random_bytes(24)
message = 'SSN, CC# go here'
cipher_ssn = crypto_box.box(nonce, message)
# nonce and cipher_ssn get stored to database. Attacker cannot view the SSN because the private key would not be available to the web application.
# meanwhile, somewhere else in the universe..
crypto_box = Crypto::Box.new(public_key, private_key)
puts crypto_box.open(nonce, cipher_ssn)
@namelessjon
Copy link

What you can do is something like what follows. Note that this throws away the mutual auth properties of the box construction, so we can no longer be sure it came from the web application, as anyone could do this. This can be mitigated by adding in second keypair for signing messages. (though any compromise of the server likely reveals the signing key, so it's not a perfect solution)

# Private key would be generated somewhere other than the web application.
private_key = Crypto::PrivateKey.generate

# Given to a web application:
public_key = private_key.public_key

# Web application receives an SSN!
# generate a new keypair (this is pretty fast in NaCl, as its a random 32byte number, then the public key gen isn't slow)
temp_private = Crypto::PrivateKey.generate

# make a box with the temp private
crypto_box = Crypto::Box.new public_key, temp_private

message = 'SSN, CC# go here'

# As we're making a new keypair just for this exchange, we can use whatever nonce we like.
# Note that we can do this ONLY because we're making a new keypair
nonce = "\0"*24

cipher_ssn = crypto_box.box(nonce, message)

# temp_private.public_key and cipher_ssn get stored in the database.  temp_private is thrown away!


# meanwhile, somewhere else in the universe..

crypto_box = Crypto::Box.new(cipher_ssn_public_key, private_key)

puts crypto_box.open(nonce, cipher_ssn)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment