You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cipher.rb 2.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. module CryptCheck
  2. module Tls
  3. class Cipher
  4. TYPES = {
  5. md5: %w(MD5),
  6. sha1: %w(SHA),
  7. psk: %w(PSK),
  8. srp: %w(SRP),
  9. anonymous: %w(ADH AECDH),
  10. dss: %w(DSS),
  11. null: %w(NULL),
  12. export: %w(EXP),
  13. des: %w(DES-CBC),
  14. rc2: %w(RC2),
  15. rc4: %w(RC4),
  16. des3: %w(3DES DES-CBC3),
  17. pfs: %w(DHE EDH ECDHE ECDH)
  18. }
  19. attr_reader :protocol, :name, :size, :dh
  20. def initialize(protocol, cipher, dh=nil)
  21. @protocol, @dh = protocol, dh
  22. @name, _, @size = cipher
  23. end
  24. TYPES.each do |name, ciphers|
  25. class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
  26. def self.#{name}?(cipher)
  27. #{ciphers}.any? { |c| /(^|-)#\{c\}(-|$)/ =~ cipher }
  28. end
  29. def #{name}?
  30. #{ciphers}.any? { |c| /(^|-)#\{c\}(-|$)/ =~ @name }
  31. end
  32. RUBY_EVAL
  33. end
  34. def ssl?
  35. sslv2? or sslv3?
  36. end
  37. def tls?
  38. tlsv1? or tlsv1_1? or tlsv1_2?
  39. end
  40. def colorize
  41. colors = case
  42. when dss?,
  43. anonymous?,
  44. null?,
  45. export?,
  46. md5?,
  47. des?,
  48. rc4?
  49. { color: :white, background: :red }
  50. when des3?
  51. { color: :yellow }
  52. when pfs?
  53. { color: :green }
  54. end
  55. @name.colorize colors
  56. end
  57. def state
  58. ok = Proc.new { |n| self.send "#{n}?" }
  59. {
  60. success: %i(pfs).select { |n| ok.call n },
  61. warning: %i().select { |n| ok.call n },
  62. danger: %i(des3).select { |n| ok.call n },
  63. error: %i(dss md5 psk srp anonymous null export des rc2 rc4).select { |n| ok.call n }
  64. }
  65. end
  66. def score
  67. state = self.state
  68. return :error unless state[:error].empty?
  69. return :danger unless state[:danger].empty?
  70. return :warning unless state[:warning].empty?
  71. return :success unless state[:success].empty?
  72. :none
  73. end
  74. PRIORITY = { success: 1, none: 2, warning: 3, danger: 4, error: 5 }
  75. def self.sort(ciphers)
  76. ciphers.sort do |a, b|
  77. error_a, error_b = PRIORITY[a.score], PRIORITY[b.score]
  78. compare = error_a <=> error_b
  79. next compare unless compare == 0
  80. size_a, size_b = a.size, b.size
  81. compare = size_b <=> size_a
  82. next compare unless compare == 0
  83. dh_a, dh_b = a.dh, b.dh
  84. next -1 if not dh_a and dh_b
  85. next 1 if dh_a and not dh_b
  86. next a.name <=> b.name if not dh_a and not dh_b
  87. compare = b.dh.size <=> a.dh.size
  88. next compare unless compare == 0
  89. a.name <=> b.name
  90. end
  91. end
  92. end
  93. end
  94. end