Class: Rex::Proto::Kerberos::Crypto::BlockCipherBase

Inherits:
Object
  • Object
show all
Defined in:
lib/rex/proto/kerberos/crypto/block_cipher_base.rb

Direct Known Subclasses

AesBlockCipherBase, Des3CbcSha1, DesCbcMd5

Instance Method Summary collapse

Instance Method Details

#add_ones_complement(arr1, arr2) ⇒ Object

Add equal-length strings together with end-around carry.



146
147
148
149
150
151
152
153
154
155
156
# File 'lib/rex/proto/kerberos/crypto/block_cipher_base.rb', line 146

def add_ones_complement(arr1, arr2)
  n = arr1.length
  # Add all pairs of numbers
  v = arr1.zip(arr2).map { |a,b| a+b}
  
  while v.any? { |x| x > 0xff }
    v = v.length.times.map {|i| (v[i-n+1]>>8) + (v[i]&0xff)}
  end
          
  v
end

#checksum(key, msg_type, data) ⇒ String

Use this class’s encryption routines to create a checksum of the data based on the key and message type

Parameters:

  • key (String)

    the key to use to generate the checksum

  • msg_type (Integer)

    type of kerberos method in use

  • data (String)

    the data to checksum

Returns:

  • (String)

    the generated checksum



35
36
37
38
39
40
# File 'lib/rex/proto/kerberos/crypto/block_cipher_base.rb', line 35

def checksum(key, msg_type, data)
  kc = derive(key, [msg_type, 0x99].pack('NC'))
  hmac = OpenSSL::HMAC.digest(self.class::HASH_FUNCTION, kc, data)

  hmac[0, self.class::MAC_SIZE]
end

#decrypt(ciphertext_and_mac, key, msg_type) ⇒ String Also known as: decrypt_asn1

Decrypts the cipher

Parameters:

  • ciphertext_and_mac (String)

    the data to decrypt

  • key (String)

    the key to decrypt

  • msg_type (Integer)

    type of kerberos message

Returns:

  • (String)

    the decrypted cipher

Raises:



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rex/proto/kerberos/crypto/block_cipher_base.rb', line 49

def decrypt(ciphertext_and_mac, key, msg_type)
  ki = derive(key, [msg_type, 0x55].pack('NC'))
  ke = derive(key, [msg_type, 0xAA].pack('NC'))

  raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Ciphertext too short' if ciphertext_and_mac.length < (self.class::BLOCK_SIZE + self.class::MAC_SIZE)

  ciphertext = ciphertext_and_mac.slice(0..-(self.class::MAC_SIZE+1))
  mac = ciphertext_and_mac[-self.class::MAC_SIZE, self.class::MAC_SIZE]


  plaintext = decrypt_basic(ciphertext, ke)
  hmac = OpenSSL::HMAC.digest(self.class::HASH_FUNCTION, ki, plaintext)
  hmac_subset = hmac[0, self.class::MAC_SIZE]
  if mac != hmac_subset
      raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'HMAC integrity error'
  end

  # Discard the confounder.
  plaintext[self.class::BLOCK_SIZE, plaintext.length]
end

#encrypt(plaintext, key, msg_type, confounder: nil) ⇒ String

Encrypts the cipher

Parameters:

  • plaintext (String)

    the data to encrypt

  • key (String)

    the key to encrypt

  • msg_type (Integer)

    type of kerberos message

  • confounder (String) (defaults to: nil)

    Optionally force the confounder to a specific value

Returns:

  • (String)

    the encrypted data



83
84
85
86
87
88
89
90
91
# File 'lib/rex/proto/kerberos/crypto/block_cipher_base.rb', line 83

def encrypt(plaintext, key, msg_type, confounder: nil)
  ki = derive(key, [msg_type, 0x55].pack('NC'))
  ke = derive(key, [msg_type, 0xAA].pack('NC'))
  confounder = Rex::Text::rand_text(self.class::BLOCK_SIZE) if confounder == nil
  plaintext = confounder + pad_with_zeroes(plaintext, self.class::PADDING_SIZE)
  hmac = OpenSSL::HMAC.digest(self.class::HASH_FUNCTION, ki, plaintext)

  encrypt_basic(plaintext, ke) + hmac[0,self.class::MAC_SIZE]
end

#gss_unwrap(ciphertext, key, expected_sequence_number, is_initiator, use_acceptor_subkey: true) ⇒ Object

Raises:

  • (NotImplementedError)


97
98
99
# File 'lib/rex/proto/kerberos/crypto/block_cipher_base.rb', line 97

def gss_unwrap(ciphertext, key, expected_sequence_number, is_initiator, use_acceptor_subkey: true)
  raise NotImplementedError
end

#gss_wrap(plaintext, key, sequence_number, is_initiator, use_acceptor_subkey: true) ⇒ Object

Raises:

  • (NotImplementedError)


93
94
95
# File 'lib/rex/proto/kerberos/crypto/block_cipher_base.rb', line 93

def gss_wrap(plaintext, key, sequence_number, is_initiator, use_acceptor_subkey: true)
  raise NotImplementedError
end

#rotate_right(ba, nbits) ⇒ Object

Rotate the bytes in ba to the right by nbits bits.



138
139
140
141
142
143
# File 'lib/rex/proto/kerberos/crypto/block_cipher_base.rb', line 138

def rotate_right(ba, nbits)
  nbytes, remain = (nbits / 8) % ba.length, nbits % 8
  ba.length.times.map do |i|
    (ba[i-nbytes] >> remain) | ((ba[i-nbytes-1] << (8-remain)) & 0xff)
  end
end

#string_to_key(password, salt, params = nil) ⇒ String

Derive an encryption key based on a password and salt for the given cipher type

Parameters:

  • password (String)

    The password to use as the basis for key generation

  • salt (String)

    A salt (usually based on domain and username)

  • params (String) (defaults to: nil)

    A cipher-specific parameter (currently only used in AES, and even then not usually provided)

Returns:

  • (String)

    The derived key

Raises:

  • (NotImplementedError)


25
26
27
# File 'lib/rex/proto/kerberos/crypto/block_cipher_base.rb', line 25

def string_to_key(password, salt, params=nil)
  raise NotImplementedError
end