CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/kerberos/crypto/des3_cbc_sha1.rb
Views: 11766
1
# -*- coding: binary -*-
2
require 'rex/text'
3
4
module Rex
5
module Proto
6
module Kerberos
7
module Crypto
8
class Des3CbcSha1 < BlockCipherBase
9
include Rex::Proto::Kerberos::Crypto::Asn1Utils
10
SEED_SIZE = 21
11
BLOCK_SIZE = 8
12
PADDING_SIZE = 8
13
MAC_SIZE = 20
14
HASH_FUNCTION = 'SHA1'
15
16
# Derive an encryption key based on a password and salt for the given cipher type
17
#
18
# @param string [Stringl The password to use as the basis for key generation
19
# @param salt [String] A salt (usually based on domain and username)
20
# @param params [String] Unused for this encryption type
21
# @return [String] The derived key
22
def string_to_key(string, salt, params: nil)
23
raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Params not supported for DES' unless params == nil
24
utf8_encoded = (string + salt).encode('UTF-8').bytes
25
k = random_to_key(nfold(utf8_encoded, 21))
26
k = k.pack('C*')
27
result = derive(k, 'kerberos'.encode('UTF-8'))
28
29
result
30
end
31
32
def decrypt_asn1(ciphertext, key, msg_type)
33
result = decrypt(ciphertext, key, msg_type)
34
padding_removed = truncate_nulls_after_asn1(result)
35
end
36
37
private
38
39
# Decrypts the cipher using DES3-CBC-SHA1 schema
40
def decrypt_basic(ciphertext, key)
41
raise Rex::Proto::Kerberos::Model::Error::KerberosError, 'Ciphertext is not a multiple of block length' unless ciphertext.length % BLOCK_SIZE == 0
42
43
cipher = OpenSSL::Cipher.new('des-ede3-cbc')
44
if key.length != cipher.key_len
45
raise Rex::Proto::Kerberos::Model::Error::KerberosError, "Decryption key length must be #{cipher.key_len} for des-ede3-cbc"
46
end
47
cipher.decrypt
48
cipher.key = key
49
cipher.padding = 0
50
decrypted = cipher.update(ciphertext) + cipher.final
51
52
decrypted
53
end
54
55
# Encrypts the cipher using DES3-CBC-SHA1 schema
56
def encrypt_basic(plaintext, key)
57
cipher = OpenSSL::Cipher.new('des-ede3-cbc')
58
if key.length != cipher.key_len
59
raise Rex::Proto::Kerberos::Model::Error::KerberosError, "Encryption key length must be #{cipher.key_len} for des-ede3-cbc"
60
end
61
cipher.encrypt
62
cipher.key = key
63
cipher.padding = 0
64
encrypted = cipher.update(plaintext) + cipher.final
65
66
encrypted
67
end
68
69
def random_to_key(seed)
70
def expand(seed)
71
def parity(b)
72
# Return b with the low-order bit set to yield odd parity.
73
b &= ~1
74
b | (b.digits(2).count(1) + 1) % 2
75
end
76
77
raise Rex::Proto::Kerberos::Model::Error::KerberosError unless seed.length == 7
78
79
firstbytes = seed.map {|b| parity(b & ~1)}
80
tmp = 7.times.map { |i| (seed[i] & 1) << i+1 }
81
lastbyte = parity(tmp.sum)
82
keybytes = firstbytes + [lastbyte]
83
if _is_weak_des_key(keybytes)
84
keybytes[7] = keybytes[7] ^ 0xF0
85
end
86
87
keybytes
88
end
89
90
raise Rex::Proto::Kerberos::Model::Error::KerberosError unless seed.length == 21
91
92
subkeys = seed.each_slice(7).map { |slice| expand(slice) }
93
subkeys.flatten
94
end
95
end
96
end
97
end
98
end
99
end
100
101