Certificate verify failed

Am using a X509 PEM certificate with the key for integrating a payment
gateway api.
But am not able to establish the SSL connection as the certificate
verification fails…

http.use_ssl = true
#certificate file
http.cert = OpenSSL::X509::Certificate.new(File.read(‘sdk-cert.pem’))
#private key for that certificate
http.key = OpenSSL::PKey::RSA.new(File.read(‘sdk-key.pem’))
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.start{http.request_get(uri.path){|res| print res.body }}

Error: (via Web)
OpenSSL::SSL::SSLError in TestController#test

certificate verify failed

I get the following error while i verified through command-line using
OpenSSL:

openssl verify sdk-cert.pem
“error 20 at 0 depth lookup:unable to get local issuer certificate”

Is there anything missing in the certificate ?? kindly help to sort out
the issue…

Charles R. wrote:

Am using a X509 PEM certificate with the key for integrating a payment
gateway api.
But am not able to establish the SSL connection as the certificate
verification fails…

It looks like there are two certificate verifications going on:

  • the server verifying your client certificate
  • the ruby client verifying the server’s certificate

and possibly it’s the second which is failing. Is the server’s
certificate signed by a standard CA, or your own CA, or self-signed?

Try the following on the command line:

openssl s_client -connect server.host.name:443

What does the verify result show? If it’s not 0 (OK) then an error will
be shown. What is it?

If the server.host.name certificate is signed by your own CA, then try

openssl s_client -CAfile /path/to/cacert.pem -connect 

server.host.name:443

where cacert.pem is your CA’s root certificate.

If that verifies, then use http.ca_file = … to do the same in the
Ruby client. You can see this documented in
/usr/lib/ruby/1.8/net/https.rb (or wherever it is on your system)

Or, you could install your CA’s cert into openssl’s global certificate
directory. How to do this varies from system to system, and may involve
you using the c_rehash script.

HTH,

Brian.

Charles R. wrote:

I get the following error while i verified through command-line using
OpenSSL:

openssl verify sdk-cert.pem
“error 20 at 0 depth lookup:unable to get local issuer certificate”

Ah, you did step 1 already. Retry using:

openssl s_client -CApath /path/to/cacert.pem -connect foo.bar:443

where cacert.pem is the issuer certificate (i.e. the certificate of the
CA which signed your server’s certificate)

If the certificate is self-signed, you could try using a copy of the
server’s certificate here.

Charles R. wrote:

Thanx Brian for your points…

  1. I checked whether the certificate is signed using the following cmd:

openssl x509 -text -in sdk-cert.pem

You need to look at the certificate of the other side that you are
connecting to (openssl s_client -connect whatever.com:443)

  1. Here am not sure whether the certificate is signed or not…
    – Also i tried the following cmd as you mentioned:

openssl s_client -connect www.paypal.com:443
Loading ‘screen’ into random state - done
CONNECTED(00000764)
depth=2 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=© 2006
VeriSign, I
nc. - For authorized use only/CN=VeriSign Class 3 Public Primary
Certification A
uthority - G5
verify error:num=20:unable to get local issuer certificate

OK that’s good. So this means:

(1) you’re trying to connect to www.paypal.com

(2) www.paypal.com presents a certificate signed by VeriSign

(3) openssl doesn’t have a copy of VeriSign’s root certificate, so
cannot verify PayPal’s certificate.

You need a copy of Verisign’s certificate stored on your machine.
Normally your machine would come with it pre-installed.

What platform are you running this under? For example, Ubuntu has a
package called “ca-certificates”, which installs links in
/etc/ssl/certs. You can make a fully verified SSL connection like this:

openssl s_client -CApath /etc/ssl/certs -connect www.paypal.com:443

Verify return code: 0 (ok)

Once you’ve got that working, then you can do the equivalent in Ruby,
e.g. using http.ca_path = “/etc/ssl/certs”

NB: The PEM certificate file has both the private key & the certificate.

That’s your private key and certificate, which you’re presenting to
Paypal to prove your identity.

The problem is in the other direction, with Paypal presenting their
certificate to you to prove their identity. (Which of course they have
to do: you wouldn’t want someone impersonating Paypal to intercept the
connection and collect all these credit card details you’re sending
them!)

Regards,

Brian.

Again thanx a ton Brian…

Still i’ve few more doubts…

  1. Am working with Windows XP SP3

using Ruby1.8.6

  1. I did the following cmd to find the client side certificate location
    folder

openssl version -d
OPENSSLDIR: “C:/lan/ssl”
– But I didn’t find the above path in my system! is there anyother way
to find it ?

  1. I tried the following cmd in my Linux(i686 athlon i386 GNU/Linux)
    machine

