Class: AEAD::Cipher
- Inherits:
-
Object
- Object
- AEAD::Cipher
- Defined in:
- lib/aead/cipher.rb
Overview
Wraps AEAD ciphers in a simplified interface.
Direct Known Subclasses
AES_256_CBC_HMAC_SHA_256, AES_256_CTR_HMAC_SHA_256, AES_256_GCM
Defined Under Namespace
Modules: AES_HMAC Classes: AES_256_CBC_HMAC_SHA_256, AES_256_CTR_HMAC_SHA_256, AES_256_GCM
Class Method Summary collapse
-
.generate_key ⇒ String
Returns a securely-generated key of appropriate length for the current Cipher.
-
.generate_nonce ⇒ String
Returns a unique nonce for the current Cipher.
-
.new(algorithm) ⇒ Class
Returns a particular Cipher implementation.
-
.signature_compare(left, right) ⇒ Boolean
Does a constant-time comparison between two strings.
Instance Method Summary collapse
-
#decrypt(nonce, aad, aead) ⇒ String
Decrypts a plaintext using the current Cipher.
-
#encrypt(nonce, aad, plaintext) ⇒ String
Encrypts a plaintext using the current Cipher.
-
#key_len ⇒ Integer
The length of keys of encryption keys used by the current Cipher.
-
#nonce_len ⇒ Integer
The length of nonces used by the current Cipher.
Class Method Details
.generate_key ⇒ String
Returns a securely-generated key of appropriate length for the current Cipher.
36 37 38 |
# File 'lib/aead/cipher.rb', line 36 def self.generate_key SecureRandom.random_bytes(self.key_len) end |
.generate_nonce ⇒ String
Returns a unique nonce for the current Cipher.
45 46 47 |
# File 'lib/aead/cipher.rb', line 45 def self.generate_nonce AEAD::Nonce.generate end |
.new(algorithm) ⇒ Class
Returns a particular Cipher implementation.
21 22 23 24 25 26 27 28 |
# File 'lib/aead/cipher.rb', line 21 def self.new(algorithm) # run normal Class#new if we're being called from a subclass return super unless self == AEAD::Cipher # TODO: ciphers should register themselves, as opposed to using a # potentiall-unsafe const_get self.const_get algorithm.tr('-', '_').upcase end |
.signature_compare(left, right) ⇒ Boolean
Does a constant-time comparison between two strings. Useful to avoid timing attacks when comparing a generated signature against a user-provided signature.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/aead/cipher.rb', line 58 def self.signature_compare(left, right) # short-circuit if the lengths are inequal return false if left.to_s.bytesize != right.bytesize # Constant-time string comparison algorithm: # 1. Break both strings into bytes # 2. Subtract the strings from one-another, byte by byte # (any non-equal bytes will subtract to a nonzero value) # 3. OR the XOR'd bytes together # 4. If the result is nonzero, the strings differed. left = left.bytes.to_a right = right.bytes.to_a result = 0 left.length.times do |i| result |= left[i] - right[i] end result == 0 end |
Instance Method Details
#decrypt(nonce, aad, aead) ⇒ String
Decrypts a plaintext using the current Cipher.
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/aead/cipher.rb', line 131 def decrypt(nonce, aad, aead) _verify_nonce_bytesize(nonce, self.nonce_len) self._decrypt( _pad_nonce(nonce), aad, _extract_ciphertext(aead, self.tag_len), _extract_tag(aead, self.tag_len) ) end |
#encrypt(nonce, aad, plaintext) ⇒ String
Encrypts a plaintext using the current Cipher.
IMPORTANT: Do not ever encrypt data using the same nonce more than once given a particular secret key. Doing so will violate the security guarantees of the AEAD cipher.
111 112 113 114 115 116 117 118 119 120 |
# File 'lib/aead/cipher.rb', line 111 def encrypt(nonce, aad, plaintext) _verify_nonce_bytesize(nonce, self.nonce_len) _verify_plaintext_presence(plaintext) self._encrypt( _pad_nonce(nonce), aad, plaintext ) end |
#key_len ⇒ Integer
The length of keys of encryption keys used by the current Cipher.
84 85 86 |
# File 'lib/aead/cipher.rb', line 84 def key_len self.class.key_len end |
#nonce_len ⇒ Integer
The length of nonces used by the current Cipher.
93 94 95 |
# File 'lib/aead/cipher.rb', line 93 def nonce_len self.class.nonce_len end |