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.

grade.rb 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. module CryptCheck
  2. module Tls
  3. class Grade
  4. attr_reader :server, :protocol_score, :key_exchange_score, :cipher_strengths_score, :score, :grade, :error, :danger, :warning, :success
  5. def initialize(server)
  6. @server = server
  7. calculate_protocol_score
  8. calculate_key_exchange_score
  9. calculate_cipher_strengths_score
  10. @score = @protocol_score*0.3 + @key_exchange_score*0.3 + @cipher_strengths_score*0.4
  11. calculate_states
  12. calculate_grade
  13. end
  14. def display
  15. color = case self.grade
  16. when 'A+' then :blue
  17. when 'A' then :green
  18. when 'B', 'C' then :yellow
  19. when 'E', 'F' then :red
  20. when 'M', 'T' then { color: :white, background: :red }
  21. end
  22. Logger.info { "Grade : #{self.grade.colorize color }" }
  23. Logger.info { '' }
  24. Logger.info { "Protocole : #{self.protocol_score} / 100" }
  25. Logger.info { "Key exchange : #{self.key_exchange_score} / 100" }
  26. Logger.info { "Ciphers strength : #{self.cipher_strengths_score} / 100" }
  27. Logger.info { "Overall score : #{self.score} / 100" }
  28. Logger.info { '' }
  29. Logger.info { "Errors : #{self.error.join(' ').colorize :red }" } unless self.error.empty?
  30. Logger.info { "Warnings : #{self.warning.join(' ').colorize :yellow }" } unless self.warning.empty?
  31. Logger.info { "Best practices : #{self.success.join(' ').colorize :green }" } unless self.success.empty?
  32. end
  33. private
  34. def calculate_grade
  35. @grade = case @score
  36. when 0...20 then 'F'
  37. when 20...35 then 'E'
  38. when 35...50 then 'D'
  39. when 50...65 then 'C'
  40. when 65...80 then 'B'
  41. else 'A'
  42. end
  43. @grade = [@grade, 'B'].max if !@server.tlsv1_2? or @server.key_size < 2048
  44. @grade = [@grade, 'C'].max if @server.des3?
  45. @grade = [@grade, 'F'].max unless @error.empty?
  46. @grade = 'M' unless @server.cert_valid
  47. @grade = 'T' unless @server.cert_trusted
  48. @grade = 'A+' if @grade == 'A' and @error.empty? and @warning.empty? and (all_success & @success) == all_success
  49. end
  50. def calculate_states
  51. ok = Proc.new { |n| @server.send "#{n}?" }
  52. state = {
  53. success: %i().select { |n| ok.call n },
  54. warning: %i(sha1_sig).select { |n| ok.call n },
  55. danger: %i(des3).select { |n| ok.call n },
  56. error: %i(md5_sig md5 sslv2 sslv3 anonymous dss null export des rc4).select { |n| ok.call n }
  57. }
  58. state[:success] << :pfs if @server.pfs_only?
  59. @success, @warning, @danger, @error = state[:success], state[:warning], state[:danger], state[:error]
  60. end
  61. ALL_ERROR = %i(md5_sig md5 anonymous dss null export des rc4)
  62. def all_error
  63. ALL_ERROR
  64. end
  65. ALL_WARNING = %i(sha1_sig des3)
  66. def all_warning
  67. ALL_WARNING
  68. end
  69. ALL_SUCCESS = %i(pfs)
  70. def all_success
  71. ALL_SUCCESS
  72. end
  73. METHODS_SCORES = { SSLv2: 0, SSLv3: 20, TLSv1: 60, TLSv1_1: 80, TLSv1_2: 100 }
  74. def calculate_protocol_score
  75. @protocol_score = @server.supported_protocols.collect { |p| METHODS_SCORES[p] }.min
  76. end
  77. def calculate_key_exchange_score
  78. @key_exchange_score = case @server.key_size
  79. when 0 then 0
  80. when 0...512 then 10
  81. when 512...1024 then 20
  82. when 1024...3072 then 50
  83. when 3072...4096 then 90
  84. else 100
  85. end
  86. end
  87. def calculate_cipher_strengths_score
  88. @cipher_strengths_score = case @server.cipher_size
  89. when 0 then 0
  90. when 0...112 then 10
  91. when 112...128 then 50
  92. when 128...256 then 90
  93. else 100
  94. end
  95. end
  96. end
  97. end
  98. end