openssl s_client -CApath /usr/share/ssl -connect www.paypal.com:443
– I got a “Verify return code: 0 (ok)” for the above cmd

  1. From your previous detailed explanation i very well understood my
    issue and the ssl verification flow. So if i’ve the server’s certificate
    in my app’s root(in case of RoR app, in Win XP), i’d be able to
    successfully connect to paypal…?? Or is it enough to supply the openssl
    certificates path of windows somewhere in the code…??

So far I was doubting the issue with the PEM certifcate which now am clear that it’s only for my identification… thanx a ton for your patience in explaining me.

Guess your next reply would resolve my issue… kindly help me out…

Charles R. wrote:

  1. I did the following cmd to find the client side certificate location
    folder

openssl version -d
OPENSSLDIR: “C:/lan/ssl”
– But I didn’t find the above path in my system! is there anyother way
to find it ?

dir /s perhaps?

Is it cygwin, or some native Win32 openssl? Maybe it even could be
configured to use the Windows cert store, I have no idea.

  1. I tried the following cmd in my Linux(i686 athlon i386 GNU/Linux)
    machine

openssl s_client -CApath /usr/share/ssl -connect www.paypal.com:443
– I got a “Verify return code: 0 (ok)” for the above cmd

So your app should work on Linux with

http.ca_path = “/usr/share/ssl”

  1. From your previous detailed explanation i very well understood my
    issue and the ssl verification flow. So if i’ve the server’s certificate
    in my app’s root(in case of RoR app, in Win XP), i’d be able to
    successfully connect to paypal…?? Or is it enough to supply the openssl
    certificates path of windows somewhere in the code…??

You need to supply the collection of known trusted root CA certificates
(which includes Verisign’s certificate).

At worst, you could copy verisign’s cert, or the whole CA bundle, from
Ubuntu to XP. I expect there’s a cleaner Windowsy way, but as I hate
Windows and don’t use it, I’m afraid I can’t help you there.

Regards,

Brian.

Thanx Brian for your points…

  1. I checked whether the certificate is signed using the following cmd:

openssl x509 -text -in sdk-cert.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3389 (0xd3d)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US…
Validity
Not Before: Feb 23 16:28:12 2005 GMT
Not After : Feb 21 16:28:12 2015 GMT
Subject: CN=sdk-cert_api1.sdk.com…
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:a8:f8:c7:5d:e3:

Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Signature Algorithm: sha1WithRSAEncryption
09:31:0e:a5:c9:d8:69:0e:49:bd:99:46:49:75:a0:04:9e:19:

-----BEGIN CERTIFICATE-----
MIIClDCCAf2gAwIBAgICDT0wDQYJ…

-----END CERTIFICATE-----

  1. Here am not sure whether the certificate is signed or not…
    – Also i tried the following cmd as you mentioned:

openssl s_client -connect www.paypal.com:443
Loading ‘screen’ into random state - done
CONNECTED(00000764)
depth=2 /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=© 2006
VeriSign, I
nc. - For authorized use only/CN=VeriSign Class 3 Public Primary
Certification A
uthority - G5
verify error:num=20:unable to get local issuer certificate
verify return:0


Certificate chain
0
s:/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/2.5.4.15=V1.

Server certificate
-----BEGIN CERTIFICATE-----
MIIFxzCCBK+gAwIBAgIQa1UJlCEr…

-----END CERTIFICATE-----
subject=/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/2.5.4.15=

No client certificate CA names sent

SSL handshake has read 4404 bytes and written 314 bytes

New, TLSv1/SSLv3, Cipher is DES-CBC3-SHA
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DES-CBC3-SHA
Session-ID:
9BCA761FFA3C4DF596207BAEAA01328583E40418AFCC2273851B209B7D61850B

Session-ID-ctx:
Master-Key: 

D0DA9C2D6649033D39A7E248B53CC2D90FEFCC6F64E73794A8AF8D0095426899
04FA4B4FEBB3498AE2098E33FEA6C84E
Key-Arg : None
Start Time: 1283333209
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)

read:errno=10054

–> Again am getting the same issue at last…

Still am not sure whether the way am using the certificates while
connecting the server is correct or not?

NB: The PEM certificate file has both the private key & the certificate.
The Key file has only the private key that is specified in the
certificate
- file.
If there’s no CA (as mentioned in the above logs), is there any
workaround
- to solve the same ?

Am totally blocked with this stuff… Kindly enlighten me in resolving
this issue…

~ Charles

Thanx a lot Brian for all your help…

As you said, i’ll try the same in Linux machine itself…

thanx & regards,
~ Charles S.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs