From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001
From: Jari Vetoniemi <jari.vetoniemi@indooratlas.com>
Date: Mon, 16 Mar 2020 18:49:26 +0900
Subject: Fresh start

---
 jni/ruby/sample/openssl/c_rehash.rb    | 174 +++++++++++++++++++++++++++++++++
 jni/ruby/sample/openssl/cert2text.rb   |  23 +++++
 jni/ruby/sample/openssl/certstore.rb   | 161 ++++++++++++++++++++++++++++++
 jni/ruby/sample/openssl/cipher.rb      |  54 ++++++++++
 jni/ruby/sample/openssl/crlstore.rb    | 122 +++++++++++++++++++++++
 jni/ruby/sample/openssl/echo_cli.rb    |  44 +++++++++
 jni/ruby/sample/openssl/echo_svr.rb    |  65 ++++++++++++
 jni/ruby/sample/openssl/gen_csr.rb     |  51 ++++++++++
 jni/ruby/sample/openssl/smime_read.rb  |  23 +++++
 jni/ruby/sample/openssl/smime_write.rb |  23 +++++
 jni/ruby/sample/openssl/wget.rb        |  34 +++++++
 11 files changed, 774 insertions(+)
 create mode 100644 jni/ruby/sample/openssl/c_rehash.rb
 create mode 100644 jni/ruby/sample/openssl/cert2text.rb
 create mode 100644 jni/ruby/sample/openssl/certstore.rb
 create mode 100644 jni/ruby/sample/openssl/cipher.rb
 create mode 100644 jni/ruby/sample/openssl/crlstore.rb
 create mode 100644 jni/ruby/sample/openssl/echo_cli.rb
 create mode 100644 jni/ruby/sample/openssl/echo_svr.rb
 create mode 100644 jni/ruby/sample/openssl/gen_csr.rb
 create mode 100644 jni/ruby/sample/openssl/smime_read.rb
 create mode 100644 jni/ruby/sample/openssl/smime_write.rb
 create mode 100644 jni/ruby/sample/openssl/wget.rb

(limited to 'jni/ruby/sample/openssl')

