Class: Net::TTI::Crypto

Inherits:
Object
  • Object
show all
Defined in:
lib/net/tti/crypto.rb

Class Method Summary collapse

Class Method Details

.create_combined_session_key_hash_10g(server_session_key, client_session_key) ⇒ String

Generates the combined session key hash, for use in encrypting the password in authentication.

Parameters:

  • server_session_key (String)

    The unencrypted server session key, as a binary packed string.

  • client_session_key (String)

    The unencrypted client session key, as a binary packed string.

Returns:

  • (String)

    The hash of the combined session key, as a binary packed string.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/net/tti/crypto.rb', line 111

def self.create_combined_session_key_hash_10g( server_session_key, client_session_key )
  # Unpack the session keys into byte arrays
  server_key_bytes = server_session_key.unpack( "C*" )
  client_key_bytes = client_session_key.unpack( "C*" )
  combo_session_key = ""

  # XOR bytes 17-32 of the session keys to make the combined session key
  for byte_itr in (16..31)
    combo_session_key += (server_key_bytes[ byte_itr ] ^ client_key_bytes[ byte_itr ]).chr
  end

  # Hash the combined session key
  return md5_digest( combo_session_key )
end

.create_combined_session_key_hash_11g(server_session_key, client_session_key) ⇒ String

Generates the combined session key hash, for use in encrypting the password in authentication.

Parameters:

  • server_session_key (String)

    The unencrypted server session key, as a binary packed string.

  • client_session_key (String)

    The unencrypted client session key, as a binary packed string.

Returns:

  • (String)

    The hash of the combined session key, as a binary packed string.



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/net/tti/crypto.rb', line 135

def self.create_combined_session_key_hash_11g( server_session_key, client_session_key )
  # make combined session key
  server_key_bytes = server_session_key.unpack( "C*" )
  client_key_bytes = client_session_key.unpack( "C*" )
  combo_session_key = ""
  for byte_itr in (16..39)
    combo_session_key += (server_key_bytes[ byte_itr ] ^ client_key_bytes[ byte_itr ]).chr
  end

  # hash combined session key
  combo_session_key = ( md5_digest(combo_session_key[0,16]) +
                        md5_digest(combo_session_key[16,combo_session_key.length]) )
  combo_session_key = combo_session_key[0,24]

  return combo_session_key
end

.get_10g_auth_values(username, password, enc_server_session_key) ⇒ Array<String>

Generates the encrypted password and encrypted client session key for authentication with a 10g server.

Parameters:

  • username (String)

    The username for authentication.

  • password (String)

    The password for authentication.

  • enc_server_session_key (String)

    The encrypted server session key. provided by the server. This should be a 32-byte binary packed string.

Returns:

  • (Array<String>)

    The encrypted password and the encrypted client session key to use to authenticate with the server. These are returned as binary packed strings.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/net/tti/crypto.rb', line 15

def self.get_10g_auth_values( username, password, enc_server_session_key )
  # Hash the password and pad it to 16 bytes. This will be used as the key
  # for encrypting the client session key and decrypting the server session key.
  password_hash = hash_password_10g( username, password )
  password_hash += "\0" * 8

  # TODO: make random client session key
  client_session_key = "FAF5034314546426F329B1DAB1CDC5B8FF94349E0875623160350B0E13A0DA36".tns_unhexify

  # Encrypt client session key and decrypt the server session key, using the
  # password hash as a key.
  enc_client_session_key = openssl_encrypt( "AES-128-CBC", password_hash, nil,     client_session_key )
  server_session_key =     openssl_decrypt( "AES-128-CBC", password_hash, nil, enc_server_session_key )

  # Make the combined session key hash. This is used as the key to encrypt
  # the password.
  combo_session_key = create_combined_session_key_hash_10g( server_session_key, client_session_key )

  # TODO: make random salt
  salt = "4C31AFE05F3B012C0AE9AB0CDFF0C508".tns_unhexify
  # Encrypt the salted password
  enc_password = openssl_encrypt( "AES-128-CBC", combo_session_key, nil, salt + password, true )

  return enc_password, enc_client_session_key
end

.get_11g_auth_values(password, enc_server_session_key, auth_vfr_data) ⇒ Array<String>

Generates the encrypted password and encrypted client session key for authentication with an 11g server.

