Hi, > From: "Joel VanderWerf" <vjoel / PATH.Berkeley.EDU> > Sent: Wednesday, January 14, 2004 5:54 PM > > Maybe, the next issue might be "how to generate key and certificate" > > -> "how to create CA (certificate authority)" -> "how to setup > > drbssl client/server with key/certificate". If you are really a > > ssl newbie (sorry), it's rather a long road. Do you really need > > SSL? > > Well, maybe not. In my distributed app, users have passwords that they > use in their drb clients to access their own data in the server. The > data itself is not critical, though, so a stolen password is not the end > of the world (and the server itself will be SAFE enough not to do any > harm). I was hoping SSL would be easy to plug in to drb, and generating > keys would be as easy as it is for SSH (maybe it is?). Unfortunately, no. You'll know... > > I'll be able to post setup log of this tomorrow or the next if you > > want. Though I've not used drb with ssl yet. > > Only if you feel like it, NaHi. But I have a feeling the next step is > for me to read the openssl man page.... Setting CA up with openssl command line sample can be found from Google. But I love ruby. I feel like it. Here we go. ### ## Get setup scripts. # 0$ mkdir ~/drbssldemo 0$ cd ~/drbssldemo 0$ wget http://rrr.jin.gr.jp/dav/NaHi/casetupssample/casetupsample_20040115.tar.gz --12:05:08-- http://rrr.jin.gr.jp/dav/NaHi/casetupssample/casetupsample_20040115.tar.gz => `casetupsample_20040115.tar.gz' Resolving rrr.jin.gr.jp... 61.120.18.100 Connecting to rrr.jin.gr.jp[61.120.18.100]:80... connected. HTTP request sent, awaiting response... 200 OK Length: 3,038 [application/x-tar] 100%[====================================>] 3,038 --.--K/s 12:05:09 (28.97 MB/s) - `casetupsample_20040115.tar.gz' saved [3038/3038] 0$ gzip -dc casetupsample_20040115.tar.gz | tar xvf - ca_config.rb # CA configuration file drbssl_c.rb # DRb SSL server sample based on drb/sample/drbssl_s.rb drbssl_s.rb # DRb SSL client sample based on drb/sample/drbssl_c.rb gen_cert.rb # generates certificate gen_rsakey.rb # generates RSA keypair init_ca.rb # initializes files for CA ### ## Setup CA # 0$ mkdir ~/demoCA 0$ cd ~/demoCA 0$ cp -p ~/drbssldemo/ca_config.rb . 0$ cat ca_config.rb class CAConfig BASE_DIR = "/home/nakahiro/demoCA" KEYPAIR_FILE = "#{BASE_DIR}/private/cakeypair.pem" CERT_FILE = "#{BASE_DIR}/cacert.pem" SERIAL_FILE = "#{BASE_DIR}/serial" NEW_CERTS_DIR = "#{BASE_DIR}/newcerts" NEW_KEYPAIR_DIR = "#{BASE_DIR}/private/keypair_backup" CRL_DIR = "#{BASE_DIR}/crl" NAME = [['C', 'JP'], ['O', 'JIN.GR.JP'], ['OU', 'RRR']] CA_CERT_DAYS = 5 * 365 CA_RSA_KEY_LENGTH = 2048 CERT_DAYS = 365 CERT_KEY_LENGTH_MIN = 1024 CERT_KEY_LENGTH_MAX = 2048 CDP_LOCATION = nil OCSP_LOCATION = nil CRL_FILE = "#{CRL_DIR}/rrr.crl" CRL_PEM_FILE = "#{CRL_DIR}/rrr.pem" CRL_DAYS = 14 PASSWD_CB = Proc.new { |flag| print "Enter password: " pass = $stdin.gets.chop! # when the flag is true, this passphrase # will be used to perform encryption; otherwise it will # be used to perform decryption. if flag print "Verify password: " pass2 = $stdin.gets.chop! raise "verify failed." if pass != pass2 end pass } end 0$ vi ca_config.rb # Edit for your env. # BASE_DIR is a must. NAME should be changed once # after you succeeded initial setup. 0$ ~/drbssldemo/init_ca.rb Generating CA keypair: ............................................................ Writing keypair. Enter password: 1234 # Set a password for CA's private key. Don't forget # this password. The private key cannot be activated # without this password. You can't do anything without # the private key activated. Verify password: 1234 # Input again. Writing /home/nakahiro/demoCA/cacert.pem. DONE. (Generated certificate for '/C=JP/O=JIN.GR.JP/OU=RRR/CN=CA') 0$ ls # init_ca.rb generates following files. ca_config.rb cacert.pem crl/ newcerts/ private/ serial ### ## Generate SSL server certificate # ## Create private/public keypair 0$ mkdir ~/demoserver 0$ cd ~/demoserver 0$ ~/drbssldemo/gen_rsakey.rb keypair.pem Generating CA keypair: ..................................................... Writing keypair. Enter password: 5678 # Set a password for SSL server's private key. You # need this password to activate the private key. SSL # server requires private key activated at running. # So you must type this password each time to wake SSL # server up. Verify password: 5678 # Input again. ## Create CSR: Certificate Signing Request 0$ ~/cvs/ruby/HEAD/sample/openssl/gen_csr.rb --key keypair.pem /C=JP/O=JIN.GR.JP/OU=RRR/OU=CA/CN=localhost # Creates "localhost" server certificate. # You can specify hostname here. # gen_csr.rb is included in ruby package. Enter PEM pass phrase: 5678 # To create CSR, you must use private key to # show your identity. So you need to type the # password here. Generating CSR for [["C", "JP"], ["O", "JIN.GR.JP"], ["OU", "RRR"], ["OU", "CA"], ["CN", "localhost"]] Writing csr.pem... ## Send CSR to CA 0$ cp -p csr.pem ~/demoCA/csr_localhost.pem ## CA creates a certificate from CSR 0$ cd ~/demoCA 0$ ~/drbssldemo/gen_cert.rb --type server --out cert_localhost.pem csr_localhost.pem Reading CA cert (from /home/nakahiro/demoCA/cacert.pem) Reading CA keypair (from /home/nakahiro/demoCA/private/cakeypair.pem) Enter password: 1234 # To create certificate, you need to type the password # of CA. Writing cert.pem... DONE. (Generated certificate for '/C=JP/O=JIN.GR.JP/OU=RRR/OU=CA/CN=localhost') ## Send back the certificate to SSL server 0$ mv cert_localhost.pem ~/demoserver 0$ cp -p cacert.pem ~/demoserver ### ## Genertes SSL client certificate # 0$ mkdir ~/democlient 0$ cd ~/democlient ## At the SSL server certificate section, I generated a keypair then pass it to ## gen_csr.rb with --key option. gen_csr.rb can do it at once as below. But ## bear in mind that the private key which gen_csr.rb generates is not ## protected by a password so anyone who get the keypair.pem file can use the ## private key without any protect. 0$ ~/cvs/ruby/HEAD/sample/openssl/gen_csr.rb /C=JP/O=JIN.GR.JP/OU=RRR/OU=CA/CN=NaHi/emailAddress=nahi / keynauts.com [["C", "JP"], ["O", "JIN.GR.JP"], ["OU", "RRR"], ["OU", "CA"], ["CN", "NaHi"], ["emailAddress", "nahi / keynauts.com"]] ........................................................... Writing keypair.pem... Generating CSR for [["C", "JP"], ["O", "JIN.GR.JP"], ["OU", "RRR"], ["OU", "CA"], ["CN", "NaHi"], ["emailAddress", "nahi / keynauts.com"]] Writing csr.pem... 0$ ls csr.pem keypair.pem 0$ cp -p csr.pem ~/demoCA/csr_nahi.pem 0$ cd ~/demoCA 0$ ~/drbssldemo/gen_cert.rb --type client --out cert_nahi.pem csr_nahi.pem Reading CA cert (from /home/nakahiro/demoCA/cacert.pem) Reading CA keypair (from /home/nakahiro/demoCA/private/cakeypair.pem) Enter password: 1234 Writing cert.pem... DONE. (Generated certificate for '/C=JP/O=JIN.GR.JP/OU=RRR/OU=CA/CN=NaHi/emailAddress=nahi / keynauts.com') 0$ mv cert_nahi.pem ~/democlient 0$ cp -p cacert.pem ~/democlient ### ## Run DRb SSL server # 0$ cd ~/demoserver 0$ cp -p ~/drbssldemo/drbssl_s.rb . 0$ cat drbssl_s.rb #!/usr/bin/env ruby require 'drb' require 'drb/ssl' here = ARGV.shift || "drbssl://localhost:3456" class HelloWorld include DRbUndumped def hello(name) "Hello, #{name}." end end config = Hash.new config[:verbose] = true config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read("keypair.pem")) config[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.read("cert_localhost.pem")) DRb.start_service(here, HelloWorld.new, config) puts DRb.uri $stdin.gets DRb.stop_service 0$ ruby drbssl_s.rb Enter PEM pass phrase: drbssl://localhost:3456 ### ## Run DRb SSL client (on another terminal) # 0$ cd ~/democlient 0$ cp -p ~/drbssldemo/drbssl_c.rb . 0$ cat drbssl_c.rb #!/usr/bin/env ruby require 'drb' require 'drb/ssl' there = ARGV.shift || "drbssl://localhost:3456" config = Hash.new config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER config[:SSLCACertificateFile] = "cacert.pem" # config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read("keypair.pem")) # config[:SSLCertificate] = # OpenSSL::X509::Certificate.new(File.read("cert_nahi.pem")) config[:SSLVerifyCallback] = lambda { |ok, store| p [ok, store.error_string] ok } DRb.start_service(nil,nil,config) h = DRbObject.new(nil, there) while line = gets p h.hello(line.chomp) end 0$ ruby drbssl_c.rb # Type something here and see the result. Above example does not use SSL client certificate for authentication. Here is the DRb SSL server which requires client certificate to connect. Try to connect with drbssl_c.rb. ==== #!/usr/bin/env ruby require 'drb' require 'drb/ssl' here = ARGV.shift || "drbssl://localhost:3456" class HelloWorld include DRbUndumped def hello(name) "Hello, #{name}." end end config = Hash.new config[:verbose] = true config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT config[:SSLCACertificateFile] = "cacert.pem" config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read("keypair.pem")) config[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.read("cert_localhost.pem")) config[:SSLVerifyCallback] = lambda { |ok, store| p [ok, store.error_string] ok } DRb.start_service(here, HelloWorld.new, config) puts DRb.uri $stdin.gets DRb.stop_service ==== You'll know if you try, current DRb SSL server implementation hangs when SSLError raises. It's not good maybe. I'll talk to the author. Regards, // NaHi