diff --git a/jni/ruby/sample/openssl/c_rehash.rb b/jni/ruby/sample/openssl/c_rehash.rb
new file mode 100644
index 0000000..cd6c9d5
--- /dev/null
+++ b/jni/ruby/sample/openssl/c_rehash.rb
@@ -0,0 +1,174 @@
+#!/usr/bin/env ruby
+
+require 'openssl'
+require 'digest/md5'
+
+class CHashDir
+  include Enumerable
+
+  def initialize(dirpath)
+    @dirpath = dirpath
+    @fingerprint_cache = @cert_cache = @crl_cache = nil
+  end
+
+  def hash_dir(silent = false)
+    # ToDo: Should lock the directory...
+    @silent = silent
+    @fingerprint_cache = Hash.new
+    @cert_cache = Hash.new
+    @crl_cache = Hash.new
+    do_hash_dir
+  end
+
+  def get_certs(name = nil)
+    if name
+      @cert_cache[hash_name(name)]
+    else
+      @cert_cache.values.flatten
+    end
+  end
+
+  def get_crls(name = nil)
+    if name
+      @crl_cache[hash_name(name)]
+    else
+      @crl_cache.values.flatten
+    end
+  end
+
+  def delete_crl(crl)
+    File.unlink(crl_filename(crl))
+    hash_dir(true)
+  end
+
+  def add_crl(crl)
+    File.open(crl_filename(crl), "w") do |f|
+      f << crl.to_pem
+    end
+    hash_dir(true)
+  end
+
+  def load_pem_file(filepath)
+    str = File.read(filepath)
+    begin
+      OpenSSL::X509::Certificate.new(str)
+    rescue
+      begin
+        OpenSSL::X509::CRL.new(str)
+      rescue
+        begin
+          OpenSSL::X509::Request.new(str)
+        rescue
+          nil
+        end
+      end
+    end
+  end
+
+private
+
+  def crl_filename(crl)
+    path(hash_name(crl.issuer)) + '.pem'
+  end
+
+  def do_hash_dir
+    Dir.chdir(@dirpath) do
+      delete_symlink
+      Dir.glob('*.pem') do |pemfile|
+        cert = load_pem_file(pemfile)
+        case cert
+        when OpenSSL::X509::Certificate
+          link_hash_cert(pemfile, cert)
+        when OpenSSL::X509::CRL
+          link_hash_crl(pemfile, cert)
+        else
+          STDERR.puts("WARNING: #{pemfile} does not contain a certificate or CRL: skipping") unless @silent
+        end
+      end
+    end
+  end
+
+  def delete_symlink
+    Dir.entries(".").each do |entry|
+      next unless /^[\da-f]+\.r{0,1}\d+$/ =~ entry
+      File.unlink(entry) if FileTest.symlink?(entry)
+    end
+  end
+
+  def link_hash_cert(org_filename, cert)
+    name_hash = hash_name(cert.subject)
+    fingerprint = fingerprint(cert.to_der)
+    filepath = link_hash(org_filename, name_hash, fingerprint) { |idx|
+      "#{name_hash}.#{idx}"
+    }
+    unless filepath
+      unless @silent
+        STDERR.puts("WARNING: Skipping duplicate certificate #{org_filename}")
+      end
+    else
+      (@cert_cache[name_hash] ||= []) << path(filepath)
+    end
+  end
+
+  def link_hash_crl(org_filename, crl)
+    name_hash = hash_name(crl.issuer)
+    fingerprint = fingerprint(crl.to_der)
+    filepath = link_hash(org_filename, name_hash, fingerprint) { |idx|
+      "#{name_hash}.r#{idx}"
+    }
+    unless filepath
+      unless @silent
+        STDERR.puts("WARNING: Skipping duplicate CRL #{org_filename}")
+      end
+    else
+      (@crl_cache[name_hash] ||= []) << path(filepath)
+    end
+  end
+
+  def link_hash(org_filename, name, fingerprint)
+    idx = 0
+    filepath = nil
+    while true
+      filepath = yield(idx)
+      break unless FileTest.symlink?(filepath) or FileTest.exist?(filepath)
+      if @fingerprint_cache[filepath] == fingerprint
+        return false
+      end
+      idx += 1
+    end
+    STDOUT.puts("#{org_filename} => #{filepath}") unless @silent
+    symlink(org_filename, filepath)
+    @fingerprint_cache[filepath] = fingerprint
+    filepath
+  end
+
+  def symlink(from, to)
+    begin
+      File.symlink(from, to)
+    rescue
+      File.open(to, "w") do |f|
+        f << File.read(from)
+      end
+    end
+  end
+
+  def path(filename)
+    File.join(@dirpath, filename)
+  end
+
+  def hash_name(name)
+    sprintf("%x", name.hash)
+  end
+
+  def fingerprint(der)
+    Digest::MD5.hexdigest(der).upcase
+  end
+end
+
+if $0 == __FILE__
+  dirlist = ARGV
+  dirlist << '/usr/ssl/certs' if dirlist.empty?
+  dirlist.each do |dir|
+    CHashDir.new(dir).hash_dir
+  end
+end
diff --git a/jni/ruby/sample/openssl/cert2text.rb b/jni/ruby/sample/openssl/cert2text.rb
new file mode 100644
index 0000000..50da224
--- /dev/null
+++ b/jni/ruby/sample/openssl/cert2text.rb
@@ -0,0 +1,23 @@
+#!/usr/bin/env ruby
+
+require 'openssl'
+include OpenSSL::X509
+
+def cert2text(cert_str)
+  [Certificate, CRL, Request].each do |klass|
+    begin
+      puts klass.new(cert_str).to_text
+      return
+    rescue
+    end
+  end
+  raise ArgumentError.new('Unknown format.')
+end
+
+if ARGV.empty?
+  cert2text(STDIN.read)
+else
+  ARGV.each do |file|
+    cert2text(File.read(file))
+  end
+end
diff --git a/jni/ruby/sample/openssl/certstore.rb b/jni/ruby/sample/openssl/certstore.rb
new file mode 100644
index 0000000..c6e8f81
--- /dev/null
+++ b/jni/ruby/sample/openssl/certstore.rb
@@ -0,0 +1,161 @@
+require 'c_rehash'
+require 'crlstore'
+
+
+class CertStore
+  include OpenSSL
+  include X509
+
+  attr_reader :self_signed_ca
+  attr_reader :other_ca
+  attr_reader :ee
+  attr_reader :crl
+  attr_reader :request
+
+  def initialize(certs_dir)
+    @certs_dir = certs_dir
+    @c_store = CHashDir.new(@certs_dir)
+    @c_store.hash_dir(true)
+    @crl_store = CrlStore.new(@c_store)
+    @x509store = Store.new
+    @self_signed_ca = @other_ca = @ee = @crl = nil
+
+    # Uncomment this line to let OpenSSL to check CRL for each certs.
+    # @x509store.flags = V_FLAG_CRL_CHECK | V_FLAG_CRL_CHECK_ALL
+
+    add_path
+    scan_certs
+  end
+
+  def generate_cert(filename)
+    @c_store.load_pem_file(filename)
+  end
+
+  def verify(cert)
+    error, crl_map = do_verify(cert)
+    if error
+      [[false, cert, crl_map[cert.subject], error]]
+    else
+      @x509store.chain.collect { |c| [true, c, crl_map[c.subject], nil] }
+    end
+  end
+
+  def match_cert(cert1, cert2)
+    (cert1.issuer.cmp(cert2.issuer) == 0) and cert1.serial == cert2.serial
+  end
+
+  def is_ca?(cert)
+    case guess_cert_type(cert)
+    when CERT_TYPE_SELF_SIGNED
+      true
+    when CERT_TYPE_OTHER
+      true
+    else
+      false
+    end
+  end
+
+  def scan_certs
+    @self_signed_ca = []
+    @other_ca = []
+    @ee = []
+    @crl = []
+    @request = []
+    load_certs
+  end
+
+private
+
+  def add_path
+    @x509store.add_path(@certs_dir)
+  end
+
+  def do_verify(cert)
+    error_map = {}
+    crl_map = {}
+    result = @x509store.verify(cert) do |ok, ctx|
+      cert = ctx.current_cert
+      if ctx.current_crl
+        crl_map[cert.subject] = true
+      end
+      if ok
+        if !ctx.current_crl
+          if crl = @crl_store.find_crl(cert)
+            crl_map[cert.subject] = true
+            if crl.revoked.find { |revoked| revoked.serial == cert.serial }
+              ok = false
+              error_string = 'certification revoked'
+            end
+          end
+        end
+      end
+      error_map[cert.subject] = error_string if error_string
+      ok
+    end
+    error = if result
+      nil
+    else
+      error_map[cert.subject] || @x509store.error_string
+    end
+    return error, crl_map
+  end
+
+  def load_certs
+    @c_store.get_certs.each do |certfile|
+      cert = generate_cert(certfile)
+      case guess_cert_type(cert)
+      when CERT_TYPE_SELF_SIGNED
+        @self_signed_ca << cert
+      when CERT_TYPE_OTHER
+        @other_ca << cert
+      when CERT_TYPE_EE
+        @ee << cert
+      else
+        raise "Unknown cert type."
+      end
+    end
+    @c_store.get_crls.each do |crlfile|
+      @crl << generate_cert(crlfile)
+    end
+  end
+
+  CERT_TYPE_SELF_SIGNED = 0
+  CERT_TYPE_OTHER = 1
+  CERT_TYPE_EE = 2
+  def guess_cert_type(cert)
+    ca = self_signed = is_cert_self_signed(cert)
+    cert.extensions.each do |ext|
+      # Ignores criticality of extensions.  It's 'guess'ing.
+      case ext.oid
+      when 'basicConstraints'
+        /CA:(TRUE|FALSE), pathlen:(\d+)/ =~ ext.value
+        ca = ($1 == 'TRUE') unless ca
+      when 'keyUsage'
+        usage = ext.value.split(/\s*,\s*/)
+        ca = usage.include?('Certificate Sign') unless ca
+      when 'nsCertType'
+        usage = ext.value.split(/\s*,\s*/)
+        ca = usage.include?('SSL CA') unless ca
+      end
+    end
+    if ca
+      if self_signed
+        CERT_TYPE_SELF_SIGNED
+      else
+        CERT_TYPE_OTHER
+      end
+    else
+      CERT_TYPE_EE
+    end
+  end
+
+  def is_cert_self_signed(cert)
+    # cert.subject.cmp(cert.issuer) == 0
+    cert.subject.to_s == cert.issuer.to_s
+  end
+end
+
+
+if $0 == __FILE__
+  c = CertStore.new("trust_certs")
+end
diff --git a/jni/ruby/sample/openssl/cipher.rb b/jni/ruby/sample/openssl/cipher.rb
new file mode 100644
index 0000000..58b10d6
--- /dev/null
+++ b/jni/ruby/sample/openssl/cipher.rb
@@ -0,0 +1,54 @@
+#!/usr/bin/env ruby
+require 'openssl'
+
+def crypt_by_password(alg, pass, salt, text)
+  puts "--Setup--"
+  puts %(cipher alg:    "#{alg}")
+  puts %(plain text:    "#{text}")
+  puts %(password:      "#{pass}")
+  puts %(salt:          "#{salt}")
+  puts
+
+  puts "--Encrypting--"
+  enc = OpenSSL::Cipher::Cipher.new(alg)
+  enc.encrypt
+  enc.pkcs5_keyivgen(pass, salt)
+  cipher =  enc.update(text)
+  cipher << enc.final
+  puts %(encrypted text: #{cipher.inspect})
+  puts
+
+  puts "--Decrypting--"
+  dec = OpenSSL::Cipher::Cipher.new(alg)
+  dec.decrypt
+  dec.pkcs5_keyivgen(pass, salt)
+  plain =  dec.update(cipher)
+  plain << dec.final
+  puts %(decrypted text: "#{plain}")
+  puts
+end
+
+def ciphers
+  ciphers = OpenSSL::Cipher.ciphers.sort
+  ciphers.each{|i|
+    if i.upcase != i && ciphers.include?(i.upcase)
+      ciphers.delete(i)
+    end
+  }
+  return ciphers
+end
+
+puts "Supported ciphers in #{OpenSSL::OPENSSL_VERSION}:"
+ciphers.each_with_index{|name, i|
+  printf("%-15s", name)
+  puts if (i + 1) % 5 == 0
+}
+puts
+puts
+
+alg  = ARGV.shift || ciphers.first
+pass = "secret password"
+salt = "8 octets"        # or nil
+text = "abcdefghijklmnopqrstuvwxyz"
+
+crypt_by_password(alg, pass, salt, text)
diff --git a/jni/ruby/sample/openssl/crlstore.rb b/jni/ruby/sample/openssl/crlstore.rb
new file mode 100644
index 0000000..e3a5925
--- /dev/null
+++ b/jni/ruby/sample/openssl/crlstore.rb
@@ -0,0 +1,122 @@
+begin
+  require 'http-access2'
+rescue LoadError
+  STDERR.puts("Cannot load http-access2.  CRL might not be fetched.")
+end
+require 'c_rehash'
+
+
+class CrlStore
+  def initialize(c_store)
+    @c_store = c_store
+    @c_store.hash_dir(true)
+  end
+
+  def find_crl(cert)
+    do_find_crl(cert)
+  end
+
+private
+
+  def do_find_crl(cert)
+    unless ca = find_ca(cert)
+      return nil
+    end
+    unless crlfiles = @c_store.get_crls(ca.subject)
+      if crl = renew_crl(cert, ca)
+        @c_store.add_crl(crl)
+        return crl
+      end
+      return nil
+    end
+    crlfiles.each do |crlfile|
+      next unless crl = load_crl(crlfile)
+      if crl.next_update < Time.now
+        if new_crl = renew_crl(cert, ca)
+          @c_store.delete_crl(crl)
+          @c_store.add_crl(new_crl)
+          crl = new_crl
+        end
+      end
+      if check_valid(crl, ca)
+        return crl
+      end
+    end
+    nil
+  end
+
+  def find_ca(cert)
+    @c_store.get_certs(cert.issuer).each do |cafile|
+      ca = load_cert(cafile)
+      if cert.verify(ca.public_key)
+        return ca
+      end
+    end
+    nil
+  end
+
+  def fetch(location)
+    if /\AURI:(.*)\z/ =~ location
+      begin
+        c = HTTPAccess2::Client.new(ENV['http_proxy'] || ENV['HTTP_PROXY'])
+        c.get_content($1)
+      rescue NameError, StandardError
+        nil
+      end
+    else
+      nil
+    end
+  end
+
+  def load_cert(certfile)
+    load_cert_str(File.read(certfile))
+  end
+
+  def load_crl(crlfile)
+    load_crl_str(File.read(crlfile))
+  end
+
+  def load_cert_str(cert_str)
+    OpenSSL::X509::Certificate.new(cert_str)
+  end
+
+  def load_crl_str(crl_str)
+    OpenSSL::X509::CRL.new(crl_str)
+  end
+
+  def check_valid(crl, ca)
+    unless crl.verify(ca.public_key)
+      return false
+    end
+    crl.last_update <= Time.now
+  end
+
+  RE_CDP = /\AcrlDistributionPoints\z/
+  def get_cdp(cert)
+    if cdp_ext = cert.extensions.find { |ext| RE_CDP =~ ext.oid }
+      cdp_ext.value.chomp
+    else
+      false
+    end
+  end
+
+  def renew_crl(cert, ca)
+    if cdp = get_cdp(cert)
+      if new_crl_str = fetch(cdp)
+        new_crl = load_crl_str(new_crl_str)
+        if check_valid(new_crl, ca)
+          return new_crl
+        end
+      end
+    end
+    false
+  end
+end
+
+if $0 == __FILE__
+  dir = "trust_certs"
+  c_store = CHashDir.new(dir)
+  s = CrlStore.new(c_store)
+  c = OpenSSL::X509::Certificate.new(File.read("cert_store/google_codesign.pem"))
+  p s.find_crl(c)
+end
diff --git a/jni/ruby/sample/openssl/echo_cli.rb b/jni/ruby/sample/openssl/echo_cli.rb
new file mode 100644
index 0000000..069a21e
--- /dev/null
+++ b/jni/ruby/sample/openssl/echo_cli.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env ruby
+
+require 'socket'
+require 'openssl'
+require 'optparse'
+
+options = ARGV.getopts("p:c:k:C:")
+
+host      = ARGV[0] || "localhost"
+port      = options["p"] || "2000"
+cert_file = options["c"]
+key_file  = options["k"]
+ca_path   = options["C"]
+
+ctx = OpenSSL::SSL::SSLContext.new()
+if cert_file && key_file
+  ctx.cert = OpenSSL::X509::Certificate.new(File::read(cert_file))
+  ctx.key  = OpenSSL::PKey::RSA.new(File::read(key_file))
+end
+if ca_path
+  ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
+  ctx.ca_path = ca_path
+else
+  $stderr.puts "!!! WARNING: PEER CERTIFICATE WON'T BE VERIFIED !!!"
+end
+
+s = TCPSocket.new(host, port)
+ssl = OpenSSL::SSL::SSLSocket.new(s, ctx)
+ssl.connect # start SSL session
+p ssl.peer_cert
+errors = Hash.new
+OpenSSL::X509.constants.grep(/^V_(ERR_|OK)/).each do |name|
+  errors[OpenSSL::X509.const_get(name)] = name
+end
+p errors[ssl.verify_result]
+
+ssl.sync_close = true  # if true the underlying socket will be
+                       # closed in SSLSocket#close. (default: false)
+while line = $stdin.gets
+  ssl.write line
+  puts ssl.gets.inspect
+end
+
+ssl.close
diff --git a/jni/ruby/sample/openssl/echo_svr.rb b/jni/ruby/sample/openssl/echo_svr.rb
new file mode 100644
index 0000000..719de6b
--- /dev/null
+++ b/jni/ruby/sample/openssl/echo_svr.rb
@@ -0,0 +1,65 @@
+#!/usr/bin/env ruby
+
+require 'socket'
+require 'openssl'
+require 'optparse'
+
+options = ARGV.getopts("p:c:k:C:")
+
+port      = options["p"] || "2000"
+cert_file = options["c"]
+key_file  = options["k"]
+ca_path   = options["C"]
+
+if cert_file && key_file
+  cert = OpenSSL::X509::Certificate.new(File::read(cert_file))
+  key  = OpenSSL::PKey::RSA.new(File::read(key_file))
+else
+  key = OpenSSL::PKey::RSA.new(512){ print "." }
+  puts
+  cert = OpenSSL::X509::Certificate.new
+  cert.version = 2
+  cert.serial = 0
+  name = OpenSSL::X509::Name.new([["C","JP"],["O","TEST"],["CN","localhost"]])
+  cert.subject = name
+  cert.issuer = name
+  cert.not_before = Time.now
+  cert.not_after = Time.now + 3600
+  cert.public_key = key.public_key
+  ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
+  cert.extensions = [
+    ef.create_extension("basicConstraints","CA:FALSE"),
+    ef.create_extension("subjectKeyIdentifier","hash"),
+    ef.create_extension("extendedKeyUsage","serverAuth"),
+    ef.create_extension("keyUsage",
+                        "keyEncipherment,dataEncipherment,digitalSignature")
+  ]
+  ef.issuer_certificate = cert
+  cert.add_extension ef.create_extension("authorityKeyIdentifier",
+                                         "keyid:always,issuer:always")
+  cert.sign(key, OpenSSL::Digest::SHA1.new)
+end
+
+ctx = OpenSSL::SSL::SSLContext.new()
+ctx.key = key
+ctx.cert = cert
+if ca_path
+  ctx.verify_mode =
+    OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
+  ctx.ca_path = ca_path
+else
+  $stderr.puts "!!! WARNING: PEER CERTIFICATE WON'T BE VERIFIED !!!"
+end
+
+tcps = TCPServer.new(port)
+ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
+loop do
+  ns = ssls.accept
+  puts "connected from #{ns.peeraddr}"
+  while line = ns.gets
+    puts line.inspect
+    ns.write line
+  end
+  puts "connection closed"
+  ns.close
+end
diff --git a/jni/ruby/sample/openssl/gen_csr.rb b/jni/ruby/sample/openssl/gen_csr.rb
new file mode 100644
index 0000000..4228707
--- /dev/null
+++ b/jni/ruby/sample/openssl/gen_csr.rb
@@ -0,0 +1,51 @@
+#!/usr/bin/env ruby
+
+require 'optparse'
+require 'openssl'
+
+include OpenSSL
+
+def usage
+  myname = File::basename($0)
+  $stderr.puts <<EOS
+Usage: #{myname} [--key keypair_file] name
+  name ... ex. /C=JP/O=RRR/OU=CA/CN=NaHi/emailAddress=nahi@example.org
+EOS
+  exit
+end
+
+options = ARGV.getopts(nil, "key:", "csrout:", "keyout:")
+keypair_file = options["key"]
+csrout = options["csrout"] || "csr.pem"
+keyout = options["keyout"] || "keypair.pem"
+
+$stdout.sync = true
+name_str = ARGV.shift or usage()
+name = X509::Name.parse(name_str)
+
+keypair = nil
+if keypair_file
+  keypair = PKey::RSA.new(File.open(keypair_file).read)
+else
+  keypair = PKey::RSA.new(1024) { putc "." }
+  puts
+  puts "Writing #{keyout}..."
+  File.open(keyout, "w", 0400) do |f|
+    f << keypair.to_pem
+  end
+end
+
+puts "Generating CSR for #{name_str}"
+
+req = X509::Request.new
+req.version = 0
+req.subject = name
+req.public_key = keypair.public_key
+req.sign(keypair, Digest::MD5.new)
+
+puts "Writing #{csrout}..."
+File.open(csrout, "w") do |f|
+  f << req.to_pem
+end
+puts req.to_text
+puts req.to_pem
diff --git a/jni/ruby/sample/openssl/smime_read.rb b/jni/ruby/sample/openssl/smime_read.rb
new file mode 100644
index 0000000..17394f9
--- /dev/null
+++ b/jni/ruby/sample/openssl/smime_read.rb
@@ -0,0 +1,23 @@
+require 'optparse'
+require 'openssl'
+include OpenSSL
+
+options = ARGV.getopts("c:k:C:")
+
+cert_file = options["c"]
+key_file  = options["k"]
+ca_path   = options["C"]
+
+data = $stdin.read
+
+cert = X509::Certificate.new(File::read(cert_file))
+key = PKey::RSA.new(File::read(key_file))
+p7enc = PKCS7::read_smime(data)
+data = p7enc.decrypt(key, cert)
+
+store = X509::Store.new
+store.add_path(ca_path)
+p7sig = PKCS7::read_smime(data)
+if p7sig.verify([], store)
+  puts p7sig.data
+end
diff --git a/jni/ruby/sample/openssl/smime_write.rb b/jni/ruby/sample/openssl/smime_write.rb
new file mode 100644
index 0000000..5a5236c
--- /dev/null
+++ b/jni/ruby/sample/openssl/smime_write.rb
@@ -0,0 +1,23 @@
+require 'openssl'
+require 'optparse'
+include OpenSSL
+
+options = ARGV.getopts("c:k:r:")
+
+cert_file = options["c"]
+key_file  = options["k"]
+rcpt_file = options["r"]
+
+cert = X509::Certificate.new(File::read(cert_file))
+key = PKey::RSA.new(File::read(key_file))
+
+data  = "Content-Type: text/plain\r\n"
+data << "\r\n"
+data << "This is a clear-signed message.\r\n"
+
+p7sig  = PKCS7::sign(cert, key, data, [], PKCS7::DETACHED)
+smime0 = PKCS7::write_smime(p7sig)
+
+rcpt  = X509::Certificate.new(File::read(rcpt_file))
+p7enc = PKCS7::encrypt([rcpt], smime0)
+print PKCS7::write_smime(p7enc)
diff --git a/jni/ruby/sample/openssl/wget.rb b/jni/ruby/sample/openssl/wget.rb
new file mode 100644
index 0000000..ee63720
--- /dev/null
+++ b/jni/ruby/sample/openssl/wget.rb
@@ -0,0 +1,34 @@
+#!/usr/bin/env ruby
+
+require 'net/https'
+require 'optparse'
+
+options = ARGV.getopts('C:')
+
+cert_store = options["C"]
+
+uri = URI.parse(ARGV[0])
+if proxy = ENV['HTTP_PROXY']
+  prx_uri = URI.parse(proxy)
+  prx_host = prx_uri.host
+  prx_port = prx_uri.port
+end
+
+h = Net::HTTP.new(uri.host, uri.port, prx_host, prx_port)
+h.set_debug_output($stderr) if $DEBUG
+if uri.scheme == "https"
+  h.use_ssl = true
+  if cert_store
+    if File.directory?(cert_store)
+      h.ca_path = cert_store
+    else
+      h.ca_file = cert_store
+    end
+  end
+end
+
+path = uri.path.empty? ? "/" : uri.path
+h.get2(path){|resp|
+  STDERR.puts h.peer_cert.inspect if h.peer_cert
+  print resp.body
+}
-- 
cgit v1.2.3-70-g09d2