Mageia Bugzilla – Attachment 8511 Details for
Bug 19501
ruby new security issue CVE-2016-7798
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
New Account
|
Forgot Password
updated self contained test_cipher.rb verifying the fix
test_cipher.rb (text/plain), 31.58 KB, created by
Pascal Terjan
on 2016-10-10 01:13:34 CEST
(
hide
)
Description:
updated self contained test_cipher.rb verifying the fix
Filename:
MIME Type:
Creator:
Pascal Terjan
Created:
2016-10-10 01:13:34 CEST
Size:
31.58 KB
patch
obsolete
># -*- coding: us-ascii -*- >require "open3" >require "timeout" >require "test/unit" > >module EnvUtil > def rubybin > unless ENV["RUBYOPT"] > > end > if ruby = ENV["RUBY"] > return ruby > end > ruby = "ruby" > rubyexe = ruby+".exe" > 3.times do > if File.exist? ruby and File.executable? ruby and !File.directory? ruby > return File.expand_path(ruby) > end > if File.exist? rubyexe and File.executable? rubyexe > return File.expand_path(rubyexe) > end > ruby = File.join("..", ruby) > end > if defined?(RbConfig.ruby) > RbConfig.ruby > else > "ruby" > end > end > module_function :rubybin > > LANG_ENVS = %w"LANG LC_ALL LC_CTYPE" > > def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = false, > encoding: nil, timeout: 10, reprieve: 1, **opt) > in_c, in_p = IO.pipe > out_p, out_c = IO.pipe if capture_stdout > err_p, err_c = IO.pipe if capture_stderr && capture_stderr != :merge_to_stdout > opt[:in] = in_c > opt[:out] = out_c if capture_stdout > opt[:err] = capture_stderr == :merge_to_stdout ? out_c : err_c if capture_stderr > if encoding > out_p.set_encoding(encoding) if out_p > err_p.set_encoding(encoding) if err_p > end > c = "C" > child_env = {} > LANG_ENVS.each {|lc| child_env[lc] = c} > if Array === args and Hash === args.first > child_env.update(args.shift) > end > args = [args] if args.kind_of?(String) > pid = spawn(child_env, EnvUtil.rubybin, *args, **opt) > in_c.close > out_c.close if capture_stdout > err_c.close if capture_stderr && capture_stderr != :merge_to_stdout > if block_given? > return yield in_p, out_p, err_p, pid > else > th_stdout = Thread.new { out_p.read } if capture_stdout > th_stderr = Thread.new { err_p.read } if capture_stderr && capture_stderr != :merge_to_stdout > in_p.write stdin_data.to_str > in_p.close > if (!th_stdout || th_stdout.join(timeout)) && (!th_stderr || th_stderr.join(timeout)) > stdout = th_stdout.value if capture_stdout > stderr = th_stderr.value if capture_stderr && capture_stderr != :merge_to_stdout > else > signal = /mswin|mingw/ =~ RUBY_PLATFORM ? :KILL : :TERM > begin > Process.kill signal, pid > rescue Errno::ESRCH > break > else > end until signal == :KILL or (sleep reprieve; signal = :KILL; false) > raise Timeout::Error > end > out_p.close if capture_stdout > err_p.close if capture_stderr && capture_stderr != :merge_to_stdout > Process.wait pid > status = $? > return stdout, stderr, status > end > ensure > [th_stdout, th_stderr].each do |th| > th.kill if th > end > [in_c, in_p, out_c, out_p, err_c, err_p].each do |io| > io.close if io && !io.closed? > end > [th_stdout, th_stderr].each do |th| > th.join if th > end > end > module_function :invoke_ruby > > alias rubyexec invoke_ruby > class << self > alias rubyexec invoke_ruby > end > > def verbose_warning > class << (stderr = "") > alias write << > end > stderr, $stderr, verbose, $VERBOSE = $stderr, stderr, $VERBOSE, true > yield stderr > return $stderr > ensure > stderr, $stderr, $VERBOSE = $stderr, stderr, verbose > end > module_function :verbose_warning > > def suppress_warning > verbose, $VERBOSE = $VERBOSE, nil > yield > ensure > $VERBOSE = verbose > end > module_function :suppress_warning > > def under_gc_stress > stress, GC.stress = GC.stress, true > yield > ensure > GC.stress = stress > end > module_function :under_gc_stress > > def with_default_external(enc) > verbose, $VERBOSE = $VERBOSE, nil > origenc, Encoding.default_external = Encoding.default_external, enc > $VERBOSE = verbose > yield > ensure > verbose, $VERBOSE = $VERBOSE, nil > Encoding.default_external = origenc > $VERBOSE = verbose > end > module_function :with_default_external > > def with_default_internal(enc) > verbose, $VERBOSE = $VERBOSE, nil > origenc, Encoding.default_internal = Encoding.default_internal, enc > $VERBOSE = verbose > yield > ensure > verbose, $VERBOSE = $VERBOSE, nil > Encoding.default_internal = origenc > $VERBOSE = verbose > end > module_function :with_default_internal > > def labeled_module(name, &block) > Module.new do > singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s} > class_eval(&block) if block > end > end > module_function :labeled_module > > def labeled_class(name, superclass = Object, &block) > Class.new(superclass) do > singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s} > class_eval(&block) if block > end > end > module_function :labeled_class >end > >module Test > module Unit > module Assertions > public > def assert_valid_syntax(code, fname = caller_locations(1, 1)[0], mesg = fname.to_s) > code = code.dup.force_encoding("ascii-8bit") > code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) { > "#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ok}\n" > } > code.force_encoding(Encoding::UTF_8) > verbose, $VERBOSE = $VERBOSE, nil > yield if defined?(yield) > case > when Array === fname > fname, line = *fname > when defined?(fname.path) && defined?(fname.lineno) > fname, line = fname.path, fname.lineno > else > line = 0 > end > assert_nothing_raised(SyntaxError, mesg) do > assert_equal(:ok, catch {|tag| eval(code, binding, fname, line)}, mesg) > end > ensure > $VERBOSE = verbose > end > > def assert_syntax_error(code, error, fname = caller_locations(1, 1)[0], mesg = fname.to_s) > code = code.dup.force_encoding("ascii-8bit") > code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) { > "#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ng}\n" > } > code.force_encoding("us-ascii") > verbose, $VERBOSE = $VERBOSE, nil > yield if defined?(yield) > case > when Array === fname > fname, line = *fname > when defined?(fname.path) && defined?(fname.lineno) > fname, line = fname.path, fname.lineno > else > line = 0 > end > e = assert_raise(SyntaxError, mesg) do > catch {|tag| eval(code, binding, fname, line)} > end > assert_match(error, e.message, mesg) > ensure > $VERBOSE = verbose > end > > def assert_normal_exit(testsrc, message = '', child_env: nil, **opt) > assert_valid_syntax(testsrc, caller_locations(1, 1)[0]) > if child_env > child_env = [child_env] > else > child_env = [] > end > out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, opt) > assert !status.signaled?, FailDesc[status, message, out] > end > > FailDesc = proc do |status, message = "", out = ""| > pid = status.pid > faildesc = proc do > signo = status.termsig > signame = Signal.list.invert[signo] > sigdesc = "signal #{signo}" > if signame > sigdesc = "SIG#{signame} (#{sigdesc})" > end > if status.coredump? > sigdesc << " (core dumped)" > end > full_message = '' > if message and !message.empty? > full_message << message << "\n" > end > full_message << "pid #{pid} killed by #{sigdesc}" > if out and !out.empty? > full_message << "\n#{out.gsub(/^/, '| ')}" > full_message << "\n" if /\n\z/ !~ full_message > end > full_message > end > faildesc > end > > def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [], message = nil, **opt) > stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, true, true, opt) > if block_given? > raise "test_stdout ignored, use block only or without block" if test_stdout != [] > raise "test_stderr ignored, use block only or without block" if test_stderr != [] > yield(stdout.lines.map {|l| l.chomp }, stderr.lines.map {|l| l.chomp }, status) > else > errs = [] > [[test_stdout, stdout], [test_stderr, stderr]].each do |exp, act| > begin > if exp.is_a?(Regexp) > assert_match(exp, act, message) > else > assert_equal(exp, act.lines.map {|l| l.chomp }, message) > end > rescue MiniTest::Assertion => e > errs << e.message > message = nil > end > end > raise MiniTest::Assertion, errs.join("\n---\n") unless errs.empty? > status > end > end > > def assert_ruby_status(args, test_stdin="", message=nil, **opt) > out, _, status = EnvUtil.invoke_ruby(args, test_stdin, true, :merge_to_stdout, opt) > message ||= "ruby exit status is not success:" > assert(status.success?, FailDesc[status, message, out]) > end > > ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV") > > def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt) > unless file and line > loc, = caller_locations(1,1) > file ||= loc.path > line ||= loc.lineno > end > line -= 2 > src = <<eom ># -*- coding: #{src.encoding}; -*- > require #{__dir__.dump}'/envutil';include Test::Unit::Assertions;begin >#{src} > ensure > puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}" > end > class Test::Unit::Runner > @@stop_auto_run = true > end >eom > args = args.dup > $:.each{|l| args.unshift "-I#{l}" } > stdout, stderr, status = EnvUtil.invoke_ruby(args, src, true, true, opt) > abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig)) > assert(!abort, FailDesc[status, stderr]) > self._assertions += stdout[/^assertions=(\d+)/, 1].to_i > res = Marshal.load(stdout.unpack("m")[0]) > if res > res.backtrace.each do |l| > l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"} > end > raise res > end > > # really is it succeed? > unless ignore_stderr > # the body of assert_separately must not output anything to detect errror > assert_equal("", stderr, "assert_separately failed with error message") > end > assert_equal(0, status, "assert_separately failed: '#{stderr}'") > end > > def assert_warning(pat, message = nil) > stderr = EnvUtil.verbose_warning { yield } > message = ' "' + message + '"' if message > msg = proc {"warning message #{stderr.inspect} is expected to match #{pat.inspect}#{message}"} > assert(pat === stderr, msg) > end > > def assert_warn(*args) > assert_warning(*args) {$VERBOSE = false; yield} > end > > def assert_is_minus_zero(f) > assert(1.0/f == -Float::INFINITY, "#{f} is not -0.0") > end > > def assert_raise_with_message(exception, expected, msg = nil, &block) > case expected > when String > assert = :assert_equal > when Regexp > assert = :assert_match > else > raise TypeError, "Expected #{expected.inspect} to be a kind of String or Regexp, not #{expected.class}" > end > > ex = assert_raise(exception, *msg) {yield} > msg = message(msg, "") {"Expected Exception(#{exception}) was raised, but the message doesn't match"} > > if assert == :assert_equal > assert_equal(expected, ex.message, msg) > else > msg = message(msg) { "Expected #{mu_pp expected} to match #{mu_pp ex.message}" } > assert expected =~ ex.message, msg > block.binding.eval("proc{|_|$~=_}").call($~) > end > ex > end > > def assert_file > AssertFile > end > > class << (AssertFile = Struct.new(:message).new) > include Assertions > def assert_file_predicate(predicate, *args) > if /\Anot_/ =~ predicate > predicate = $' > neg = " not" > end > result = File.__send__(predicate, *args) > result = !result if neg > mesg = "Expected file " << args.shift.inspect > mesg << mu_pp(args) unless args.empty? > mesg << "#{neg} to be #{predicate}" > mesg << " #{message}" if message > assert(result, mesg) > end > alias method_missing assert_file_predicate > > def for(message) > clone.tap {|a| a.message = message} > end > end > end > end >end > >begin > require 'rbconfig' >rescue LoadError >else > module RbConfig > @ruby = EnvUtil.rubybin > class << self > undef ruby if method_defined?(:ruby) > attr_reader :ruby > end > dir = File.dirname(ruby) > name = File.basename(ruby, CONFIG['EXEEXT']) > CONFIG['bindir'] = dir > CONFIG['ruby_install_name'] = name > CONFIG['RUBY_INSTALL_NAME'] = name > Gem::ConfigMap[:bindir] = dir if defined?(Gem::ConfigMap) > end >end >begin > require "openssl" > > # Disable FIPS mode for tests for installations > # where FIPS mode would be enabled by default. > # Has no effect on all other installations. > OpenSSL.fips_mode=false >rescue LoadError >end >require "test/unit" >require "digest/md5" >require 'tempfile' >require "rbconfig" >require "socket" > >module OpenSSL::TestUtils > TEST_KEY_RSA1024 = OpenSSL::PKey::RSA.new <<-_end_of_pem_ >-----BEGIN RSA PRIVATE KEY----- >MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx >aKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/ >Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQAB >AoGBAKSl/MQarye1yOysqX6P8fDFQt68VvtXkNmlSiKOGuzyho0M+UVSFcs6k1L0 >maDE25AMZUiGzuWHyaU55d7RXDgeskDMakD1v6ZejYtxJkSXbETOTLDwUWTn618T >gnb17tU1jktUtU67xK/08i/XodlgnQhs6VoHTuCh3Hu77O6RAkEA7+gxqBuZR572 >74/akiW/SuXm0SXPEviyO1MuSRwtI87B02D0qgV8D1UHRm4AhMnJ8MCs1809kMQE >JiQUCrp9mQJBANlt2ngBO14us6NnhuAseFDTBzCHXwUUu1YKHpMMmxpnGqaldGgX >sOZB3lgJsT9VlGf3YGYdkLTNVbogQKlKpB8CQQDiSwkb4vyQfDe8/NpU5Not0fII >8jsDUCb+opWUTMmfbxWRR3FBNu8wnym/m19N4fFj8LqYzHX4KY0oVPu6qvJxAkEA >wa5snNekFcqONLIE4G5cosrIrb74sqL8GbGb+KuTAprzj5z1K8Bm0UW9lTjVDjDi >qRYgZfZSL+x1P/54+xTFSwJAY1FxA/N3QPCXCjPh5YqFxAMQs2VVYTfg+t0MEcJD >dPMQD5JX6g5HKnHFg2mZtoXQrWmJSn7p8GJK8yNTopEErA== >-----END RSA PRIVATE KEY----- > _end_of_pem_ > > TEST_KEY_RSA2048 = OpenSSL::PKey::RSA.new <<-_end_of_pem_ >-----BEGIN RSA PRIVATE KEY----- >MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN >s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign >4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D >kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl >NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J >DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb >I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq >PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V >seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0 >Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc >VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW >wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G >0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj >XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb >aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n >h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw >Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k >IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb >v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId >U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr >vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS >Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC >9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41 >gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG >4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw== >-----END RSA PRIVATE KEY----- > _end_of_pem_ > > TEST_KEY_DSA256 = OpenSSL::PKey::DSA.new <<-_end_of_pem_ >-----BEGIN DSA PRIVATE KEY----- >MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE >9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed >AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM >3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT >b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn >ISNX5cMzFHRW3Q== >-----END DSA PRIVATE KEY----- > _end_of_pem_ > > TEST_KEY_DSA512 = OpenSSL::PKey::DSA.new <<-_end_of_pem_ >-----BEGIN DSA PRIVATE KEY----- >MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok >RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D >AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR >S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++ >Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S >55jreJD3Se3slps= >-----END DSA PRIVATE KEY----- > _end_of_pem_ > >if defined?(OpenSSL::PKey::EC) > > TEST_KEY_EC_P256V1 = OpenSSL::PKey::EC.new <<-_end_of_pem_ >-----BEGIN EC PRIVATE KEY----- >MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 >AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt >CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== >-----END EC PRIVATE KEY----- > _end_of_pem_ > >end > > TEST_KEY_DH512_PUB = OpenSSL::PKey::DH.new <<-_end_of_pem_ >-----BEGIN DH PARAMETERS----- >MEYCQQDmWXGPqk76sKw/edIOdhAQD4XzjJ+AR/PTk2qzaGs+u4oND2yU5D2NN4wr >aPgwHyJBiK1/ebK3tYcrSKrOoRyrAgEC >-----END DH PARAMETERS----- > _end_of_pem_ > > TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_ >-----BEGIN DH PARAMETERS----- >MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0 >pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG >AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC >-----END DH PARAMETERS----- > _end_of_pem_ > > TEST_KEY_DH1024.priv_key = OpenSSL::BN.new("48561834C67E65FFD2A9B47F41E5E78FDC95C387428FDB1E4B0188B64D1643C3A8D3455B945B7E8C4D166010C7C2CE23BFB9BEF43D0348FE7FA5284B0225E7FE1537546D114E3D8A4411B9B9351AB451E1A358F50ED61B1F00DA29336EEBBD649980AC86D76AF8BBB065298C2052672EEF3EF13AB47A15275FC2836F3AC74CEA", 16) > > DSA_SIGNATURE_DIGEST = OpenSSL::OPENSSL_VERSION_NUMBER > 0x10000000 ? > OpenSSL::Digest::SHA1 : > OpenSSL::Digest::DSS1 > > module_function > > def issue_cert(dn, key, serial, not_before, not_after, extensions, > issuer, issuer_key, digest) > cert = OpenSSL::X509::Certificate.new > issuer = cert unless issuer > issuer_key = key unless issuer_key > cert.version = 2 > cert.serial = serial > cert.subject = dn > cert.issuer = issuer.subject > cert.public_key = key.public_key > cert.not_before = not_before > cert.not_after = not_after > ef = OpenSSL::X509::ExtensionFactory.new > ef.subject_certificate = cert > ef.issuer_certificate = issuer > extensions.each{|oid, value, critical| > cert.add_extension(ef.create_extension(oid, value, critical)) > } > cert.sign(issuer_key, digest) > cert > end > > def issue_crl(revoke_info, serial, lastup, nextup, extensions, > issuer, issuer_key, digest) > crl = OpenSSL::X509::CRL.new > crl.issuer = issuer.subject > crl.version = 1 > crl.last_update = lastup > crl.next_update = nextup > revoke_info.each{|rserial, time, reason_code| > revoked = OpenSSL::X509::Revoked.new > revoked.serial = rserial > revoked.time = time > enum = OpenSSL::ASN1::Enumerated(reason_code) > ext = OpenSSL::X509::Extension.new("CRLReason", enum) > revoked.add_extension(ext) > crl.add_revoked(revoked) > } > ef = OpenSSL::X509::ExtensionFactory.new > ef.issuer_certificate = issuer > ef.crl = crl > crlnum = OpenSSL::ASN1::Integer(serial) > crl.add_extension(OpenSSL::X509::Extension.new("crlNumber", crlnum)) > extensions.each{|oid, value, critical| > crl.add_extension(ef.create_extension(oid, value, critical)) > } > crl.sign(issuer_key, digest) > crl > end > > def get_subject_key_id(cert) > asn1_cert = OpenSSL::ASN1.decode(cert) > tbscert = asn1_cert.value[0] > pkinfo = tbscert.value[6] > publickey = pkinfo.value[1] > pkvalue = publickey.value > OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase > end > > def silent > begin > back, $VERBOSE = $VERBOSE, nil > yield > ensure > $VERBOSE = back > end > end > > class OpenSSL::SSLTestCase < Test::Unit::TestCase > RUBY = EnvUtil.rubybin > SSL_SERVER = File.join(File.dirname(__FILE__), "ssl_server.rb") > PORT = 20443 > ITERATIONS = ($0 == __FILE__) ? 100 : 10 > > def setup > @ca_key = OpenSSL::TestUtils::TEST_KEY_RSA2048 > @svr_key = OpenSSL::TestUtils::TEST_KEY_RSA1024 > @cli_key = OpenSSL::TestUtils::TEST_KEY_DSA256 > @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") > @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") > @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") > now = Time.at(Time.now.to_i) > ca_exts = [ > ["basicConstraints","CA:TRUE",true], > ["keyUsage","cRLSign,keyCertSign",true], > ] > ee_exts = [ > ["keyUsage","keyEncipherment,digitalSignature",true], > ] > @ca_cert = issue_cert(@ca, @ca_key, 1, now, now+3600, ca_exts, nil, nil, OpenSSL::Digest::SHA1.new) > @svr_cert = issue_cert(@svr, @svr_key, 2, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new) > @cli_cert = issue_cert(@cli, @cli_key, 3, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new) > @server = nil > end > > def teardown > end > > def issue_cert(*arg) > OpenSSL::TestUtils.issue_cert(*arg) > end > > def issue_crl(*arg) > OpenSSL::TestUtils.issue_crl(*arg) > end > > def readwrite_loop(ctx, ssl) > while line = ssl.gets > if line =~ /^STARTTLS$/ > ssl.accept > next > end > ssl.write(line) > end > rescue OpenSSL::SSL::SSLError > rescue IOError > ensure > ssl.close rescue nil > end > > def server_loop(ctx, ssls, server_proc) > loop do > ssl = nil > begin > ssl = ssls.accept > rescue OpenSSL::SSL::SSLError > retry > end > > Thread.start do > Thread.current.abort_on_exception = true > server_proc.call(ctx, ssl) > end > end > rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET > end > > def start_server(port0, verify_mode, start_immediately, args = {}, &block) > ctx_proc = args[:ctx_proc] > server_proc = args[:server_proc] > server_proc ||= method(:readwrite_loop) > > store = OpenSSL::X509::Store.new > store.add_cert(@ca_cert) > store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT > ctx = OpenSSL::SSL::SSLContext.new > ctx.cert_store = store > #ctx.extra_chain_cert = [ ca_cert ] > ctx.cert = @svr_cert > ctx.key = @svr_key > ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } > ctx.verify_mode = verify_mode > ctx_proc.call(ctx) if ctx_proc > > Socket.do_not_reverse_lookup = true > tcps = nil > port = port0 > begin > tcps = TCPServer.new("127.0.0.1", port) > rescue Errno::EADDRINUSE > port += 1 > retry > end > > ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) > ssls.start_immediately = start_immediately > > begin > server = Thread.new do > Thread.current.abort_on_exception = true > server_loop(ctx, ssls, server_proc) > end > > $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, $$, port) if $DEBUG > > block.call(server, port.to_i) > ensure > begin > begin > tcps.shutdown > rescue Errno::ENOTCONN > # when `Errno::ENOTCONN: Socket is not connected' on some platforms, > # call #close instead of #shutdown. > tcps.close > tcps = nil > end if (tcps) > if (server) > server.join(5) > if server.alive? > server.kill > server.join > flunk("TCPServer was closed and SSLServer is still alive") unless $! > end > end > ensure > tcps.close if (tcps) > end > end > end > > def starttls(ssl) > ssl.puts("STARTTLS") > sleep 1 # When this line is eliminated, process on Cygwin blocks > # forever at ssl.connect. But I don't know why it does. > ssl.connect > end > end > >class OpenSSL::TestCipher < Test::Unit::TestCase > > class << self > > def has_cipher?(name) > ciphers = OpenSSL::Cipher.ciphers > # redefine method so we can use the cached ciphers value from the closure > # and need not recompute the list each time > define_singleton_method :has_cipher? do |name| > ciphers.include?(name) > end > has_cipher?(name) > end > > def has_ciphers?(list) > list.all? { |name| has_cipher?(name) } > end > > end > > def setup > @c1 = OpenSSL::Cipher::Cipher.new("DES-EDE3-CBC") > @c2 = OpenSSL::Cipher::DES.new(:EDE3, "CBC") > @key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" > @iv = "\0\0\0\0\0\0\0\0" > @hexkey = "0000000000000000000000000000000000000000000000" > @hexiv = "0000000000000000" > @data = "DATA" > end > > def teardown > @c1 = @c2 = nil > end > > def test_crypt > @c1.encrypt.pkcs5_keyivgen(@key, @iv) > @c2.encrypt.pkcs5_keyivgen(@key, @iv) > s1 = @c1.update(@data) + @c1.final > s2 = @c2.update(@data) + @c2.final > assert_equal(s1, s2, "encrypt") > > @c1.decrypt.pkcs5_keyivgen(@key, @iv) > @c2.decrypt.pkcs5_keyivgen(@key, @iv) > assert_equal(@data, @c1.update(s1)+@c1.final, "decrypt") > assert_equal(@data, @c2.update(s2)+@c2.final, "decrypt") > end > > def test_info > assert_equal("DES-EDE3-CBC", @c1.name, "name") > assert_equal("DES-EDE3-CBC", @c2.name, "name") > assert_kind_of(Fixnum, @c1.key_len, "key_len") > assert_kind_of(Fixnum, @c1.iv_len, "iv_len") > end > > def test_dup > assert_equal(@c1.name, @c1.dup.name, "dup") > assert_equal(@c1.name, @c1.clone.name, "clone") > @c1.encrypt > @c1.key = @key > @c1.iv = @iv > tmpc = @c1.dup > s1 = @c1.update(@data) + @c1.final > s2 = tmpc.update(@data) + tmpc.final > assert_equal(s1, s2, "encrypt dup") > end > > def test_reset > @c1.encrypt > @c1.key = @key > @c1.iv = @iv > s1 = @c1.update(@data) + @c1.final > @c1.reset > s2 = @c1.update(@data) + @c1.final > assert_equal(s1, s2, "encrypt reset") > end > > def test_empty_data > @c1.encrypt > @c1.key = @key > assert_raise(ArgumentError){ @c1.update("") } > end > > def test_initialize > assert_raise(RuntimeError) {@c1.__send__(:initialize, "DES-EDE3-CBC")} > assert_raise(RuntimeError) {OpenSSL::Cipher.allocate.final} > end > > def test_ctr_if_exists > begin > cipher = OpenSSL::Cipher.new('aes-128-ctr') > cipher.encrypt > cipher.pkcs5_keyivgen('password') > c = cipher.update('hello,world') + cipher.final > cipher.decrypt > cipher.pkcs5_keyivgen('password') > assert_equal('hello,world', cipher.update(c) + cipher.final) > end > end if has_cipher?('aes-128-ctr') > > if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00907000 > def test_ciphers > OpenSSL::Cipher.ciphers.each{|name| > next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name > begin > assert_kind_of(OpenSSL::Cipher::Cipher, OpenSSL::Cipher::Cipher.new(name)) > rescue OpenSSL::Cipher::CipherError => e > next if /wrap/ =~ name and e.message == 'wrap mode not allowed' > raise > end > } > end > > def test_AES > pt = File.read(__FILE__) > %w(ECB CBC CFB OFB).each{|mode| > c1 = OpenSSL::Cipher::AES256.new(mode) > c1.encrypt > c1.pkcs5_keyivgen("passwd") > ct = c1.update(pt) + c1.final > > c2 = OpenSSL::Cipher::AES256.new(mode) > c2.decrypt > c2.pkcs5_keyivgen("passwd") > assert_equal(pt, c2.update(ct) + c2.final) > } > end > > def test_update_raise_if_key_not_set > assert_raise(OpenSSL::Cipher::CipherError) do > # it caused OpenSSL SEGV by uninitialized key [Bug #2768] > OpenSSL::Cipher::AES128.new("ECB").update "." * 17 > end > end > end > > if has_ciphers?(['aes-128-gcm', 'aes-192-gcm', 'aes-128-gcm']) > > def test_authenticated > cipher = OpenSSL::Cipher.new('aes-128-gcm') > assert(cipher.authenticated?) > cipher = OpenSSL::Cipher.new('aes-128-cbc') > refute(cipher.authenticated?) > end > > def test_aes_gcm > ['aes-128-gcm', 'aes-192-gcm', 'aes-128-gcm'].each do |algo| > pt = "You should all use Authenticated Encryption!" > cipher, key, iv = new_encryptor(algo) > > cipher.auth_data = "aad" > ct = cipher.update(pt) + cipher.final > tag = cipher.auth_tag > assert_equal(16, tag.size) > > decipher = new_decryptor(algo, key, iv) > decipher.auth_tag = tag > decipher.auth_data = "aad" > > assert_equal(pt, decipher.update(ct) + decipher.final) > end > end > > def test_aes_gcm_short_tag > ['aes-128-gcm', 'aes-192-gcm', 'aes-128-gcm'].each do |algo| > pt = "You should all use Authenticated Encryption!" > cipher, key, iv = new_encryptor(algo) > > cipher.auth_data = "aad" > ct = cipher.update(pt) + cipher.final > tag = cipher.auth_tag(8) > assert_equal(8, tag.size) > > decipher = new_decryptor(algo, key, iv) > decipher.auth_tag = tag > decipher.auth_data = "aad" > > assert_equal(pt, decipher.update(ct) + decipher.final) > end > end > > def test_aes_gcm_wrong_tag > pt = "You should all use Authenticated Encryption!" > cipher, key, iv = new_encryptor('aes-128-gcm') > > cipher.auth_data = "aad" > ct = cipher.update(pt) + cipher.final > tag = cipher.auth_tag > > decipher = new_decryptor('aes-128-gcm', key, iv) > tag.setbyte(-1, (tag.getbyte(-1) + 1) & 0xff) > decipher.auth_tag = tag > decipher.auth_data = "aad" > > assert_raise OpenSSL::Cipher::CipherError do > decipher.update(ct) + decipher.final > end > end > > def test_aes_gcm_wrong_auth_data > pt = "You should all use Authenticated Encryption!" > cipher, key, iv = new_encryptor('aes-128-gcm') > > cipher.auth_data = "aad" > ct = cipher.update(pt) + cipher.final > tag = cipher.auth_tag > > decipher = new_decryptor('aes-128-gcm', key, iv) > decipher.auth_tag = tag > decipher.auth_data = "daa" > > assert_raise OpenSSL::Cipher::CipherError do > decipher.update(ct) + decipher.final > end > end > > def test_aes_gcm_wrong_ciphertext > pt = "You should all use Authenticated Encryption!" > cipher, key, iv = new_encryptor('aes-128-gcm') > > cipher.auth_data = "aad" > ct = cipher.update(pt) + cipher.final > tag = cipher.auth_tag > > decipher = new_decryptor('aes-128-gcm', key, iv) > decipher.auth_tag = tag > decipher.auth_data = "aad" > > assert_raise OpenSSL::Cipher::CipherError do > decipher.update(ct[0..-2] << ct[-1].succ) + decipher.final > end > end > > def test_aes_gcm_key_iv_order_issue > pt = "You should all use Authenticated Encryption!" > cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt > cipher.key = "x" * 16 > cipher.iv = "a" * 12 > ct1 = cipher.update(pt) << cipher.final > tag1 = cipher.auth_tag > > cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt > cipher.iv = "a" * 12 > cipher.key = "x" * 16 > ct2 = cipher.update(pt) << cipher.final > tag2 = cipher.auth_tag > > assert_equal ct1, ct2 > assert_equal tag1, tag2 > end if has_cipher?("aes-128-gcm") > end > > private > > def new_encryptor(algo) > cipher = OpenSSL::Cipher.new(algo) > cipher.encrypt > key = cipher.random_key > iv = cipher.random_iv > [cipher, key, iv] > end > > def new_decryptor(algo, key, iv) > OpenSSL::Cipher.new(algo).tap do |cipher| > cipher.decrypt > cipher.key = key > cipher.iv = iv > end > end > >end > >end
# -*- coding: us-ascii -*- require "open3" require "timeout" require "test/unit" module EnvUtil def rubybin unless ENV["RUBYOPT"] end if ruby = ENV["RUBY"] return ruby end ruby = "ruby" rubyexe = ruby+".exe" 3.times do if File.exist? ruby and File.executable? ruby and !File.directory? ruby return File.expand_path(ruby) end if File.exist? rubyexe and File.executable? rubyexe return File.expand_path(rubyexe) end ruby = File.join("..", ruby) end if defined?(RbConfig.ruby) RbConfig.ruby else "ruby" end end module_function :rubybin LANG_ENVS = %w"LANG LC_ALL LC_CTYPE" def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = false, encoding: nil, timeout: 10, reprieve: 1, **opt) in_c, in_p = IO.pipe out_p, out_c = IO.pipe if capture_stdout err_p, err_c = IO.pipe if capture_stderr && capture_stderr != :merge_to_stdout opt[:in] = in_c opt[:out] = out_c if capture_stdout opt[:err] = capture_stderr == :merge_to_stdout ? out_c : err_c if capture_stderr if encoding out_p.set_encoding(encoding) if out_p err_p.set_encoding(encoding) if err_p end c = "C" child_env = {} LANG_ENVS.each {|lc| child_env[lc] = c} if Array === args and Hash === args.first child_env.update(args.shift) end args = [args] if args.kind_of?(String) pid = spawn(child_env, EnvUtil.rubybin, *args, **opt) in_c.close out_c.close if capture_stdout err_c.close if capture_stderr && capture_stderr != :merge_to_stdout if block_given? return yield in_p, out_p, err_p, pid else th_stdout = Thread.new { out_p.read } if capture_stdout th_stderr = Thread.new { err_p.read } if capture_stderr && capture_stderr != :merge_to_stdout in_p.write stdin_data.to_str in_p.close if (!th_stdout || th_stdout.join(timeout)) && (!th_stderr || th_stderr.join(timeout)) stdout = th_stdout.value if capture_stdout stderr = th_stderr.value if capture_stderr && capture_stderr != :merge_to_stdout else signal = /mswin|mingw/ =~ RUBY_PLATFORM ? :KILL : :TERM begin Process.kill signal, pid rescue Errno::ESRCH break else end until signal == :KILL or (sleep reprieve; signal = :KILL; false) raise Timeout::Error end out_p.close if capture_stdout err_p.close if capture_stderr && capture_stderr != :merge_to_stdout Process.wait pid status = $? return stdout, stderr, status end ensure [th_stdout, th_stderr].each do |th| th.kill if th end [in_c, in_p, out_c, out_p, err_c, err_p].each do |io| io.close if io && !io.closed? end [th_stdout, th_stderr].each do |th| th.join if th end end module_function :invoke_ruby alias rubyexec invoke_ruby class << self alias rubyexec invoke_ruby end def verbose_warning class << (stderr = "") alias write << end stderr, $stderr, verbose, $VERBOSE = $stderr, stderr, $VERBOSE, true yield stderr return $stderr ensure stderr, $stderr, $VERBOSE = $stderr, stderr, verbose end module_function :verbose_warning def suppress_warning verbose, $VERBOSE = $VERBOSE, nil yield ensure $VERBOSE = verbose end module_function :suppress_warning def under_gc_stress stress, GC.stress = GC.stress, true yield ensure GC.stress = stress end module_function :under_gc_stress def with_default_external(enc) verbose, $VERBOSE = $VERBOSE, nil origenc, Encoding.default_external = Encoding.default_external, enc $VERBOSE = verbose yield ensure verbose, $VERBOSE = $VERBOSE, nil Encoding.default_external = origenc $VERBOSE = verbose end module_function :with_default_external def with_default_internal(enc) verbose, $VERBOSE = $VERBOSE, nil origenc, Encoding.default_internal = Encoding.default_internal, enc $VERBOSE = verbose yield ensure verbose, $VERBOSE = $VERBOSE, nil Encoding.default_internal = origenc $VERBOSE = verbose end module_function :with_default_internal def labeled_module(name, &block) Module.new do singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s} class_eval(&block) if block end end module_function :labeled_module def labeled_class(name, superclass = Object, &block) Class.new(superclass) do singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s} class_eval(&block) if block end end module_function :labeled_class end module Test module Unit module Assertions public def assert_valid_syntax(code, fname = caller_locations(1, 1)[0], mesg = fname.to_s) code = code.dup.force_encoding("ascii-8bit") code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) { "#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ok}\n" } code.force_encoding(Encoding::UTF_8) verbose, $VERBOSE = $VERBOSE, nil yield if defined?(yield) case when Array === fname fname, line = *fname when defined?(fname.path) && defined?(fname.lineno) fname, line = fname.path, fname.lineno else line = 0 end assert_nothing_raised(SyntaxError, mesg) do assert_equal(:ok, catch {|tag| eval(code, binding, fname, line)}, mesg) end ensure $VERBOSE = verbose end def assert_syntax_error(code, error, fname = caller_locations(1, 1)[0], mesg = fname.to_s) code = code.dup.force_encoding("ascii-8bit") code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) { "#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ng}\n" } code.force_encoding("us-ascii") verbose, $VERBOSE = $VERBOSE, nil yield if defined?(yield) case when Array === fname fname, line = *fname when defined?(fname.path) && defined?(fname.lineno) fname, line = fname.path, fname.lineno else line = 0 end e = assert_raise(SyntaxError, mesg) do catch {|tag| eval(code, binding, fname, line)} end assert_match(error, e.message, mesg) ensure $VERBOSE = verbose end def assert_normal_exit(testsrc, message = '', child_env: nil, **opt) assert_valid_syntax(testsrc, caller_locations(1, 1)[0]) if child_env child_env = [child_env] else child_env = [] end out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, opt) assert !status.signaled?, FailDesc[status, message, out] end FailDesc = proc do |status, message = "", out = ""| pid = status.pid faildesc = proc do signo = status.termsig signame = Signal.list.invert[signo] sigdesc = "signal #{signo}" if signame sigdesc = "SIG#{signame} (#{sigdesc})" end if status.coredump? sigdesc << " (core dumped)" end full_message = '' if message and !message.empty? full_message << message << "\n" end full_message << "pid #{pid} killed by #{sigdesc}" if out and !out.empty? full_message << "\n#{out.gsub(/^/, '| ')}" full_message << "\n" if /\n\z/ !~ full_message end full_message end faildesc end def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [], message = nil, **opt) stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, true, true, opt) if block_given? raise "test_stdout ignored, use block only or without block" if test_stdout != [] raise "test_stderr ignored, use block only or without block" if test_stderr != [] yield(stdout.lines.map {|l| l.chomp }, stderr.lines.map {|l| l.chomp }, status) else errs = [] [[test_stdout, stdout], [test_stderr, stderr]].each do |exp, act| begin if exp.is_a?(Regexp) assert_match(exp, act, message) else assert_equal(exp, act.lines.map {|l| l.chomp }, message) end rescue MiniTest::Assertion => e errs << e.message message = nil end end raise MiniTest::Assertion, errs.join("\n---\n") unless errs.empty? status end end def assert_ruby_status(args, test_stdin="", message=nil, **opt) out, _, status = EnvUtil.invoke_ruby(args, test_stdin, true, :merge_to_stdout, opt) message ||= "ruby exit status is not success:" assert(status.success?, FailDesc[status, message, out]) end ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV") def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt) unless file and line loc, = caller_locations(1,1) file ||= loc.path line ||= loc.lineno end line -= 2 src = <<eom # -*- coding: #{src.encoding}; -*- require #{__dir__.dump}'/envutil';include Test::Unit::Assertions;begin #{src} ensure puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}" end class Test::Unit::Runner @@stop_auto_run = true end eom args = args.dup $:.each{|l| args.unshift "-I#{l}" } stdout, stderr, status = EnvUtil.invoke_ruby(args, src, true, true, opt) abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig)) assert(!abort, FailDesc[status, stderr]) self._assertions += stdout[/^assertions=(\d+)/, 1].to_i res = Marshal.load(stdout.unpack("m")[0]) if res res.backtrace.each do |l| l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"} end raise res end # really is it succeed? unless ignore_stderr # the body of assert_separately must not output anything to detect errror assert_equal("", stderr, "assert_separately failed with error message") end assert_equal(0, status, "assert_separately failed: '#{stderr}'") end def assert_warning(pat, message = nil) stderr = EnvUtil.verbose_warning { yield } message = ' "' + message + '"' if message msg = proc {"warning message #{stderr.inspect} is expected to match #{pat.inspect}#{message}"} assert(pat === stderr, msg) end def assert_warn(*args) assert_warning(*args) {$VERBOSE = false; yield} end def assert_is_minus_zero(f) assert(1.0/f == -Float::INFINITY, "#{f} is not -0.0") end def assert_raise_with_message(exception, expected, msg = nil, &block) case expected when String assert = :assert_equal when Regexp assert = :assert_match else raise TypeError, "Expected #{expected.inspect} to be a kind of String or Regexp, not #{expected.class}" end ex = assert_raise(exception, *msg) {yield} msg = message(msg, "") {"Expected Exception(#{exception}) was raised, but the message doesn't match"} if assert == :assert_equal assert_equal(expected, ex.message, msg) else msg = message(msg) { "Expected #{mu_pp expected} to match #{mu_pp ex.message}" } assert expected =~ ex.message, msg block.binding.eval("proc{|_|$~=_}").call($~) end ex end def assert_file AssertFile end class << (AssertFile = Struct.new(:message).new) include Assertions def assert_file_predicate(predicate, *args) if /\Anot_/ =~ predicate predicate = $' neg = " not" end result = File.__send__(predicate, *args) result = !result if neg mesg = "Expected file " << args.shift.inspect mesg << mu_pp(args) unless args.empty? mesg << "#{neg} to be #{predicate}" mesg << " #{message}" if message assert(result, mesg) end alias method_missing assert_file_predicate def for(message) clone.tap {|a| a.message = message} end end end end end begin require 'rbconfig' rescue LoadError else module RbConfig @ruby = EnvUtil.rubybin class << self undef ruby if method_defined?(:ruby) attr_reader :ruby end dir = File.dirname(ruby) name = File.basename(ruby, CONFIG['EXEEXT']) CONFIG['bindir'] = dir CONFIG['ruby_install_name'] = name CONFIG['RUBY_INSTALL_NAME'] = name Gem::ConfigMap[:bindir] = dir if defined?(Gem::ConfigMap) end end begin require "openssl" # Disable FIPS mode for tests for installations # where FIPS mode would be enabled by default. # Has no effect on all other installations. OpenSSL.fips_mode=false rescue LoadError end require "test/unit" require "digest/md5" require 'tempfile' require "rbconfig" require "socket" module OpenSSL::TestUtils TEST_KEY_RSA1024 = OpenSSL::PKey::RSA.new <<-_end_of_pem_ -----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx aKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/ Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQAB AoGBAKSl/MQarye1yOysqX6P8fDFQt68VvtXkNmlSiKOGuzyho0M+UVSFcs6k1L0 maDE25AMZUiGzuWHyaU55d7RXDgeskDMakD1v6ZejYtxJkSXbETOTLDwUWTn618T gnb17tU1jktUtU67xK/08i/XodlgnQhs6VoHTuCh3Hu77O6RAkEA7+gxqBuZR572 74/akiW/SuXm0SXPEviyO1MuSRwtI87B02D0qgV8D1UHRm4AhMnJ8MCs1809kMQE JiQUCrp9mQJBANlt2ngBO14us6NnhuAseFDTBzCHXwUUu1YKHpMMmxpnGqaldGgX sOZB3lgJsT9VlGf3YGYdkLTNVbogQKlKpB8CQQDiSwkb4vyQfDe8/NpU5Not0fII 8jsDUCb+opWUTMmfbxWRR3FBNu8wnym/m19N4fFj8LqYzHX4KY0oVPu6qvJxAkEA wa5snNekFcqONLIE4G5cosrIrb74sqL8GbGb+KuTAprzj5z1K8Bm0UW9lTjVDjDi qRYgZfZSL+x1P/54+xTFSwJAY1FxA/N3QPCXCjPh5YqFxAMQs2VVYTfg+t0MEcJD dPMQD5JX6g5HKnHFg2mZtoXQrWmJSn7p8GJK8yNTopEErA== -----END RSA PRIVATE KEY----- _end_of_pem_ TEST_KEY_RSA2048 = OpenSSL::PKey::RSA.new <<-_end_of_pem_ -----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign 4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0 Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G 0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC 9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41 gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG 4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw== -----END RSA PRIVATE KEY----- _end_of_pem_ TEST_KEY_DSA256 = OpenSSL::PKey::DSA.new <<-_end_of_pem_ -----BEGIN DSA PRIVATE KEY----- MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE 9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM 3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn ISNX5cMzFHRW3Q== -----END DSA PRIVATE KEY----- _end_of_pem_ TEST_KEY_DSA512 = OpenSSL::PKey::DSA.new <<-_end_of_pem_ -----BEGIN DSA PRIVATE KEY----- MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++ Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S 55jreJD3Se3slps= -----END DSA PRIVATE KEY----- _end_of_pem_ if defined?(OpenSSL::PKey::EC) TEST_KEY_EC_P256V1 = OpenSSL::PKey::EC.new <<-_end_of_pem_ -----BEGIN EC PRIVATE KEY----- MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== -----END EC PRIVATE KEY----- _end_of_pem_ end TEST_KEY_DH512_PUB = OpenSSL::PKey::DH.new <<-_end_of_pem_ -----BEGIN DH PARAMETERS----- MEYCQQDmWXGPqk76sKw/edIOdhAQD4XzjJ+AR/PTk2qzaGs+u4oND2yU5D2NN4wr aPgwHyJBiK1/ebK3tYcrSKrOoRyrAgEC -----END DH PARAMETERS----- _end_of_pem_ TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_ -----BEGIN DH PARAMETERS----- MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0 pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC -----END DH PARAMETERS----- _end_of_pem_ TEST_KEY_DH1024.priv_key = OpenSSL::BN.new("48561834C67E65FFD2A9B47F41E5E78FDC95C387428FDB1E4B0188B64D1643C3A8D3455B945B7E8C4D166010C7C2CE23BFB9BEF43D0348FE7FA5284B0225E7FE1537546D114E3D8A4411B9B9351AB451E1A358F50ED61B1F00DA29336EEBBD649980AC86D76AF8BBB065298C2052672EEF3EF13AB47A15275FC2836F3AC74CEA", 16) DSA_SIGNATURE_DIGEST = OpenSSL::OPENSSL_VERSION_NUMBER > 0x10000000 ? OpenSSL::Digest::SHA1 : OpenSSL::Digest::DSS1 module_function def issue_cert(dn, key, serial, not_before, not_after, extensions, issuer, issuer_key, digest) cert = OpenSSL::X509::Certificate.new issuer = cert unless issuer issuer_key = key unless issuer_key cert.version = 2 cert.serial = serial cert.subject = dn cert.issuer = issuer.subject cert.public_key = key.public_key cert.not_before = not_before cert.not_after = not_after ef = OpenSSL::X509::ExtensionFactory.new ef.subject_certificate = cert ef.issuer_certificate = issuer extensions.each{|oid, value, critical| cert.add_extension(ef.create_extension(oid, value, critical)) } cert.sign(issuer_key, digest) cert end def issue_crl(revoke_info, serial, lastup, nextup, extensions, issuer, issuer_key, digest) crl = OpenSSL::X509::CRL.new crl.issuer = issuer.subject crl.version = 1 crl.last_update = lastup crl.next_update = nextup revoke_info.each{|rserial, time, reason_code| revoked = OpenSSL::X509::Revoked.new revoked.serial = rserial revoked.time = time enum = OpenSSL::ASN1::Enumerated(reason_code) ext = OpenSSL::X509::Extension.new("CRLReason", enum) revoked.add_extension(ext) crl.add_revoked(revoked) } ef = OpenSSL::X509::ExtensionFactory.new ef.issuer_certificate = issuer ef.crl = crl crlnum = OpenSSL::ASN1::Integer(serial) crl.add_extension(OpenSSL::X509::Extension.new("crlNumber", crlnum)) extensions.each{|oid, value, critical| crl.add_extension(ef.create_extension(oid, value, critical)) } crl.sign(issuer_key, digest) crl end def get_subject_key_id(cert) asn1_cert = OpenSSL::ASN1.decode(cert) tbscert = asn1_cert.value[0] pkinfo = tbscert.value[6] publickey = pkinfo.value[1] pkvalue = publickey.value OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase end def silent begin back, $VERBOSE = $VERBOSE, nil yield ensure $VERBOSE = back end end class OpenSSL::SSLTestCase < Test::Unit::TestCase RUBY = EnvUtil.rubybin SSL_SERVER = File.join(File.dirname(__FILE__), "ssl_server.rb") PORT = 20443 ITERATIONS = ($0 == __FILE__) ? 100 : 10 def setup @ca_key = OpenSSL::TestUtils::TEST_KEY_RSA2048 @svr_key = OpenSSL::TestUtils::TEST_KEY_RSA1024 @cli_key = OpenSSL::TestUtils::TEST_KEY_DSA256 @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA") @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost") now = Time.at(Time.now.to_i) ca_exts = [ ["basicConstraints","CA:TRUE",true], ["keyUsage","cRLSign,keyCertSign",true], ] ee_exts = [ ["keyUsage","keyEncipherment,digitalSignature",true], ] @ca_cert = issue_cert(@ca, @ca_key, 1, now, now+3600, ca_exts, nil, nil, OpenSSL::Digest::SHA1.new) @svr_cert = issue_cert(@svr, @svr_key, 2, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new) @cli_cert = issue_cert(@cli, @cli_key, 3, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new) @server = nil end def teardown end def issue_cert(*arg) OpenSSL::TestUtils.issue_cert(*arg) end def issue_crl(*arg) OpenSSL::TestUtils.issue_crl(*arg) end def readwrite_loop(ctx, ssl) while line = ssl.gets if line =~ /^STARTTLS$/ ssl.accept next end ssl.write(line) end rescue OpenSSL::SSL::SSLError rescue IOError ensure ssl.close rescue nil end def server_loop(ctx, ssls, server_proc) loop do ssl = nil begin ssl = ssls.accept rescue OpenSSL::SSL::SSLError retry end Thread.start do Thread.current.abort_on_exception = true server_proc.call(ctx, ssl) end end rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET end def start_server(port0, verify_mode, start_immediately, args = {}, &block) ctx_proc = args[:ctx_proc] server_proc = args[:server_proc] server_proc ||= method(:readwrite_loop) store = OpenSSL::X509::Store.new store.add_cert(@ca_cert) store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT ctx = OpenSSL::SSL::SSLContext.new ctx.cert_store = store #ctx.extra_chain_cert = [ ca_cert ] ctx.cert = @svr_cert ctx.key = @svr_key ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::TEST_KEY_DH1024 } ctx.verify_mode = verify_mode ctx_proc.call(ctx) if ctx_proc Socket.do_not_reverse_lookup = true tcps = nil port = port0 begin tcps = TCPServer.new("127.0.0.1", port) rescue Errno::EADDRINUSE port += 1 retry end ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx) ssls.start_immediately = start_immediately begin server = Thread.new do Thread.current.abort_on_exception = true server_loop(ctx, ssls, server_proc) end $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, $$, port) if $DEBUG block.call(server, port.to_i) ensure begin begin tcps.shutdown rescue Errno::ENOTCONN # when `Errno::ENOTCONN: Socket is not connected' on some platforms, # call #close instead of #shutdown. tcps.close tcps = nil end if (tcps) if (server) server.join(5) if server.alive? server.kill server.join flunk("TCPServer was closed and SSLServer is still alive") unless $! end end ensure tcps.close if (tcps) end end end def starttls(ssl) ssl.puts("STARTTLS") sleep 1 # When this line is eliminated, process on Cygwin blocks # forever at ssl.connect. But I don't know why it does. ssl.connect end end class OpenSSL::TestCipher < Test::Unit::TestCase class << self def has_cipher?(name) ciphers = OpenSSL::Cipher.ciphers # redefine method so we can use the cached ciphers value from the closure # and need not recompute the list each time define_singleton_method :has_cipher? do |name| ciphers.include?(name) end has_cipher?(name) end def has_ciphers?(list) list.all? { |name| has_cipher?(name) } end end def setup @c1 = OpenSSL::Cipher::Cipher.new("DES-EDE3-CBC") @c2 = OpenSSL::Cipher::DES.new(:EDE3, "CBC") @key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" @iv = "\0\0\0\0\0\0\0\0" @hexkey = "0000000000000000000000000000000000000000000000" @hexiv = "0000000000000000" @data = "DATA" end def teardown @c1 = @c2 = nil end def test_crypt @c1.encrypt.pkcs5_keyivgen(@key, @iv) @c2.encrypt.pkcs5_keyivgen(@key, @iv) s1 = @c1.update(@data) + @c1.final s2 = @c2.update(@data) + @c2.final assert_equal(s1, s2, "encrypt") @c1.decrypt.pkcs5_keyivgen(@key, @iv) @c2.decrypt.pkcs5_keyivgen(@key, @iv) assert_equal(@data, @c1.update(s1)+@c1.final, "decrypt") assert_equal(@data, @c2.update(s2)+@c2.final, "decrypt") end def test_info assert_equal("DES-EDE3-CBC", @c1.name, "name") assert_equal("DES-EDE3-CBC", @c2.name, "name") assert_kind_of(Fixnum, @c1.key_len, "key_len") assert_kind_of(Fixnum, @c1.iv_len, "iv_len") end def test_dup assert_equal(@c1.name, @c1.dup.name, "dup") assert_equal(@c1.name, @c1.clone.name, "clone") @c1.encrypt @c1.key = @key @c1.iv = @iv tmpc = @c1.dup s1 = @c1.update(@data) + @c1.final s2 = tmpc.update(@data) + tmpc.final assert_equal(s1, s2, "encrypt dup") end def test_reset @c1.encrypt @c1.key = @key @c1.iv = @iv s1 = @c1.update(@data) + @c1.final @c1.reset s2 = @c1.update(@data) + @c1.final assert_equal(s1, s2, "encrypt reset") end def test_empty_data @c1.encrypt @c1.key = @key assert_raise(ArgumentError){ @c1.update("") } end def test_initialize assert_raise(RuntimeError) {@c1.__send__(:initialize, "DES-EDE3-CBC")} assert_raise(RuntimeError) {OpenSSL::Cipher.allocate.final} end def test_ctr_if_exists begin cipher = OpenSSL::Cipher.new('aes-128-ctr') cipher.encrypt cipher.pkcs5_keyivgen('password') c = cipher.update('hello,world') + cipher.final cipher.decrypt cipher.pkcs5_keyivgen('password') assert_equal('hello,world', cipher.update(c) + cipher.final) end end if has_cipher?('aes-128-ctr') if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00907000 def test_ciphers OpenSSL::Cipher.ciphers.each{|name| next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name begin assert_kind_of(OpenSSL::Cipher::Cipher, OpenSSL::Cipher::Cipher.new(name)) rescue OpenSSL::Cipher::CipherError => e next if /wrap/ =~ name and e.message == 'wrap mode not allowed' raise end } end def test_AES pt = File.read(__FILE__) %w(ECB CBC CFB OFB).each{|mode| c1 = OpenSSL::Cipher::AES256.new(mode) c1.encrypt c1.pkcs5_keyivgen("passwd") ct = c1.update(pt) + c1.final c2 = OpenSSL::Cipher::AES256.new(mode) c2.decrypt c2.pkcs5_keyivgen("passwd") assert_equal(pt, c2.update(ct) + c2.final) } end def test_update_raise_if_key_not_set assert_raise(OpenSSL::Cipher::CipherError) do # it caused OpenSSL SEGV by uninitialized key [Bug #2768] OpenSSL::Cipher::AES128.new("ECB").update "." * 17 end end end if has_ciphers?(['aes-128-gcm', 'aes-192-gcm', 'aes-128-gcm']) def test_authenticated cipher = OpenSSL::Cipher.new('aes-128-gcm') assert(cipher.authenticated?) cipher = OpenSSL::Cipher.new('aes-128-cbc') refute(cipher.authenticated?) end def test_aes_gcm ['aes-128-gcm', 'aes-192-gcm', 'aes-128-gcm'].each do |algo| pt = "You should all use Authenticated Encryption!" cipher, key, iv = new_encryptor(algo) cipher.auth_data = "aad" ct = cipher.update(pt) + cipher.final tag = cipher.auth_tag assert_equal(16, tag.size) decipher = new_decryptor(algo, key, iv) decipher.auth_tag = tag decipher.auth_data = "aad" assert_equal(pt, decipher.update(ct) + decipher.final) end end def test_aes_gcm_short_tag ['aes-128-gcm', 'aes-192-gcm', 'aes-128-gcm'].each do |algo| pt = "You should all use Authenticated Encryption!" cipher, key, iv = new_encryptor(algo) cipher.auth_data = "aad" ct = cipher.update(pt) + cipher.final tag = cipher.auth_tag(8) assert_equal(8, tag.size) decipher = new_decryptor(algo, key, iv) decipher.auth_tag = tag decipher.auth_data = "aad" assert_equal(pt, decipher.update(ct) + decipher.final) end end def test_aes_gcm_wrong_tag pt = "You should all use Authenticated Encryption!" cipher, key, iv = new_encryptor('aes-128-gcm') cipher.auth_data = "aad" ct = cipher.update(pt) + cipher.final tag = cipher.auth_tag decipher = new_decryptor('aes-128-gcm', key, iv) tag.setbyte(-1, (tag.getbyte(-1) + 1) & 0xff) decipher.auth_tag = tag decipher.auth_data = "aad" assert_raise OpenSSL::Cipher::CipherError do decipher.update(ct) + decipher.final end end def test_aes_gcm_wrong_auth_data pt = "You should all use Authenticated Encryption!" cipher, key, iv = new_encryptor('aes-128-gcm') cipher.auth_data = "aad" ct = cipher.update(pt) + cipher.final tag = cipher.auth_tag decipher = new_decryptor('aes-128-gcm', key, iv) decipher.auth_tag = tag decipher.auth_data = "daa" assert_raise OpenSSL::Cipher::CipherError do decipher.update(ct) + decipher.final end end def test_aes_gcm_wrong_ciphertext pt = "You should all use Authenticated Encryption!" cipher, key, iv = new_encryptor('aes-128-gcm') cipher.auth_data = "aad" ct = cipher.update(pt) + cipher.final tag = cipher.auth_tag decipher = new_decryptor('aes-128-gcm', key, iv) decipher.auth_tag = tag decipher.auth_data = "aad" assert_raise OpenSSL::Cipher::CipherError do decipher.update(ct[0..-2] << ct[-1].succ) + decipher.final end end def test_aes_gcm_key_iv_order_issue pt = "You should all use Authenticated Encryption!" cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt cipher.key = "x" * 16 cipher.iv = "a" * 12 ct1 = cipher.update(pt) << cipher.final tag1 = cipher.auth_tag cipher = OpenSSL::Cipher.new("aes-128-gcm").encrypt cipher.iv = "a" * 12 cipher.key = "x" * 16 ct2 = cipher.update(pt) << cipher.final tag2 = cipher.auth_tag assert_equal ct1, ct2 assert_equal tag1, tag2 end if has_cipher?("aes-128-gcm") end private def new_encryptor(algo) cipher = OpenSSL::Cipher.new(algo) cipher.encrypt key = cipher.random_key iv = cipher.random_iv [cipher, key, iv] end def new_decryptor(algo, key, iv) OpenSSL::Cipher.new(algo).tap do |cipher| cipher.decrypt cipher.key = key cipher.iv = iv end end end end
View Attachment As Raw
Actions:
View
Attachments on
bug 19501
:
8486
|
8509
| 8511