Skip to content

Secret Key Encryption

Tony Arcieri edited this page Aug 9, 2018 · 23 revisions

SecretBox: XSalsa20Poly1305

RbNaCl::SecretBox provides authenticated secret-key encryption.

Think of SecretBox like a safe: you can put information inside of it, and anyone with the combination can open it. Also, like any high security safe, any attempts to tamper with the safe or its contents will be detected.

Important Usage Notes

  • What the algorithm does for you: ensures data is kept confidential and that it cannot be undetectably modified by an attacker
  • What the algorithm expects from you: a secret key which must be kept confidential, and a unique ("nonce") value each time the SecretBox function is used. The SecretBox function must never ever be called with the same key:nonce pair!
  • What happens if you reuse a nonce: ALL IS LOST! complete loss of the confidentiality of your data (provided nonces are reused with the same key). Do NOT let this happen or you are breaking the security of your system.
  • What nonces should I use then?: Use SimpleBox if you're at all confused about what nonces to use.

Code Example

# Generate a random secret key (or perhaps use scrypt or Argon2)
key = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes)

# Initialize the box
secret_box = RbNaCl::SecretBox.new(key)

# First, make a nonce: A single-use value never repeated under the same key
# The nonce isn't secret, and can be sent with the ciphertext.
# The cipher instance has a nonce_bytes method for determining how many bytes should be in a nonce
nonce = RbNaCl::Random.random_bytes(secret_box.nonce_bytes)

# Encrypt a message with SecretBox
message = "..."
ciphertext = secret_box.encrypt(nonce, message)
#=> "..." # string of random looking bytes, 16 bytes longer than message.
# The extra 16-bytes are the authenticator

# Decrypt a message, passing in the same nonce we used to encrypt
decrypted_message = secret_box.decrypt(nonce, ciphertext)
#=> "..."

# But if the ciphertext has been tampered with:
secret_box.open(nonce, corrupted_ciphertext)
#=> RbNaCl::CryptoError exception is raised.
# Chosen ciphertext attacks are prevented by authentication and constant-time comparisons

Algorithm details

RDoc

AEAD: ChaCha20Poly1305

Authenticated Encryption with Additional Data (AEAD) modes provide a standard API for tamper-evident "authenticated" encryption which detects modifications to ciphertexts and also includes the ability to authenticate "additional" data sent in the clear along with an encrypted payload.

RbNaCl presently exposes a single AEAD cipher: ChaCha20Poly1305, the successor to the Salsa20Poly1305 authenticated stream cipher. ChaCha20 is designed to perform well in software on a wide range of CPU architectures, often performing nearly as well as hardware implementations of AES on the same CPUs.

Code Example

# generate a random secret key (or perhaps use scrypt or PBKDF2)
key = RbNaCl::Random.random_bytes(RbNaCl::SecretBox.key_bytes)

# Initialize a ChaCha20Poly1305 cipher object
cipher = RbNaCl::AEAD::ChaCha20Poly1305IETF.new(key)

# First, make a nonce: A single-use value never repeated under the same key
# The nonce isn't secret, and can be sent with the ciphertext.
# The cipher instance has a nonce_bytes method for determining how many bytes should be in a nonce
nonce = RbNaCl::Random.random_bytes(cipher.nonce_bytes)

# Encrypt a message with ChaCha20Poly1305
message = "..." # Message to be encrypted
ad = ""         # Additional data sent *in the clear* to be authenticated
ciphertext = cipher.encrypt(nonce, message, ad)
#=> "..." # string of random looking bytes, 16 bytes longer than message.
# The extra 16-bytes are the authenticator

# Decrypt a message, passing in the same nonce and additional data we used to encrypt
decrypted_message = cipher.decrypt(nonce, ciphertext, ad)
#=> "..."

# But if the ciphertext has been tampered with:
cipher.decrypt(nonce, ad, corrupted_ciphertext)
#=> RbNaCl::CryptoError exception is raised.
# Chosen ciphertext attacks are prevented by authentication and constant-time comparisons

Algorithm details

RDoc