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.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/aead/cipher.rb', line 140 def decrypt(nonce, aad, aead) nonce.force_encoding('ASCII-8BIT') if nonce.respond_to?(:force_encoding) aad.force_encoding('ASCII-8BIT') if aad.respond_to?(:force_encoding) aead.force_encoding('ASCII-8BIT') if aead.respond_to?(:force_encoding) _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 121 122 123 124 125 126 127 128 129 |
# File 'lib/aead/cipher.rb', line 111 def encrypt(nonce, aad, plaintext) nonce.force_encoding('ASCII-8BIT') if nonce.respond_to?(:force_encoding) aad.force_encoding('ASCII-8BIT') if aad.respond_to?(:force_encoding) plaintext.force_encoding('ASCII-8BIT') if plaintext.respond_to?(:force_encoding) _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 |