Class: SSLShake::TLS
- Inherits:
-
Object
- Object
- SSLShake::TLS
- Includes:
- CommonHelpers
- Defined in:
- lib/sslshake/tls.rb
Overview
rubocop:disable Metrics/ClassLength
Constant Summary collapse
- VERSIONS =
{ 'ssl3' => '0300', 'tls1.0' => '0301', 'tls1.1' => '0302', 'tls1.2' => '0303', }.freeze
- CONTENT_TYPES =
{ 'ChangeCipherSpec' => '14', 'Alert' => '15', 'Handshake' => '16', 'Application' => '17', 'Heartbeat' => '18', }.freeze
- HANDSHAKE_TYPES =
{ 'HelloRequest' => '00', 'ClientHello' => '01', 'ServerHello' => '02', 'NewSessionTicket' => '04', 'Certificate' => '11', 'ServerKeyExchange' => '12', 'CertificateRequest' => '13', 'ServerHelloDone' => '14', 'CertificateVerify' => '15', 'ClientKeyExchange' => '16', 'Finished' => '20', }.freeze
- SSL3_CIPHERS =
::SSLShake::CIPHERS.select { |_, v| v < '001F' && v.length == 4 }
- TLS_CIPHERS =
::SSLShake::CIPHERS.select { |k, _| k.start_with? 'TLS_' }
- TLS10_CIPHERS =
TLS_CIPHERS.select { |_, v| v[0] == '0' && v[1] == '0' }
- OPENSSL_1_0_2_TLS10_CIPHERS =
Additional collection of ciphers used by different apps and versions
'c014c00ac022c021c02000390038003700360088008700860085c00fc00500350084c013c009c01fc01ec01d00330032008000810082008300310030009a0099009800970045004400430042c00ec004002f009600410007c011c0070066c00cc00200050004c012c008c01cc01bc01a001600130010000dc00dc003000a006300150012000f000c006200090065006400140011000e000b00080006000300ff'.freeze
- OPENSSL_1_0_2_TLS11_CIPHERS =
'c014c00ac022c021c02000390038003700360088008700860085c00fc00500350084c013c009c01fc01ec01d00330032008000810082008300310030009a0099009800970045004400430042c00ec004002f009600410007c011c0070066c00cc00200050004c012c008c01cc01bc01a001600130010000dc00dc003000a006300150012000f000c006200090065006400140011000e000b00080006000300ff'.freeze
- OPENSSL_1_0_2_TLS12_CIPHERS =
'cc14cc13cc15c030c02cc028c024c014c00a00a500a300a1009f006b006a006900680039003800370036c077c07300c400c300c200c1008800870086008500810080c032c02ec02ac026c00fc005c079c075009d003d003500c000840095c02fc02bc027c023c013c00900a400a200a0009e00670040003f003e0033003200310030c076c07200be00bd00bc00bb009a0099009800970045004400430042c031c02dc029c025c00ec004c078c074009c003c002f00ba0096004100070094c011c0070066c00cc002000500040092c012c008001600130010000dc00dc003000a009300150012000f000c000900ff'.freeze
Instance Method Summary collapse
- #hello(version, cipher_search = nil, extensions = nil) ⇒ Object
-
#parse_hello(socket, opts) ⇒ Object
rubocop:disable Meterics/AbcSize.
- #ssl_hello(content, version) ⇒ Object
- #ssl_record(content_type, content, version) ⇒ Object
Methods included from CommonHelpers
#cipher_string, #int_bytes, #socket_read
Instance Method Details
#hello(version, cipher_search = nil, extensions = nil) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/sslshake/tls.rb', line 64 def hello(version, cipher_search = nil, extensions = nil) case version when 'ssl3' ciphers = cipher_string(SSL3_CIPHERS, cipher_search) when 'tls1.0', 'tls1.1' ciphers = cipher_string(TLS_CIPHERS, cipher_search) (extensions ||= '') << '000f000101' # add Heartbeat extensions << '000d00140012040308040401050308050501080606010201' # add signature_algorithms extensions << '000b00020100' # add ec_points_format extensions << '000a000a0008fafa001d00170018' # add elliptic_curve when 'tls1.2' ciphers = cipher_string(TLS_CIPHERS, cipher_search) (extensions ||= '') << '000f000101' # add Heartbeat extensions << '000d00140012040308040401050308050501080606010201' # add signature_algorithms extensions << '000b00020100' # add ec_points_format extensions << '000a000a0008fafa001d00170018' # add elliptic_curve else fail UserError, "This version is not supported: #{version.inspect}" end hello_tls(version, ciphers, extensions || '') end |
#parse_hello(socket, opts) ⇒ Object
rubocop:disable Meterics/AbcSize
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/sslshake/tls.rb', line 86 def parse_hello(socket, opts) # rubocop:disable Meterics/AbcSize raw = socket_read(socket, 5, opts[:timeout], opts[:retries]) .unpack('H*')[0].upcase.scan(/../) type = raw.shift if type == CONTENT_TYPES['Alert'] return { 'error' => 'SSL Alert.' } end unless type == CONTENT_TYPES['Handshake'] return { 'error' => 'Failed to parse response. It is not an SSL handshake.' } end res = {} res['version'] = VERSIONS.key(raw.shift(2).join('')) len = raw.shift(2).join.to_i(16) res['raw'] = response = socket_read(socket, len, opts[:timeout], opts[:retries]) .unpack('H*')[0].upcase raw = response.scan(/../) res['handshake_type'] = HANDSHAKE_TYPES.key(raw.shift) _len = raw.shift(3) res['handshake_tls_version'] = VERSIONS.key(raw.shift(2).join('')) res['random'] = raw.shift(32).join('') len = raw.shift.to_i(16) res['session_id'] = raw.shift(len).join('') ciphers = case res['version'] when 'ssl3' SSL3_CIPHERS else TLS_CIPHERS end res['cipher_suite'] = ciphers.key(raw.shift(2).join('')) res['compression_method'] = raw.shift res['success'] = true res['success'] = (res['version'] == opts[:protocol]) unless opts[:protocol].nil? res rescue SystemCallError, Alert => _ return { 'error' => 'Failed to parse response. The connection was terminated.' } end |
#ssl_hello(content, version) ⇒ Object
56 57 58 59 60 61 62 |
# File 'lib/sslshake/tls.rb', line 56 def ssl_hello(content, version) ssl_record( CONTENT_TYPES['Handshake'], HANDSHAKE_TYPES['ClientHello'] + int_bytes(content.length / 2, 3) + content, version, ) end |
#ssl_record(content_type, content, version) ⇒ Object
51 52 53 54 |
# File 'lib/sslshake/tls.rb', line 51 def ssl_record(content_type, content, version) res = content_type + version + int_bytes(content.length / 2, 2) + content [res].pack('H*') end |