Class: CoinOp::Crypto::PassphraseBox
- Inherits:
-
Object
- Object
- CoinOp::Crypto::PassphraseBox
- Extended by:
- Encodings
- Includes:
- Encodings
- Defined in:
- lib/coin-op/crypto.rb
Overview
A wrapper for NaCl’s Secret Box, taking a user-supplied passphrase and deriving a secret key, rather than using a (far more secure) randomly generated secret key.
NaCl Secret Box provides a high level interface for authenticated symmetric encryption. When creating the box, you must supply a key. When using the box to encrypt, you must supply a random nonce. Nonces must never be re-used.
Secret Box decryption requires the ciphertext and the nonce used to create it.
The PassphraseBox class takes a passphrase, rather than a randomly generated key. It uses PBKDF2 to generate a key that, while not random, is somewhat resistant to brute force attacks. Great care should still be taken to avoid passphrases that are subject to dictionary attacks.
Constant Summary collapse
- ITERATIONS =
PBKDF2 work factor
100_000
Instance Attribute Summary collapse
-
#salt ⇒ Object
readonly
Returns the value of attribute salt.
Class Method Summary collapse
-
.decrypt(passphrase, hash) ⇒ Object
PassphraseBox.decrypt “my great password”, :salt => salt, :nonce => nonce, :ciphertext => ciphertext.
-
.encrypt(passphrase, plaintext) ⇒ Object
Given passphrase and plaintext as strings, returns a Hash containing the ciphertext and other values needed for later decryption.
Instance Method Summary collapse
- #decrypt(nonce, ciphertext) ⇒ Object
- #encrypt(plaintext) ⇒ Object
-
#initialize(passphrase, salt = nil, iterations = nil) ⇒ PassphraseBox
constructor
Initialize with an existing salt and iterations to allow decryption.
Methods included from Encodings
base58, decode_base58, decode_hex, hex
Constructor Details
#initialize(passphrase, salt = nil, iterations = nil) ⇒ PassphraseBox
Initialize with an existing salt and iterations to allow decryption. Otherwise, creates new values for these, meaning it creates an entirely new secret-box.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/coin-op/crypto.rb', line 57 def initialize(passphrase, salt=nil, iterations=nil) @salt = salt || RbNaCl::Random.random_bytes(16) @iterations = iterations || ITERATIONS key = OpenSSL::PKCS5.pbkdf2_hmac_sha1( passphrase, @salt, # TODO: decide on a very safe work factor # https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet # @iterations, # number of iterations 32 # key length in bytes ) @box = RbNaCl::SecretBox.new(key) end |
Instance Attribute Details
#salt ⇒ Object (readonly)
Returns the value of attribute salt.
52 53 54 |
# File 'lib/coin-op/crypto.rb', line 52 def salt @salt end |
Class Method Details
.decrypt(passphrase, hash) ⇒ Object
PassphraseBox.decrypt “my great password”,
:salt => salt, :nonce => nonce, :ciphertext => ciphertext
45 46 47 48 49 50 |
# File 'lib/coin-op/crypto.rb', line 45 def self.decrypt(passphrase, hash) salt, nonce, ciphertext = hash.values_at(:salt, :nonce, :ciphertext).map {|s| decode_hex(s) } box = self.new(passphrase, salt, hash[:iterations]) box.decrypt(nonce, ciphertext) end |
.encrypt(passphrase, plaintext) ⇒ Object
Given passphrase and plaintext as strings, returns a Hash containing the ciphertext and other values needed for later decryption. Binary values are encoded as hexadecimal strings.
37 38 39 40 |
# File 'lib/coin-op/crypto.rb', line 37 def self.encrypt(passphrase, plaintext) box = self.new(passphrase) box.encrypt(plaintext) end |
Instance Method Details
#decrypt(nonce, ciphertext) ⇒ Object
83 84 85 |
# File 'lib/coin-op/crypto.rb', line 83 def decrypt(nonce, ciphertext) @box.decrypt(nonce, ciphertext) end |
#encrypt(plaintext) ⇒ Object
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/coin-op/crypto.rb', line 72 def encrypt(plaintext) nonce = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.nonce_bytes) ciphertext = @box.encrypt(nonce, plaintext) { :iterations => @iterations, :salt => hex(@salt), :nonce => hex(nonce), :ciphertext => hex(ciphertext) } end |