Class: Rex::Proto::Kerberos::Crypto::AesBlockCipherBase
- Inherits:
-
BlockCipherBase
- Object
- BlockCipherBase
- Rex::Proto::Kerberos::Crypto::AesBlockCipherBase
- Includes:
- GssNewEncryptionType, Utils
- Defined in:
- lib/rex/proto/kerberos/crypto/aes_block_cipher_base.rb
Overview
Base class for RFC3962 AES encryption classes
Direct Known Subclasses
Constant Summary collapse
- BLOCK_SIZE =
16
- PADDING_SIZE =
1
- MAC_SIZE =
12
- HASH_FUNCTION =
'SHA1'
Constants included from GssNewEncryptionType
GssNewEncryptionType::GSS_ACCEPTOR_SUBKEY, GssNewEncryptionType::GSS_HEADER_LEN, GssNewEncryptionType::GSS_SEALED, GssNewEncryptionType::GSS_SENT_BY_ACCEPTOR, GssNewEncryptionType::TOK_ID_GSS_WRAP
Instance Method Summary collapse
- #decrypt_basic(ciphertext, key) ⇒ Object
- #encrypt_basic(plaintext, key) ⇒ Object
-
#header_byte_count ⇒ Object
The number of bytes in the encrypted plaintext that precede the actual plaintext.
-
#string_to_key(password, salt, params: nil) ⇒ String
Derive an encryption key based on a password and salt for the given cipher type.
-
#trailing_byte_count ⇒ Object
The number of bytes in the encrypted plaintext that follow the actual plaintext.
Methods included from GssNewEncryptionType
Methods included from Utils
Methods inherited from BlockCipherBase
#add_ones_complement, #checksum, #decrypt, #encrypt, #gss_unwrap, #gss_wrap, #rotate_right
Instance Method Details
#decrypt_basic(ciphertext, key) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/rex/proto/kerberos/crypto/aes_block_cipher_base.rb', line 55 def decrypt_basic(ciphertext, key) raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Ciphertext too short' if ciphertext.length < BLOCK_SIZE cipher = OpenSSL::Cipher.new(self.class::DECRYPT_CIPHER_NAME) cipher.decrypt cipher.key = key cipher.padding = 0 if ciphertext.length == BLOCK_SIZE return cipher.update(ciphertext) + cipher.final end # Split the ciphertext into blocks. The last block may be partial. block_chunks = ciphertext.unpack('C*').each_slice(BLOCK_SIZE).to_a last_block_length = block_chunks[-1].length # CBC-decrypt all but the last two blocks. prev_chunk = [0] * BLOCK_SIZE plaintext_arr = [] block_chunks.slice(0..-3).each do |chunk| decrypted = cipher.update(chunk.pack('C*')) + cipher.final decrypted_arr = decrypted.unpack('C*') plaintext_arr += xor_bytes(decrypted_arr, prev_chunk) prev_chunk = chunk end # Decrypt the second-to-last cipher block. The left side of # the decrypted block will be the final block of plaintext # xor'd with the final partial cipher block; the right side # will be the omitted bytes of ciphertext from the final # block. decrypted = cipher.update(block_chunks[-2].pack('C*')) + cipher.final decrypted_arr = decrypted.unpack('C*') last_plaintext_arr = xor_bytes(decrypted_arr[0, last_block_length], block_chunks[-1]) omitted_arr = decrypted_arr[last_block_length, decrypted.length] # Decrypt the final cipher block plus the omitted bytes to get # the second-to-last plaintext block. decrypted = cipher.update((block_chunks[-1] + omitted_arr).pack('C*')) decrypted_arr = decrypted.unpack('C*') plaintext_arr += xor_bytes(decrypted_arr, prev_chunk) (plaintext_arr + last_plaintext_arr).pack('C*') end |
#encrypt_basic(plaintext, key) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/rex/proto/kerberos/crypto/aes_block_cipher_base.rb', line 34 def encrypt_basic(plaintext, key) raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Ciphertext too short' if plaintext.length < BLOCK_SIZE cipher = OpenSSL::Cipher.new(self.class::ENCRYPT_CIPHER_NAME) cipher.encrypt cipher.key = key cipher.padding = 0 padded = pad_with_zeroes(plaintext, BLOCK_SIZE) ciphertext = cipher.update(padded) + cipher.final if plaintext.length > BLOCK_SIZE # Swap the last two ciphertext blocks and truncate the # final block to match the plaintext length. last_block_length = plaintext.length % BLOCK_SIZE last_block_length = BLOCK_SIZE if last_block_length == 0 ciphertext = ciphertext[0, ciphertext.length - 32] + ciphertext[-BLOCK_SIZE, BLOCK_SIZE] + ciphertext[-32, last_block_length] end ciphertext end |
#header_byte_count ⇒ Object
The number of bytes in the encrypted plaintext that precede the actual plaintext
103 104 105 |
# File 'lib/rex/proto/kerberos/crypto/aes_block_cipher_base.rb', line 103 def header_byte_count BLOCK_SIZE end |
#string_to_key(password, salt, params: nil) ⇒ String
Derive an encryption key based on a password and salt for the given cipher type
26 27 28 29 30 31 32 |
# File 'lib/rex/proto/kerberos/crypto/aes_block_cipher_base.rb', line 26 def string_to_key(password, salt, params: nil) params = "\x00\x00\x10\x00" if params == nil iterations = params.unpack('N')[0] seed = OpenSSL::KDF.pbkdf2_hmac(password, salt: salt, iterations: iterations, length: self.class::SEED_SIZE, hash: HASH_FUNCTION) tkey = random_to_key(seed) derive(tkey, 'kerberos'.encode('utf-8')) end |
#trailing_byte_count ⇒ Object
The number of bytes in the encrypted plaintext that follow the actual plaintext
110 111 112 |
# File 'lib/rex/proto/kerberos/crypto/aes_block_cipher_base.rb', line 110 def trailing_byte_count MAC_SIZE end |