@@ -1,4 +1,5 @@ | |||
*.iml | |||
*.gem | |||
Gemfile.lock | |||
/.idea/ | |||
/html/ | |||
@@ -1,21 +1,2 @@ | |||
source 'https://rubygems.org' | |||
gem 'rake' | |||
gem 'httparty' | |||
gem 'nokogiri' | |||
gem 'net-ssh', '>= 2.9.2.beta' | |||
gem 'net-scp' | |||
gem 'tcp_timeout' | |||
gem 'parallel' | |||
gem 'ruby-progressbar' | |||
gem 'logging' | |||
#gem 'activerecord' | |||
#gem 'sqlite3' | |||
gem 'colorize' | |||
group :test do | |||
gem 'rspec' | |||
gem 'webmock' | |||
end | |||
gem 'debase' | |||
gemspec |
@@ -2,7 +2,6 @@ | |||
$:.unshift File.expand_path File.join File.dirname(__FILE__), '../lib' | |||
require 'rubygems' | |||
require 'bundler/setup' | |||
require 'logging' | |||
require 'cryptcheck' | |||
GROUP_NAME = 'Top 100 Alexa' | |||
@@ -2,7 +2,6 @@ | |||
$:.unshift File.expand_path File.join File.dirname(__FILE__), '../lib' | |||
require 'rubygems' | |||
require 'bundler/setup' | |||
require 'logging' | |||
require 'cryptcheck' | |||
name = ARGV[0] | |||
@@ -2,7 +2,6 @@ | |||
$:.unshift File.expand_path File.join File.dirname(__FILE__), '../lib' | |||
require 'rubygems' | |||
require 'bundler/setup' | |||
require 'logging' | |||
require 'cryptcheck' | |||
name = ARGV[0] | |||
@@ -0,0 +1,38 @@ | |||
# coding: utf-8 | |||
lib = File.expand_path('../lib', __FILE__) | |||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) | |||
Gem::Specification.new do |spec| | |||
spec.name = 'cryptcheck' | |||
spec.version = '1.0.0' | |||
spec.authors = ['Aeris'] | |||
spec.email = ['aeris+tls@imirhil.fr'] | |||
spec.summary = %q{Check best practices on crypto-stack implementation} | |||
spec.description = %q{Verify if best practices are well implemented on current crypto-stack (TLS & SSH) protocol (HTTPS, SMTP, XMPP, SSH & VPN)} | |||
spec.homepage = 'https://tls.imirhil.fr' | |||
spec.license = 'AGPLv3+' | |||
if spec.respond_to?(:metadata) | |||
spec.metadata['allowed_push_host'] = 'TODO: Set to "http://mygemserver.com"' | |||
else | |||
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' | |||
end | |||
spec.files = { '*.rb' => %w(lib) } | |||
.collect_concat { |e, ds| ds.collect_concat { |d| Dir[File.join d, '**', e] } } | |||
# spec.bindir = 'bin' | |||
# spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } | |||
# spec.test_files = spec.files.grep(%r{^spec/}) | |||
spec.require_paths = %w(lib) | |||
spec.add_development_dependency 'bundler', '~> 1.9', '>= 1.9.8' | |||
spec.add_development_dependency 'rake', '~> 10.4', '>= 10.4.2' | |||
spec.add_development_dependency 'rspec', '~> 3.2', '>= 3.2.0' | |||
spec.add_dependency 'httparty', '~> 0.13', '>= 0.13.3' | |||
spec.add_dependency 'nokogiri', '~> 1.6', '>= 1.6.6' | |||
spec.add_dependency 'parallel', '~> 1.3', '>= 1.3.4' | |||
spec.add_dependency 'ruby-progressbar', '~> 1.7', '>= 1.7.1' | |||
spec.add_dependency 'colorize', '~> 0.7', '>= 0.7.7' | |||
end |
@@ -5,6 +5,7 @@ module CryptCheck | |||
autoload :Logger, 'cryptcheck/logger' | |||
autoload :Tls, 'cryptcheck/tls' | |||
module Tls | |||
autoload :Cipher, 'cryptcheck/tls/cipher' | |||
autoload :Server, 'cryptcheck/tls/server' | |||
autoload :TcpServer, 'cryptcheck/tls/server' | |||
autoload :UdpServer, 'cryptcheck/tls/server' | |||
@@ -1,5 +1,4 @@ | |||
require 'erb' | |||
require 'logging' | |||
require 'parallel' | |||
module CryptCheck | |||
@@ -7,33 +6,6 @@ module CryptCheck | |||
MAX_ANALYSIS_DURATION = 600 | |||
PARALLEL_ANALYSIS = 10 | |||
TYPES = { | |||
md5: %w(MD5), | |||
sha1: %w(SHA), | |||
psk: %w(PSK), | |||
srp: %w(SRP), | |||
anonymous: %w(ADH AECDH), | |||
dss: %w(DSS), | |||
null: %w(NULL), | |||
export: %w(EXP), | |||
des: %w(DES-CBC), | |||
rc4: %w(RC4), | |||
des3: %w(3DES DES-CBC3), | |||
pfs: %w(DHE EDH ECDHE ECDH) | |||
} | |||
TYPES.each do |name, ciphers| | |||
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 | |||
def self.#{name}?(cipher) | |||
#{ciphers}.any? { |c| /(^|-)#\{c\}(-|$)/ =~ cipher } | |||
end | |||
RUBY_EVAL | |||
end | |||
def self.grade(hostname, port, server_class:, grade_class:) | |||
timeout MAX_ANALYSIS_DURATION do | |||
grade_class.new server_class.new hostname, port | |||
@@ -89,20 +61,8 @@ module CryptCheck | |||
def self.colorize(cipher) | |||
colors = case | |||
when /^SSL/ =~ cipher, | |||
dss?(cipher), | |||
anonymous?(cipher), | |||
null?(cipher), | |||
export?(cipher), | |||
md5?(cipher), | |||
des?(cipher), | |||
rc4?(cipher) | |||
{ color: :white, background: :red } | |||
when des3?(cipher) | |||
{ color: :yellow } | |||
when :TLSv1_2 == cipher, | |||
pfs?(cipher) | |||
{ color: :green } | |||
when /^SSL/ =~ cipher then { color: :white, background: :red } | |||
when :TLSv1_2 == cipher then { color: :green } | |||
end | |||
cipher.to_s.colorize colors | |||
end | |||
@@ -110,18 +70,13 @@ module CryptCheck | |||
def self.key_to_s(key) | |||
size = key.rsa_equivalent_size | |||
type_color = case key.type | |||
when :ecc | |||
{ color: :green } | |||
when :dsa | |||
{ color: :yellow } | |||
when :ecc then { color: :green } | |||
when :dsa then { color: :yellow } | |||
end | |||
size_color = case size | |||
when 0...1024 | |||
{ color: :white, background: :red } | |||
when 1024...2048 | |||
{ color: :yellow } | |||
when 4096...::Float::INFINITY | |||
{ color: :green } | |||
when 0...1024 then { color: :white, background: :red } | |||
when 1024...2048 then { color: :yellow } | |||
when 4096...::Float::INFINITY then { color: :green } | |||
end | |||
"#{key.type.to_s.upcase.colorize type_color} #{key.size.to_s.colorize size_color} bits" | |||
end | |||
@@ -0,0 +1,69 @@ | |||
module CryptCheck | |||
module Tls | |||
class Cipher | |||
TYPES = { | |||
md5: %w(MD5), | |||
sha1: %w(SHA), | |||
psk: %w(PSK), | |||
srp: %w(SRP), | |||
anonymous: %w(ADH AECDH), | |||
dss: %w(DSS), | |||
null: %w(NULL), | |||
export: %w(EXP), | |||
des: %w(DES-CBC), | |||
rc2: %w(RC2), | |||
rc4: %w(RC4), | |||
des3: %w(3DES DES-CBC3), | |||
pfs: %w(DHE EDH ECDHE ECDH) | |||
} | |||
attr_reader :protocol, :name, :size, :dh | |||
def initialize(protocol, cipher, dh) | |||
@protocol, @dh = protocol, dh | |||
@name, _, @size = cipher | |||
end | |||
TYPES.each do |name, ciphers| | |||
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 | |||
def self.#{name}?(cipher) | |||
#{ciphers}.any? { |c| /(^|-)#\{c\}(-|$)/ =~ cipher } | |||
end | |||
def #{name}? | |||
#{ciphers}.any? { |c| /(^|-)#\{c\}(-|$)/ =~ @name } | |||
end | |||
RUBY_EVAL | |||
end | |||
def ssl? | |||
sslv2? or sslv3? | |||
end | |||
def tls? | |||
tlsv1? or tlsv1_1? or tlsv1_2? | |||
end | |||
def colorize | |||
colors = case | |||
when dss?, | |||
anonymous?, | |||
null?, | |||
export?, | |||
md5?, | |||
des?, | |||
rc4? | |||
{ color: :white, background: :red } | |||
when des3? | |||
{ color: :yellow } | |||
when pfs? | |||
{ color: :green } | |||
end | |||
@name.colorize colors | |||
end | |||
end | |||
end | |||
end |
@@ -1,3 +1,5 @@ | |||
require 'openssl' | |||
class ::OpenSSL::PKey::EC | |||
def type | |||
:ecc | |||
@@ -14,6 +16,7 @@ class ::OpenSSL::PKey::EC | |||
when 256 then 3072 | |||
when 384 then 7680 | |||
when 521 then 15360 | |||
when 571 then 21000 | |||
end | |||
end | |||
@@ -21,21 +21,15 @@ module CryptCheck | |||
calculate_warning | |||
calculate_success | |||
calculate_grade | |||
calculate_perfect | |||
end | |||
def display | |||
color = case self.grade | |||
when 'A+' | |||
:blue | |||
when 'A' | |||
:green | |||
when 'B', 'C' | |||
:yellow | |||
when 'E', 'F' | |||
:red | |||
when 'M', 'T' | |||
{ color: :white, background: :red } | |||
when 'A+' then :blue | |||
when 'A' then :green | |||
when 'B', 'C' then :yellow | |||
when 'E', 'F' then :red | |||
when 'M', 'T' then { color: :white, background: :red } | |||
end | |||
Logger.info { "Grade : #{self.grade.colorize color }" } | |||
@@ -53,18 +47,12 @@ module CryptCheck | |||
private | |||
def calculate_grade | |||
@grade = case @score | |||
when 0...20 then | |||
'F' | |||
when 20...35 then | |||
'E' | |||
when 35...50 then | |||
'D' | |||
when 50...65 then | |||
'C' | |||
when 65...80 then | |||
'B' | |||
else | |||
'A' | |||
when 0...20 then 'F' | |||
when 20...35 then 'E' | |||
when 35...50 then 'D' | |||
when 50...65 then 'C' | |||
when 65...80 then 'B' | |||
else 'A' | |||
end | |||
@grade = [@grade, 'B'].max if !@server.tlsv1_2? or @server.key_size < 2048 | |||
@@ -73,6 +61,8 @@ module CryptCheck | |||
@grade = 'M' unless @server.cert_valid | |||
@grade = 'T' unless @server.cert_trusted | |||
@grade = 'A+' if @grade == 'A' and @error.empty? and @warning.empty? and (all_success & @success) == all_success | |||
end | |||
def calculate_error | |||
@@ -108,63 +98,44 @@ module CryptCheck | |||
end | |||
ALL_ERROR = %i(md5_sig md5 anonymous dss null export des rc4) | |||
def all_error | |||
ALL_ERROR | |||
end | |||
ALL_WARNING = %i(sha1_sig des3) | |||
def all_warning | |||
ALL_WARNING | |||
end | |||
ALL_SUCCESS = %i(pfs) | |||
def all_success | |||
ALL_SUCCESS | |||
end | |||
def calculate_perfect | |||
@grade = 'A+' if @grade == 'A' and @error.empty? and @warning.empty? and (ALL_SUCCESS & @success) == ALL_SUCCESS | |||
end | |||
METHODS_SCORES = { SSLv2: 0, SSLv3: 10, TLSv1: 50, TLSv1_1: 75, TLSv1_2: 100 } | |||
METHODS_SCORES = { SSLv2: 0, SSLv3: 20, TLSv1: 60, TLSv1_1: 80, TLSv1_2: 100 } | |||
def calculate_protocol_score | |||
methods = @server.supported_methods | |||
worst, best = methods.last, methods.first | |||
@protocol_score = (METHODS_SCORES[worst] + METHODS_SCORES[best]) / 2 | |||
@protocol_score = @server.supported_protocols.collect { |p| METHODS_SCORES[p] }.min | |||
end | |||
def calculate_key_exchange_score | |||
@key_exchange_score = case @server.key_size | |||
when 0 then 0 | |||
when 0...512 then 20 | |||
when 512...1024 then 40 | |||
when 1024...2048 then 80 | |||
when 0...512 then 10 | |||
when 512...1024 then 20 | |||
when 1024...2048 then 50 | |||
when 2048...4096 then 90 | |||
when 4096...::Float::INFINITY then 100 | |||
else 100 | |||
end | |||
end | |||
def calculate_cipher_strength_score(cipher_strength) | |||
case cipher_strength | |||
when 0 then | |||
0 | |||
when 0...128 then | |||
20 | |||
when 128...256 then | |||
80 | |||
else | |||
100 | |||
end | |||
end | |||
def calculate_cipher_strengths_score | |||
strength = @server.cipher_size | |||
worst, best = strength[:min], strength[:max] | |||
@cipher_strengths_score = (calculate_cipher_strength_score(worst) + calculate_cipher_strength_score(best)) / 2 | |||
@cipher_strengths_score = case @server.cipher_size | |||
when 0 then 0 | |||
when 0...112 then 10 | |||
when 112...128 then 50 | |||
when 128...256 then 90 | |||
else 100 | |||
end | |||
end | |||
end | |||
end | |||
@@ -14,14 +14,17 @@ module CryptCheck | |||
def fetch_hsts | |||
port = @port == 443 ? '' : ":#{@port}" | |||
response = ::HTTParty.head "https://#{@hostname}#{port}/", { follow_redirects: false, verify: false, timeout: SSL_TIMEOUT } | |||
if header = response.headers['strict-transport-security'] | |||
name, value = header.split '=' | |||
if name == 'max-age' | |||
@hsts = value.to_i | |||
Logger.info { "HSTS : #{@hsts.to_s.colorize hsts_long? ? :green : nil}" } | |||
return | |||
begin | |||
response = ::HTTParty.head "https://#{@hostname}#{port}/", { follow_redirects: false, verify: false, timeout: SSL_TIMEOUT } | |||
if header = response.headers['strict-transport-security'] | |||
name, value = header.split '=' | |||
if name == 'max-age' | |||
@hsts = value.to_i | |||
Logger.info { "HSTS : #{@hsts.to_s.colorize hsts_long? ? :green : nil}" } | |||
return | |||
end | |||
end | |||
rescue ::Net::OpenTimeout | |||
end | |||
Logger.info { 'No HSTS'.colorize :yellow } | |||
@@ -32,7 +32,7 @@ module CryptCheck | |||
class ConnectionError < TLSException | |||
end | |||
attr_reader :hostname, :port, :prefered_ciphers, :cert, :cert_valid, :cert_trusted | |||
attr_reader :hostname, :port, :prefered_ciphers, :cert, :cert_valid, :cert_trusted, :dh | |||
def initialize(hostname, port) | |||
@hostname, @port = hostname, port | |||
@@ -40,19 +40,30 @@ module CryptCheck | |||
Logger.info { "#{hostname}:#{port}".colorize :blue } | |||
extract_cert | |||
Logger.info { '' } | |||
Logger.info { "Key : #{Tls.key_to_s @cert.public_key}" } | |||
Logger.info { "Key : #{Tls.key_to_s self.key}" } | |||
fetch_prefered_ciphers | |||
check_supported_cipher | |||
uniq_dh | |||
end | |||
def supported_methods | |||
EXISTING_METHODS.select { |m| !@prefered_ciphers[m].nil? } | |||
def key | |||
@cert.public_key | |||
end | |||
def cipher_size | |||
cipher_strengths = supported_ciphers.collect { |c| c[2] }.uniq.sort | |||
worst, best = cipher_strengths.first, cipher_strengths.last | |||
{ worst: worst, best: best } | |||
supported_ciphers.collect { |c| c.size }.sort.last | |||
end | |||
def supported_protocols | |||
@supported_ciphers.keys | |||
end | |||
def supported_ciphers | |||
@supported_ciphers.values.flatten 1 | |||
end | |||
def supported_ciphers_by_protocol(protocol) | |||
@supported_ciphers[protocol] | |||
end | |||
EXISTING_METHODS.each do |method| | |||
@@ -75,10 +86,10 @@ module CryptCheck | |||
RUBY_EVAL | |||
end | |||
Tls::TYPES.each do |type, _| | |||
Cipher::TYPES.each do |type, _| | |||
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 | |||
def #{type}? | |||
supported_ciphers.any? { |s| Tls.#{type}? s.first } | |||
supported_ciphers.any? { |c| c.#{type}? } | |||
end | |||
RUBY_EVAL | |||
end | |||
@@ -100,15 +111,11 @@ module CryptCheck | |||
end | |||
def pfs? | |||
supported_ciphers.any? { |c| Tls.pfs? c.first } | |||
supported_ciphers.any? { |c| c.pfs? } | |||
end | |||
def pfs_only? | |||
supported_ciphers.all? { |c| Tls.pfs? c.first } | |||
end | |||
def supported_ciphers | |||
@supported_ciphers.values.flatten(1).uniq | |||
supported_ciphers.all? { |c| c.pfs? } | |||
end | |||
private | |||
@@ -221,8 +228,8 @@ module CryptCheck | |||
end | |||
def prefered_cipher(method) | |||
cipher = ssl_client(method, 'ALL:COMPLEMENTOFALL') { |s| s.cipher } | |||
Logger.info { "Prefered cipher for #{Tls.colorize method} : #{Tls.colorize cipher.first}" } | |||
cipher = ssl_client(method, 'ALL:COMPLEMENTOFALL') { |s| Cipher.new method, s.cipher, s.tmp_key } | |||
Logger.info { "Prefered cipher for #{Tls.colorize method} : #{cipher.colorize}" } | |||
cipher | |||
rescue TLSException => e | |||
Logger.debug { "Method #{Tls.colorize method} not supported : #{e}" } | |||
@@ -246,12 +253,14 @@ module CryptCheck | |||
def supported_cipher?(method, cipher) | |||
dh = ssl_client method, [cipher] { |s| s.tmp_key } | |||
@dh << dh if dh | |||
cipher = Cipher.new method, cipher, dh | |||
dh = dh ? " (#{'DH'.colorize :green} : #{Tls.key_to_s dh})" : '' | |||
Logger.info { "#{Tls.colorize method} / #{Tls.colorize cipher[0]} : Supported#{dh}" } | |||
true | |||
Logger.info { "#{Tls.colorize method} / #{cipher.colorize} : Supported#{dh}" } | |||
cipher | |||
rescue TLSException => e | |||
Logger.debug { "#{Tls.colorize method} / #{Tls.colorize cipher[0]} : Not supported (#{e})" } | |||
false | |||
Logger.debug { "#{Tls.colorize method} / #{cipher.colorize} : Not supported (#{e})" } | |||
nil | |||
end | |||
def check_supported_cipher | |||
@@ -259,9 +268,9 @@ module CryptCheck | |||
@supported_ciphers = {} | |||
EXISTING_METHODS.each do |method| | |||
next unless SUPPORTED_METHODS.include? method and @prefered_ciphers[method] | |||
ciphers = available_ciphers(method).select { |cipher| supported_cipher? method, cipher } | |||
@supported_ciphers[method] = ciphers | |||
Logger.info { '' } unless ciphers.empty? | |||
supported_ciphers = available_ciphers(method).collect { |c| supported_cipher? method, c }.reject { |c| c.nil? } | |||
Logger.info { '' } unless supported_ciphers.empty? | |||
@supported_ciphers[method] = supported_ciphers | |||
end | |||
end | |||
@@ -270,7 +279,7 @@ module CryptCheck | |||
store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT | |||
store.set_default_paths | |||
%w(cacert).each do |directory| | |||
%w(cacert mozilla).each do |directory| | |||
::Dir.glob(::File.join '/usr/share/ca-certificates', directory, '*').each do |file| | |||
cert = ::OpenSSL::X509::Certificate.new ::File.read file | |||
begin | |||
@@ -289,6 +298,18 @@ module CryptCheck | |||
p store.error_string unless trusted | |||
trusted | |||
end | |||
def uniq_dh | |||
dh, find = [], [] | |||
@dh.each do |k| | |||
f = [k.type, k.size] | |||
unless find.include? f | |||
dh << k | |||
find << f | |||
end | |||
end | |||
@dh = dh | |||
end | |||
end | |||
class TcpServer < Server | |||
@@ -1,5 +1,4 @@ | |||
require 'erb' | |||
require 'logging' | |||
require 'parallel' | |||
module CryptCheck | |||
@@ -7,7 +6,6 @@ module CryptCheck | |||
module Xmpp | |||
MAX_ANALYSIS_DURATION = 600 | |||
PARALLEL_ANALYSIS = 10 | |||
Logger = ::Logging.logger[Xmpp] | |||
def self.grade(hostname, type=:s2s) | |||
timeout MAX_ANALYSIS_DURATION do | |||
@@ -97,10 +97,10 @@ | |||
<%= n.grade %> | |||
</td> | |||
<td class="<%= s.key_size < 2048 ? :danger : s.key_size < 4096 ? :warning : :success %>"> | |||
<% type, size = s.key %> | |||
<%= "#{size} (#{type.to_s.upcase})" %> | |||
<span class="sr-only">(<%= s.key_size < 2048 ? '☹' : '☺' %>)</span> | |||
<% key = s.key %> | |||
<td class="<%= key.rsa_equivalent_size < 2048 ? :danger : key.rsa_equivalent_size < 4096 ? :warning : :success %>"> | |||
<%= "#{key.size} (#{key.type.to_s.upcase})" %> | |||
<span class="sr-only">(<%= key.size < 2048 ? '☹' : '☺' %>)</span> | |||
</td> | |||
<td class="<%= s.sha1_sig? ? :warning : :success %>"> | |||
<%= s.sha1_sig? ? '✓' : '✗' %> | |||
@@ -124,10 +124,9 @@ | |||
<span class="sr-only">(<%= s.tls? ? '☺' : '☹' %>)</span> | |||
</td> | |||
<% cipher_size = s.cipher_size[:worst] %> | |||
<td class="<%= cipher_size < 112 ? :danger : cipher_size < 128 ? :warning : :success %>"> | |||
<%= cipher_size %> | |||
<span class="sr-only">(<%= cipher_size < 128 ? '☹' : '☺' %>)</span> | |||
<td class="<%= s.cipher_size < 112 ? :danger : s.cipher_size < 128 ? :warning : :success %>"> | |||
<%= s.cipher_size %> | |||
<span class="sr-only">(<%= s.cipher_size < 128 ? '☹' : '☺' %>)</span> | |||
</td> | |||
<td class="<%= s.md5? ? :critical : :success %>"> | |||
<%= s.md5? ? '✓' : '✗' %> | |||
@@ -623,6 +623,7 @@ | |||
- www.xartmodels.com | |||
- www.yourdirtymind.com | |||
- your-daily-girl.com | |||
- blog.onahole.eu | |||
- description: Erotic Stories | |||
hostnames: | |||
- literotica.com | |||
@@ -97,10 +97,10 @@ | |||
<%= n.grade %> | |||
</td> | |||
<td class="<%= s.key_size < 2048 ? :danger : s.key_size < 4096 ? :warning : :success %>"> | |||
<% type, size = s.key %> | |||
<%= "#{size} (#{type.to_s.upcase})" %> | |||
<span class="sr-only">(<%= s.key_size < 2048 ? '☹' : '☺' %>)</span> | |||
<% key = s.key %> | |||
<td class="<%= key.rsa_equivalent_size < 2048 ? :danger : key.rsa_equivalent_size < 4096 ? :warning : :success %>"> | |||
<%= "#{key.size} (#{key.type.to_s.upcase})" %> | |||
<span class="sr-only">(<%= key.size < 2048 ? '☹' : '☺' %>)</span> | |||
</td> | |||
<td class="<%= s.sha1_sig? ? :warning : :success %>"> | |||
<%= s.sha1_sig? ? '✓' : '✗' %> | |||
@@ -124,10 +124,9 @@ | |||
<span class="sr-only">(<%= s.tls? ? '☺' : '☹' %>)</span> | |||
</td> | |||
<% cipher_size = s.cipher_size[:worst] %> | |||
<td class="<%= cipher_size < 112 ? :danger : cipher_size < 128 ? :warning : :success %>"> | |||
<%= cipher_size %> | |||
<span class="sr-only">(<%= cipher_size < 128 ? '☹' : '☺' %>)</span> | |||
<td class="<%= s.cipher_size < 112 ? :danger : s.cipher_size < 128 ? :warning : :success %>"> | |||
<%= s.cipher_size %> | |||
<span class="sr-only">(<%= s.cipher_size < 128 ? '☹' : '☺' %>)</span> | |||
</td> | |||
<td class="<%= s.md5? ? :critical : :success %>"> | |||
<%= s.md5? ? '✓' : '✗' %> | |||
@@ -110,10 +110,10 @@ | |||
<%= n.grade %> | |||
</td> | |||
<td class="<%= s.key_size < 2048 ? :danger : s.key_size < 4096 ? :warning : :success %>"> | |||
<% type, size = s.key %> | |||
<%= "#{size} (#{type.to_s.upcase})" %> | |||
<span class="sr-only">(<%= s.key_size < 2048 ? '☹' : '☺' %>)</span> | |||
<% key = s.key %> | |||
<td class="<%= key.rsa_equivalent_size < 2048 ? :danger : key.rsa_equivalent_size < 4096 ? :warning : :success %>"> | |||
<%= "#{key.size} (#{key.type.to_s.upcase})" %> | |||
<span class="sr-only">(<%= key.size < 2048 ? '☹' : '☺' %>)</span> | |||
</td> | |||
<td class="<%= s.sha1_sig? ? :warning : :success %>"> | |||
<%= s.sha1_sig? ? '✓' : '✗' %> | |||
@@ -137,10 +137,9 @@ | |||
<span class="sr-only">(<%= s.tls? ? '☺' : '☹' %>)</span> | |||
</td> | |||
<% cipher_size = s.cipher_size[:worst] %> | |||
<td class="<%= cipher_size < 112 ? :danger : cipher_size < 128 ? :warning : :success %>"> | |||
<%= cipher_size %> | |||
<span class="sr-only">(<%= cipher_size < 128 ? '☹' : '☺' %>)</span> | |||
<td class="<%= s.cipher_size < 112 ? :danger : s.cipher_size < 128 ? :warning : :success %>"> | |||
<%= s.cipher_size %> | |||
<span class="sr-only">(<%= s.cipher_size < 128 ? '☹' : '☺' %>)</span> | |||
</td> | |||
<td class="<%= s.md5? ? :critical : :success %>"> | |||
<%= s.md5? ? '✓' : '✗' %> | |||