Parameters:

  • password (String)

    The password for authentication.

  • enc_server_session_key (String)

    The encrypted server session key. provided by the server. This should be a 48-byte binary packed string.

  • auth_vfr_data (String)

    The value from the AUTH_VFR_DATA key-value pair provided by the server.

Returns:

  • (Array<String>)

    The encrypted password and the encrypted client session key to use to authenticate with the server. These are returned as binary packed strings.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/net/tti/crypto.rb', line 52

def self.get_11g_auth_values( password, enc_server_session_key, auth_vfr_data )
  # Hash the password and auth_vfr_data and pad it to 24 bytes. This will be
  # used as the key for encrypting the client session key and decrypting the
  # server session key.
  password_hash = sha1_digest( password + auth_vfr_data ) + ("\0" * 4)

  # TODO: make random client session key
  client_session_key = "080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808".tns_unhexify

  # Encrypt client session key and decrypt the server session key, using the
  # password hash as a key.
  enc_client_session_key = openssl_encrypt( "AES-192-CBC", password_hash, nil,     client_session_key )
  server_session_key =     openssl_decrypt( "AES-192-CBC", password_hash, nil, enc_server_session_key )

  # Make the combined session key hash. This is used as the key to encrypt
  # the password.
  combo_session_key = create_combined_session_key_hash_11g( server_session_key, client_session_key )

  # TODO: make random salt
  salt = "4C31AFE05F3B012C0AE9AB0CDFF0C508".tns_unhexify
  # Encrypt the salted password
  enc_password = openssl_encrypt( "AES-192-CBC", combo_session_key, nil, salt + password, true )

  return enc_password, enc_client_session_key
end

.hash_password_10g(username, password) ⇒ String

Generates the password hash for use in 10g authentication.

Parameters:

  • username (String)

    The username for authentication.

  • password (String)

    The password for authentication.

Returns:

  • (String)

    The password hash, as a binary packed string.



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/net/tti/crypto.rb', line 85

def self.hash_password_10g( username, password )
  uspw = (username + password).upcase().encode( Encoding::UTF_16BE )
  key = "0123456789abcdef".tns_unhexify   # fixed key used for 10g hashing

  # Pad the username-password to an 8-byte boundary
  if ( uspw.length % 4 > 0 )
    padding_length = 4 - ( uspw.length % 4 )
    uspw += ("\0".encode( Encoding::UTF_16BE )) * padding_length
  end

  key2 = openssl_encrypt( "DES-CBC", key, nil, uspw, false )
  key2 = key2[-8,8]

  pwhash = openssl_encrypt( "DES-CBC", key2, nil, uspw, false )
  pwhash = pwhash[-8,8]
end

.md5_digest(input_str) ⇒ Object

Returns the MD5 digest (as a binary string) for the given input string.

Returns:

  • the MD5 digest (as a binary string) for the given input string



176
177
178
179
180
# File 'lib/net/tti/crypto.rb', line 176

def self.md5_digest(input_str)
  digester=Digest::MD5.new()
  digester.update(input_str)
  return digester.digest
end

.openssl_decrypt(cipher, key, iv, data, padding = false) ⇒ Object

Helper function for decryption.



165
166
167
168
169
170
171
172
173
# File 'lib/net/tti/crypto.rb', line 165

def self.openssl_decrypt( cipher, key, iv, data, padding=false )
  cipher = OpenSSL::Cipher.new( cipher )
  cipher.decrypt
  cipher.key = key
  cipher.iv = iv unless iv.nil?
  cipher.padding = 0 unless padding

  ciphertext = cipher.update( data ) + cipher.final
end

.openssl_encrypt(cipher, key, iv, data, padding = false) ⇒ Object

Helper function for encryption.



154
155
156
157
158
159
160
161
162
# File 'lib/net/tti/crypto.rb', line 154

def self.openssl_encrypt( cipher, key, iv, data, padding=false )
  cipher = OpenSSL::Cipher.new( cipher )
  cipher.encrypt
  cipher.key = key
  cipher.iv = iv unless iv.nil?
  cipher.padding = 0 unless padding

  ciphertext = cipher.update( data ) + cipher.final
end

.sha1_digest(input_str) ⇒ Object

Returns the SHA1 digest (as a binary string) for the given input string.

Returns:

  • the SHA1 digest (as a binary string) for the given input string



183
184
185
186
187
# File 'lib/net/tti/crypto.rb', line 183

def self.sha1_digest(input_str)
  digester=Digest::SHA1.new()
  digester.update(input_str)
  return digester.digest
end