Client certificates with https

I've used client-side digital certificates to communicate with web servers
via Ruby. Here's some sample code in case it helps in your situation:

require 'net/https'

host = 'www.example.com'
port = 443
request_file = 'request.xml'
response_file = 'response.xml'
cert_file = 'cert.pem'
cert_pass = 'tHe*PassWORd'

request = File.read(request_file)

https = Net::HTTP.new(host,port)
https.use_ssl = true
https.cert = OpenSSL::X509::Certificate.new(File.read(cert_file))
https.key = OpenSSL::PKey::RSA.new(File.read(cert_file), cert_pass)
https.verify_mode = OpenSSL::SSL::VERIFY_NONE

response = https.post(path, request)

output = File.new(response_file, 'w')
output.puts response.body

···

-----Original Message-----
From: orangekay [mailto:84cdz4d02@sneakemail.com]
Sent: Friday, September 30, 2005 6:52 AM
To: ruby-talk@ruby-lang.org
Subject: Re: Client certificates with https

I'm pathetically replying to my own post with the solution I have come up
with since there is absolutely no example code for getting Ruby to talk to
the Linkpoint gateway out there. Hopefully it will get indexed and help
someone else who finds themselves in a similar position someday.

This example posts a phony order to the testing server. In order to talk to
the real server, you'll simply need to change the host to
"secure.linkpoint.net" in the URL.

You'll need to supply your store number in the "configfile" element of the
XML, and you'll need to provide a valid path to your own PEM file to
File.read. Once those things are done, you should get a response and be
ready to take it from there.

---------------------------------

#!/usr/bin/ruby

require 'net/https'
require 'uri'
require 'rexml/document'

xml_string = <<-END_XML
<order>

  <orderoptions>

    <result>GOOD</result>

    <ordertype>SALE</ordertype>

  </orderoptions>

  <merchantinfo>

    <configfile>PUT YOUR STORE NUMBER HERE!!!!!!!!!</configfile>

  </merchantinfo>

  <creditcard>

    <cardnumber>4111111111111111</cardnumber>

    <cardexpmonth>12</cardexpmonth>

    <cardexpyear>08</cardexpyear>

  </creditcard>

  <payment>

    <chargetotal>1.03</chargetotal>

  </payment>

</order>
END_XML

#Parse the URL to the Linkpoint gateway script.
uri = URI.parse('https://staging.linkpt.net:1129/LSGSXML')

#Read the PEM file into a string. You'll need to supply your own path to
your own PEM file here obviously pem_file =
File.read('/home/yourdomain/storenumber.pem')

#Create a new HTTP connection and configure it for SSL #with a client-side
certificate which we build from the #PEM file's data.
connection = Net::HTTP.new(uri.host, uri.port) connection.use_ssl = true
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE connection.cert =
OpenSSL::X509::Certificate.new(pem_file)
connection.key = OpenSSL::PKey::RSA.new(pem_file)

#Send the XML as POST data after ridding it of excess whitespace.
raw_response = connection.post(uri.path, xml_string.gsub!(/\s/, ''))

#Parse the (invalid!) XML response into an array of values for ease of
processing.
#REXML will complain about the multiple root elements unless we wrap what
#Linkpoint sends us up in another set of tags.
response_doc_root =
REXML::Document.new("<doc>#{raw_response.body}</doc>").root

#Build a hash containing the key/value pairs from the response.
response_values = Hash.new

response_doc_root.each_element() {|element|
response_values["#{element.name}"] = element.text if element.text != nil }

#Process those values however you like. This just prints them out.
response_values.each() {|key, val| puts "#{key} => #{val}\n" }

-----------------------------------

"MMS <firstam.com>" made the following
annotations on 09/30/2005 10:43:57 AM
------------------------------------------------------------------------------
"THIS E-MAIL MESSAGE AND ANY FILES TRANSMITTED HEREWITH, ARE INTENDED SOLELY FOR THE USE OF THE INDIVIDUAL(S) ADDRESSED AND MAY CONTAIN CONFIDENTIAL, PROPRIETARY OR PRIVILEGED INFORMATION. IF YOU ARE NOT THE ADDRESSEE INDICATED IN THIS MESSAGE (OR RESPONSIBLE FOR DELIVERY OF THIS MESSAGE TO SUCH PERSON) YOU MAY NOT REVIEW, USE, DISCLOSE OR DISTRIBUTE THIS MESSAGE OR ANY FILES TRANSMITTED HEREWITH. IF YOU RECEIVE THIS MESSAGE IN ERROR, PLEASE CONTACT THE SENDER BY REPLY E-MAIL AND DELETE THIS MESSAGE AND ALL COPIES OF IT FROM YOUR SYSTEM."