SSL certificate verify failure every other time - ruby

The following code gives an error on heroku, but only every other time.
host = "api.pagepeeker.com"
cert = "/usr/lib/ssl/certs/ca-certificates.crt"
(0..19).map do |i|
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_context.set_params(ca_file: cert, verify_mode: 1)
s = OpenSSL::SSL::SSLSocket.new(TCPSocket.open(host, 443, nil, nil), ssl_context)
s.sync_close = true
s.hostname = host
begin
s.connect
rescue
"error"
else
"ok"
ensure
s.close
end
end.join(' ')
#=> ok error ok error ok error ok error ok error
The error is: OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
This corresponds to Net::HTTP.get(URI.parse("https://api.pagepeeker.com"))
I am stumped by the alternating failures and successes. Upgrading OpenSSL from 0.9.8k to 1.0.1e did not help.

Sorry about the second answer. The first was too long to tack on, and this is a different finding.
It appears part of the problem is pagepeeker.com is not sending all the certificates required to validate the chain. That is, its not sending required intermediate certificates.
If pagepeeker.com does not send all the required certificates, then the client encounters the "which directory" problem. Its well known in PKI, and it means a client has no idea which X500 directory it should query to find the missing intermediate certificates.
Now, back to your problem: you might be seeing an intermittent problem because there could be one misconfigured server in a load balanced environment. Part of the solution to your problem may be the pagekeeper.com server sending all required certificates.
Here's the certificates sent by pagekeeper.com:
$ echo "GET / HTTP\1.1" | openssl s_client -connect api.pagepeeker.com:443 -showcerts
CONNECTED(00000003)
depth=0 description = 8CTO6gSuxeRRsIXl, C = RO, CN = api.pagepeeker.com, emailAddress = alexandru.florescu#gmail.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 description = 8CTO6gSuxeRRsIXl, C = RO, CN = api.pagepeeker.com, emailAddress = alexandru.florescu#gmail.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 description = 8CTO6gSuxeRRsIXl, C = RO, CN = api.pagepeeker.com, emailAddress = alexandru.florescu#gmail.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/description=8CTO6gSuxeRRsIXl/C=RO/CN=api.pagepeeker.com/emailAddress=alexandru.florescu#gmail.com
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
-----BEGIN CERTIFICATE-----
MIIGZTCCBU2gAwIBAgIDCJkoMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwMTAzMDA0OTAx
WhcNMTQwMTA0MTIxOTIwWjByMRkwFwYDVQQNExA4Q1RPNmdTdXhlUlJzSVhsMQsw
CQYDVQQGEwJSTzEbMBkGA1UEAxMSYXBpLnBhZ2VwZWVrZXIuY29tMSswKQYJKoZI
hvcNAQkBFhxhbGV4YW5kcnUuZmxvcmVzY3VAZ21haWwuY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2o4+19SXbidxdD02hFaBytgqz97/8Newj1lz
wOILWsTbc26/pTkDzN7IHphpPR8tJp3lH7OqV3cTshonu9ouTxxoqBAcVN+6ClSM
fH4IHFLmywcab6Rb7nhUUcFgwEWUfHbCH41fV+Yx7+tFpmzChwDMvp5m1cIVZWEb
kSk9tSTnOXT2PIAaFmVhqRJ9gFkOxrl5jNmVyo0RH3xdJ7M/pE8mK/oLcOXA9Oev
4p6d37OwbftoBOclmenDWo1fz7kgF3+BQCs5IAHQ1rnhI4v8+MelQpzUWUrxdvjX
z64KftQ9spVYl0XAMshHjncXenIO+owPGJ9NbTcE6W4GKYtCvwIDAQABo4IC5zCC
AuMwCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEw
HQYDVR0OBBYEFLU812MJONAqhRD11CpkAX0ZofLEMB8GA1UdIwQYMBaAFOtCNNCY
sKuf9BtrCPfMZC7vDixFMC0GA1UdEQQmMCSCEmFwaS5wYWdlcGVla2VyLmNvbYIO
cGFnZXBlZWtlci5jb20wggFWBgNVHSAEggFNMIIBSTAIBgZngQwBAgEwggE7Bgsr
BgEEAYG1NwECAzCCASowLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wu
Y29tL3BvbGljeS5wZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBp
c3N1ZWQgYWNjb3JkaW5nIHRvIHRoZSBDbGFzcyAxIFZhbGlkYXRpb24gcmVxdWly
ZW1lbnRzIG9mIHRoZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkg
Zm9yIHRoZSBpbnRlbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJl
bHlpbmcgcGFydHkgb2JsaWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6
Ly9jcmwuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEw
fzA5BggrBgEFBQcwAYYtaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFz
czEvc2VydmVyL2NhMEIGCCsGAQUFBzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNv
bS9jZXJ0cy9zdWIuY2xhc3MxLnNlcnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0
cDovL3d3dy5zdGFydHNzbC5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQAxdu/aWSFN
iY1TkIxvA6w5XZPS93hIRoNOfs4xUkA7LGNAEnCt0WWe33lkyC9tHBbL3Li8pJib
bQZkgK7yX79KgwUlzHaAIlXcL4WYAhLroGbjvkzv5ldmt1hTcOCtFMVhPbBEGomB
U1XBQPaoba+D2ve7ZbUJihdMUSyIps8540fHC4G4CVpLxelc34OjdknyLTIsUpIF
ey2x9eazXnCKwjC5BgrEDIyE0ew8v5Xf/Gov4718ozc60CWLv4SNQzwMgrjNElEa
vOjjDljCFJ6xjJag00uf1xJjQ1C4g2mT6oQcZCMP4x6VlEXen9xZfI5RAfTw9ElL
5FJ1IIaJc7+5
-----END CERTIFICATE-----
---
Server certificate
subject=/description=8CTO6gSuxeRRsIXl/C=RO/CN=api.pagepeeker.com/emailAddress=alexandru.florescu#gmail.com
issuer=/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
---
No client certificate CA names sent
---
SSL handshake has read 1957 bytes and written 648 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES256-SHA
Session-ID: 92E4B4B744DDFE63EBD2EDC8D0D6065FF9D05589FD10A05E0C971F6CE0B2526D
Session-ID-ctx:
Master-Key: CE01E4B9BFB3D0F3B95F81004013320DE44BFBE399AB84ABA047C0064DBDABC200CE5472F74EA5881BF99F66A58729F7
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket:
0000 - 63 03 ce 7b 9b 75 3b 4d-7f 1c dd f0 6d 56 1c 32 c..{.u;M....mV.2
0010 - c2 af 84 b2 1c c8 aa 18-6c 90 54 68 46 96 8f 5d ........l.ThF..]
0020 - 26 11 e7 37 89 e4 a4 29-ff 26 04 20 c8 08 f4 8a &..7...).&. ....
0030 - de cf 38 b1 57 83 ae 45-41 51 48 c1 7c b9 df 0f ..8.W..EAQH.|...
0040 - 6a e1 c7 75 93 b4 24 5c-5f 63 97 ce 2d b7 12 eb j..u..$\_c..-...
0050 - 05 a8 57 d3 4d af 31 5d-18 b3 f8 8e 02 70 6f 2f ..W.M.1].....po/
0060 - fe 33 18 c6 7d 83 58 76-37 5f 59 9a ed e5 28 ae .3..}.Xv7_Y...(.
0070 - d5 5a 9f a4 46 13 55 f3-14 aa 47 f5 b6 63 e8 76 .Z..F.U...G..c.v
0080 - 82 bf 2c f9 35 9a 01 fc-3d e9 2e 8f 1f ca a5 67 ..,.5...=......g
0090 - 3b 55 6f f4 4d c1 fa 79-40 20 6d 82 f7 49 58 7a ;Uo.M..y# m..IXz
Start Time: 1380751071
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
DONE
If you look at something from, for example Google, you will see the entire chain is sent:
$ echo "GET / HTTP\1.1" | openssl s_client -connect encrypted.google.com:443 -showcerts
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
i:/C=US/O=Google Inc/CN=Google Internet Authority G2
-----BEGIN CERTIFICATE-----
MIIHIDCCBgigAwIBAgIIKTc2rLt+oBEwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTMwOTExMTA1MDIxWhcNMTQwOTExMTA1MDIx
WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEVMBMGA1UEAwwMKi5n
b29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq02vkZCV
ERg2AdnOE9/NLiCNJ/0oxe+7O7eAv3Oc2xTKCaT/fXrGjMnYP+g5povMi2peIPXY
eUCnONd3KGj1f4SaLPIzoIfErwsYEMq5GBWSEqXXvPSKbv/NIU6NT/FFd5GvQY3P
KtB4+DCLXWzLUBExqGYcw+F7bfut5l/RV/uFazi8nlROgXB59LRCjbo6fiI7+kjh
+CBteUXJuGd0gRYm08KVnLOM3qi0RzjYStqLxDTAbMgAVWFN5hKcNt0R0hYBGMMO
vyHIDXXAWVlgzKMHyrpvjSwcts4nML6xO7bKzKLZZbfQ5HRRlyj6eGI+aNopNl1b
Mbw3Qul5WA5s6wIDAQABo4ID7TCCA+kwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMIICwwYDVR0RBIICujCCAraCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lk
LmNvbYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYISKi5jbG91ZC5nb29nbGUuY29t
ghYqLmdvb2dsZS1hbmFseXRpY3MuY29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUu
Y2yCDiouZ29vZ2xlLmNvLmlugg4qLmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28u
dWuCDyouZ29vZ2xlLmNvbS5hcoIPKi5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5j
b20uYnKCDyouZ29vZ2xlLmNvbS5jb4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2ds
ZS5jb20udHKCDyouZ29vZ2xlLmNvbS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xl
LmVzggsqLmdvb2dsZS5mcoILKi5nb29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdv
b2dsZS5ubIILKi5nb29nbGUucGyCCyouZ29vZ2xlLnB0gg8qLmdvb2dsZWFwaXMu
Y26CFCouZ29vZ2xlY29tbWVyY2UuY29tgg0qLmdzdGF0aWMuY29tggwqLnVyY2hp
bi5jb22CECoudXJsLmdvb2dsZS5jb22CFioueW91dHViZS1ub2Nvb2tpZS5jb22C
DSoueW91dHViZS5jb22CFioueW91dHViZWVkdWNhdGlvbi5jb22CCyoueXRpbWcu
Y29tggthbmRyb2lkLmNvbYIEZy5jb4IGZ29vLmdsghRnb29nbGUtYW5hbHl0aWNz
LmNvbYIKZ29vZ2xlLmNvbYISZ29vZ2xlY29tbWVyY2UuY29tggp1cmNoaW4uY29t
ggh5b3V0dS5iZYILeW91dHViZS5jb22CFHlvdXR1YmVlZHVjYXRpb24uY29tMGgG
CCsGAQUFBwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5nb29nbGUuY29t
L0dJQUcyLmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMxLmdvb2dsZS5j
b20vb2NzcDAdBgNVHQ4EFgQUWdyXs0sRMgoX3k/dpzVLlcMD+l8wDAYDVR0TAQH/
BAIwADAfBgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAXBgNVHSAEEDAO
MAwGCisGAQQB1nkCBQEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5nb29n
bGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAHuO6zcxRTMJl60MP
jreD1J+5+nWy6IcpWlaAaLFclcVtz+FMNAi727OR3oX4JjlTbHNWZ94MCzPObxZN
8+OBrfWQ6GYIwgeTBoRH9Q4zp5HvxtsWGOkbJSU4DTXKm/oVXoOdb8O+3xLJKRBF
C3aH6tK31KR+strGrpX3nyGm8aFaLcFp9ChiWaBTKcCLF+hJAoAJ0+4LZAlZQODd
LhWbVVLPMKr0IDpaP/ElX9n3gVmYdExvtcYVdcgSEVf3axx44A4dXXTt3KBnrzAd
MvFpqRxHCU86WGw5cNq9pi62hh4D8sZAZf0vMshiOKCLtxeQa3IByJy23Kb0CDcQ
6R8Zww==
-----END CERTIFICATE-----
1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
-----BEGIN CERTIFICATE-----
MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG
EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy
bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP
VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv
h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE
ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ
EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC
DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7
qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD
VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g
K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI
KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n
ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB
BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY
/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/
zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza
HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto
WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6
yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx
-----END CERTIFICATE-----
2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
-----BEGIN CERTIFICATE-----
MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDIwNTIxMDQwMDAwWhcNMTgwODIxMDQwMDAw
WjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UE
AxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9m
OSm9BXiLnTjoBbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIu
T8rxh0PBFpVXLVDviS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6c
JmTM386DGXHKTubU1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmR
Cw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5asz
PeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo4HwMIHtMB8GA1UdIwQYMBaAFEjm
aPkr0rKV10fYIyAQTzOYkJ/UMB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrM
TjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjA6BgNVHR8EMzAxMC+g
LaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDBO
BgNVHSAERzBFMEMGBFUdIAAwOzA5BggrBgEFBQcCARYtaHR0cHM6Ly93d3cuZ2Vv
dHJ1c3QuY29tL3Jlc291cmNlcy9yZXBvc2l0b3J5MA0GCSqGSIb3DQEBBQUAA4GB
AHbhEm5OSxYShjAGsoEIz/AIx8dxfmbuwu3UOx//8PDITtZDOLC5MH0Y0FWDomrL
NhGc6Ehmo21/uBPUR/6LWlxz/K7ZGzIZOKuXNBSqltLroxwUCEm2u+WR74M26x1W
b8ravHNjkOR/ez4iyz0H7V84dJzjA1BOoa+Y7mHyhD8S
-----END CERTIFICATE-----
---
Server certificate
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
---
SSL handshake has read 4410 bytes and written 448 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: D87198A1294D6B41660C0DA153137348B6F65BBD2E6B7D410104964C21A33682
Session-ID-ctx:
Master-Key: 2967DF01FECCBC2EF444C7723BD3CA105C522BFC613D568F8D65D3D28F2A8CD6EF031D9B6D3132DE3D8B3364ED061A41
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 100800 (seconds)
TLS session ticket:
0000 - 8b 66 a6 c9 dd b3 2e c8-f6 2e 87 18 3c 90 8b 57 .f..........<..W
0010 - 77 18 39 be 93 40 fe 20-6a 08 1d f3 54 3a f1 22 w.9..#. j...T:."
0020 - d3 eb 51 8c 56 23 bc 87-51 0e 12 6b 23 57 ba 67 ..Q.V#..Q..k#W.g
0030 - f2 5b c2 78 d7 8f 06 99-42 97 7c ce 7f 99 4a 74 .[.x....B.|...Jt
0040 - ef ec 55 f2 77 64 f3 3e-c8 24 e7 45 92 1b 54 ef ..U.wd.>.$.E..T.
0050 - 79 f2 3b 0f 69 35 84 7d-cd 21 0a 45 b6 8a b9 e4 y.;.i5.}.!.E....
0060 - 61 9a 8e 7b c5 e9 26 82-56 27 b4 f3 25 b8 82 5b a..{..&.V'..%..[
0070 - 19 8b ce b9 bf 61 e2 3e-1c 08 16 7e af 91 e9 44 .....a.>...~...D
0080 - f9 53 75 cd 59 e0 80 50-03 09 07 67 e1 2d bf 6d .Su.Y..P...g.-.m
0090 - aa d4 b9 3a ...:
Start Time: 1380750955
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
DONE

They are using a host certificate that does not chain back to a [trusted] root certificate. You should probably be seeing the error more often (every time?).
You might need to call SSL_CTX_load_verify_locations with a file that contains the required StartCom root certificate. You can get the StartCom root from http://www.startssl.com/?app=26. You want the one that includes "StartCom Certification Authority", which I believe is in the bundle http://www.startssl.com/certs/ca-bundle.pem. There's a few in that file, but OpenSSL handles the concatenation fine as long as you are willing to accept the risk of the additional roots.
$ echo "GET / HTTP\1.1" | openssl s_client -connect api.pagepeeker.com:443
CONNECTED(00000003)
depth=2 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN = StartCom Certification Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
0 s:/description=8CTO6gSuxeRRsIXl/C=RO/CN=api.pagepeeker.com/emailAddress=alexandru.florescu#gmail.com
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
1 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
2 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGZTCCBU2gAwIBAgIDCJkoMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwMTAzMDA0OTAx
WhcNMTQwMTA0MTIxOTIwWjByMRkwFwYDVQQNExA4Q1RPNmdTdXhlUlJzSVhsMQsw
CQYDVQQGEwJSTzEbMBkGA1UEAxMSYXBpLnBhZ2VwZWVrZXIuY29tMSswKQYJKoZI
hvcNAQkBFhxhbGV4YW5kcnUuZmxvcmVzY3VAZ21haWwuY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2o4+19SXbidxdD02hFaBytgqz97/8Newj1lz
wOILWsTbc26/pTkDzN7IHphpPR8tJp3lH7OqV3cTshonu9ouTxxoqBAcVN+6ClSM
fH4IHFLmywcab6Rb7nhUUcFgwEWUfHbCH41fV+Yx7+tFpmzChwDMvp5m1cIVZWEb
kSk9tSTnOXT2PIAaFmVhqRJ9gFkOxrl5jNmVyo0RH3xdJ7M/pE8mK/oLcOXA9Oev
4p6d37OwbftoBOclmenDWo1fz7kgF3+BQCs5IAHQ1rnhI4v8+MelQpzUWUrxdvjX
z64KftQ9spVYl0XAMshHjncXenIO+owPGJ9NbTcE6W4GKYtCvwIDAQABo4IC5zCC
AuMwCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEw
HQYDVR0OBBYEFLU812MJONAqhRD11CpkAX0ZofLEMB8GA1UdIwQYMBaAFOtCNNCY
sKuf9BtrCPfMZC7vDixFMC0GA1UdEQQmMCSCEmFwaS5wYWdlcGVla2VyLmNvbYIO
cGFnZXBlZWtlci5jb20wggFWBgNVHSAEggFNMIIBSTAIBgZngQwBAgEwggE7Bgsr
BgEEAYG1NwECAzCCASowLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wu
Y29tL3BvbGljeS5wZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBp
c3N1ZWQgYWNjb3JkaW5nIHRvIHRoZSBDbGFzcyAxIFZhbGlkYXRpb24gcmVxdWly
ZW1lbnRzIG9mIHRoZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkg
Zm9yIHRoZSBpbnRlbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJl
bHlpbmcgcGFydHkgb2JsaWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6
Ly9jcmwuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEw
fzA5BggrBgEFBQcwAYYtaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFz
czEvc2VydmVyL2NhMEIGCCsGAQUFBzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNv
bS9jZXJ0cy9zdWIuY2xhc3MxLnNlcnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0
cDovL3d3dy5zdGFydHNzbC5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQAxdu/aWSFN
iY1TkIxvA6w5XZPS93hIRoNOfs4xUkA7LGNAEnCt0WWe33lkyC9tHBbL3Li8pJib
bQZkgK7yX79KgwUlzHaAIlXcL4WYAhLroGbjvkzv5ldmt1hTcOCtFMVhPbBEGomB
U1XBQPaoba+D2ve7ZbUJihdMUSyIps8540fHC4G4CVpLxelc34OjdknyLTIsUpIF
ey2x9eazXnCKwjC5BgrEDIyE0ew8v5Xf/Gov4718ozc60CWLv4SNQzwMgrjNElEa
vOjjDljCFJ6xjJag00uf1xJjQ1C4g2mT6oQcZCMP4x6VlEXen9xZfI5RAfTw9ElL
5FJ1IIaJc7+5
-----END CERTIFICATE-----
subject=/description=8CTO6gSuxeRRsIXl/C=RO/CN=api.pagepeeker.com/emailAddress=alexandru.florescu#gmail.com
issuer=/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
---
No client certificate CA names sent
---
SSL handshake has read 5552 bytes and written 648 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES256-SHA
Session-ID: D761D5D91D9BD18933CD68A37A9E65CC9CF6D0A0F28A8CB1D07C34C0E7B98253
Session-ID-ctx:
Master-Key: 43E285E1113C70B0767EE4B62B042166D1BFC86B62BAFE0F3338DB2771479EE51C99C19DC6E09E98E44FB79130206B9F
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket:
0000 - c7 19 e2 ed e1 7b a1 84-40 84 3a 0d f0 73 e2 4c .....{..#.:..s.L
0010 - 2b 79 a1 3e 22 24 9a a8-d3 3a 4a 51 8d 6f 54 a5 +y.>"$...:JQ.oT.
0020 - ea 64 e4 68 3c 2b dd f2-e8 80 b8 e0 be 52 c1 ad .d.h<+.......R..
0030 - ae 44 19 76 7d a2 64 19-e1 6d bb c1 8a 80 a0 d9 .D.v}.d..m......
0040 - 42 29 99 99 16 47 34 1e-44 11 10 be 9a 6a 95 6b B)...G4.D....j.k
0050 - 09 55 ef 28 8f 44 8f 04-1d bd aa 79 b8 07 59 5f .U.(.D.....y..Y_
0060 - 1f 4e bd 00 ef e3 31 3d-6e 1f e8 79 6b bb fa 4a .N....1=n..yk..J
0070 - b9 8a cb 3a 4e 7e 8e bb-7a e7 81 b7 1f af d0 50 ...:N~..z......P
0080 - 84 70 99 77 b3 81 1d 0e-7f 04 4e 52 7e 95 fa 05 .p.w......NR~...
0090 - 19 be 78 e8 e6 bb cd 3c-08 49 dd 77 64 92 f7 eb ..x....<.I.wd...
Start Time: 1380706251
Timeout : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)
---
DONE
When I use the Startcom CA bundle and the -CAfile option, I cannot reproduce the failure, even across consecutive runs:
$ echo "GET / HTTP\1.1" | openssl s_client -connect api.pagepeeker.com:443 -CAfile startcom-ca-bundle.pem
CONNECTED(00000003)
depth=2 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN = StartCom Certification Authority
verify return:1
depth=1 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN = StartCom Class 1 Primary Intermediate Server CA
verify return:1
depth=0 description = 8CTO6gSuxeRRsIXl, C = RO, CN = api.pagepeeker.com, emailAddress = alexandru.florescu#gmail.com
verify return:1
---
Certificate chain
0 s:/description=8CTO6gSuxeRRsIXl/C=RO/CN=api.pagepeeker.com/emailAddress=alexandru.florescu#gmail.com
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
1 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
2 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGZTCCBU2gAwIBAgIDCJkoMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwMTAzMDA0OTAx
WhcNMTQwMTA0MTIxOTIwWjByMRkwFwYDVQQNExA4Q1RPNmdTdXhlUlJzSVhsMQsw
CQYDVQQGEwJSTzEbMBkGA1UEAxMSYXBpLnBhZ2VwZWVrZXIuY29tMSswKQYJKoZI
hvcNAQkBFhxhbGV4YW5kcnUuZmxvcmVzY3VAZ21haWwuY29tMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2o4+19SXbidxdD02hFaBytgqz97/8Newj1lz
wOILWsTbc26/pTkDzN7IHphpPR8tJp3lH7OqV3cTshonu9ouTxxoqBAcVN+6ClSM
fH4IHFLmywcab6Rb7nhUUcFgwEWUfHbCH41fV+Yx7+tFpmzChwDMvp5m1cIVZWEb
kSk9tSTnOXT2PIAaFmVhqRJ9gFkOxrl5jNmVyo0RH3xdJ7M/pE8mK/oLcOXA9Oev
4p6d37OwbftoBOclmenDWo1fz7kgF3+BQCs5IAHQ1rnhI4v8+MelQpzUWUrxdvjX
z64KftQ9spVYl0XAMshHjncXenIO+owPGJ9NbTcE6W4GKYtCvwIDAQABo4IC5zCC
AuMwCQYDVR0TBAIwADALBgNVHQ8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEw
HQYDVR0OBBYEFLU812MJONAqhRD11CpkAX0ZofLEMB8GA1UdIwQYMBaAFOtCNNCY
sKuf9BtrCPfMZC7vDixFMC0GA1UdEQQmMCSCEmFwaS5wYWdlcGVla2VyLmNvbYIO
cGFnZXBlZWtlci5jb20wggFWBgNVHSAEggFNMIIBSTAIBgZngQwBAgEwggE7Bgsr
BgEEAYG1NwECAzCCASowLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wu
Y29tL3BvbGljeS5wZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBp
c3N1ZWQgYWNjb3JkaW5nIHRvIHRoZSBDbGFzcyAxIFZhbGlkYXRpb24gcmVxdWly
ZW1lbnRzIG9mIHRoZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkg
Zm9yIHRoZSBpbnRlbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJl
bHlpbmcgcGFydHkgb2JsaWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6
Ly9jcmwuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEw
fzA5BggrBgEFBQcwAYYtaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFz
czEvc2VydmVyL2NhMEIGCCsGAQUFBzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNv
bS9jZXJ0cy9zdWIuY2xhc3MxLnNlcnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0
cDovL3d3dy5zdGFydHNzbC5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQAxdu/aWSFN
iY1TkIxvA6w5XZPS93hIRoNOfs4xUkA7LGNAEnCt0WWe33lkyC9tHBbL3Li8pJib
bQZkgK7yX79KgwUlzHaAIlXcL4WYAhLroGbjvkzv5ldmt1hTcOCtFMVhPbBEGomB
U1XBQPaoba+D2ve7ZbUJihdMUSyIps8540fHC4G4CVpLxelc34OjdknyLTIsUpIF
ey2x9eazXnCKwjC5BgrEDIyE0ew8v5Xf/Gov4718ozc60CWLv4SNQzwMgrjNElEa
vOjjDljCFJ6xjJag00uf1xJjQ1C4g2mT6oQcZCMP4x6VlEXen9xZfI5RAfTw9ElL
5FJ1IIaJc7+5
-----END CERTIFICATE-----
subject=/description=8CTO6gSuxeRRsIXl/C=RO/CN=api.pagepeeker.com/emailAddress=alexandru.florescu#gmail.com
issuer=/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
---
No client certificate CA names sent
---
SSL handshake has read 5552 bytes and written 648 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES256-SHA
Session-ID: 9A0E34E509AA7C2EED12E58D0D80B078B39D4A5A5C981E510D9D190E5F76B911
Session-ID-ctx:
Master-Key: 2F447B622ACBB0006DC121FA43FB562ACE2BDEAF73D3EC887AF7BC22548392AB42E3625530874EA541C569DB7543E273
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket:
0000 - c7 19 e2 ed e1 7b a1 84-40 84 3a 0d f0 73 e2 4c .....{..#.:..s.L
0010 - 46 cf b7 fd 33 95 88 14-fb da 08 4b 0a 58 e0 55 F...3......K.X.U
0020 - 31 ff 2a cf ff fb 65 a3-b4 db 8f 5f 65 6c 72 15 1.*...e...._elr.
0030 - ba ce c3 84 4f 83 9f 01-3d d4 87 f8 a1 eb bb b5 ....O...=.......
0040 - 1b a2 9a de 94 55 86 ad-d7 e7 29 ed f0 98 a4 5f .....U....)...._
0050 - 4d 93 f6 a7 db 15 7f d3-b3 ca 63 2c a9 8d 69 b2 M.........c,..i.
0060 - 77 3e a6 28 76 ba d3 a7-f7 5c 20 88 75 23 71 7d w>.(v....\ .u#q}
0070 - 99 62 b4 fd b9 09 1c ec-90 2d a0 c1 27 d0 23 61 .b.......-..'.#a
0080 - 18 da 47 17 06 3c 29 34-05 3e f3 d2 22 29 09 cc ..G..<)4.>..")..
0090 - d2 41 b7 8d 29 14 c2 88-3b ad 67 2a 88 25 e1 9b .A..)...;.g*.%..
Start Time: 1380708844
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
DONE

This has been a misconfiguration on one of the PagePeeker load balancers. It has been fixed at the time the issue was mentioned.

Related

Letsencrypt DST Root CA X3 Problem with Magento SOAP-Service client or server side?

Since 30.9. - due to DST Root CA X3 SOAP Calls (SOAPUI or PHP SoapCLient) against the system fail. However via webbrowser I can open the https-Website just fine.
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = xyz.de
verify return:1
---
Certificate chain
0 s:/CN=xyz.de
i:/C=US/O=Let's Encrypt/CN=R3
1 s:/C=US/O=Let's Encrypt/CN=R3
i:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
2 s:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFKDCCBBCgAwIBAgISBIGPZIOSvZxPr5l/FlDTq2eoMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMTEwMDgwODM3NTNaFw0yMjAxMDYwODM3NTJaMBUxEzARBgNVBAMT
CnN1Ym9sYWIuZGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDik8F+
acJc9+DtWgj830rwZL2UmkA69FT3myx27HCJSJmJ96itiN7J2GAR2/ykqHZb+4KW
0vxeA2Yp8ZcrSuxlRUITC8eCppsv+FACW+G7gO6/GVL8KIF9AA3VsyHrGEI9OKp+
W+NgIUDJrf38zONF+Of+nq2HYKJ3QJBguJYlAZpa0RD/SkmZ6J+46frQarmRuvao
R6e/DB0aMxojV9/40xUBty4hTDM3N5XQWWB1Y8WtBIpoWJDxRAExESf6pRVPae8X
QlDFq/sK7ZymlXaBB0fDk0qtlQBAUs+5fbm11SlPEuEYr1fqZUDv+OVXq2YN9goR
P9P/9FdccOLm9DH/AgMBAAGjggJTMIICTzAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0l
BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYE
FE5unoQ3VpJf/Fa9z8DzKpnBhXQ6MB8GA1UdIwQYMBaAFBQusxe3WFbLrlAJQOYf
r52LFMLGMFUGCCsGAQUFBwEBBEkwRzAhBggrBgEFBQcwAYYVaHR0cDovL3IzLm8u
bGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRwOi8vcjMuaS5sZW5jci5vcmcvMCUG
A1UdEQQeMByCCnN1Ym9sYWIuZGWCDnd3dy5zdWJvbGFiLmRlMEwGA1UdIARFMEMw
CAYGZ4EMAQIBMDcGCysGAQQBgt8TAQEBMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9j
cHMubGV0c2VuY3J5cHQub3JnMIIBAgYKKwYBBAHWeQIEAgSB8wSB8ADuAHUARqVV
63X6kSAwtaKJafTzfREsQXS+/Um4havy/HD+bUcAAAF8X0QnSgAABAMARjBEAiAv
OVmtIwzbha0CbgncP3gib90XhyZqv2zG009eliEAOAIgKlN5m2D4pyeL7u2kBbo/
Sa3eK4tybwF0s0QzEu6jmzYAdQBvU3asMfAxGdiZAKRRFf93FRwR2QLBACkGjbII
mjfZEwAAAXxfRChkAAAEAwBGMEQCIA+CagvnauTu/l8918bZlzNfR4uBa+FlhGv6
pGywruzmAiAREmyTfzTUoAnxUbdMc+hfzZB9kJCzQa0vgqZnMIl2lzANBgkqhkiG
9w0BAQsFAAOCAQEAAMeb8OLAEG/IVfwdjzlZ/lEdPnv278qFVdotMuVa1Zl9/vwC
lTxs5RBn4MiDbECNnO+s6qDBrohMpp2bzsqZhCjmRQplpYSr+iqGzvrlWAVbxuKU
STWlSh+oThxX9esghT4G8FlkTrPU4V646IDsgbMUOYVxQv8rncvmw82q3h6ccOZz
8qhrUozrUXqqglR6bq49vsp1sOIhCPCuAkHswZvf1+KA72iwIKWayQUosFga9Wph
tIE/NY19D1nOwDIKhNSUA8YAhZAOrLZm4B6ZMJeajcMLFp+D3d3LyJNs2K0VK0Yu
uUbpGd5AthElVilw/X3TxzdIPU5G/AUPJNA9IQ==
-----END CERTIFICATE-----
subject=/CN=xyz.de
issuer=/C=US/O=Let's Encrypt/CN=R3
---
No client certificate CA names sent
Peer signing digest: SHA256
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 4657 bytes and written 292 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: E6AC1CB5A43712F0CDB1FA843B35D31F16195096541920D4A7C5F60E5089797C
Session-ID-ctx:
Master-Key: B621EBF40CB97A41A1DFAEBAD317FA48F01723BE72A25D6BBD6CCA7F91C4968399BCA3E146E20F2D44160F09BC1572E1
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 600 (seconds)
TLS session ticket:
0000 - a3 a3 ce f3 2a c0 9e f7-60 59 91 f6 15 c9 56 79 ....*...`Y....Vy
0010 - 31 f8 d7 d0 cb a4 1b de-7d 1d bf 12 73 4e 5a f1 1.......}...sNZ.
0020 - b9 12 8b ff 1c c1 28 f7-cb d3 d1 f3 0e 4c 75 64 ......(......Lud
0030 - ce 3d c5 28 4e 99 5b e4-37 d4 b4 1b 4e 91 b8 e3 .=.(N.[.7...N...
0040 - 08 68 8f 6b 8a 1e dd f1-a3 79 f1 f6 1d 81 5f e7 .h.k.....y...._.
0050 - 7f 34 78 0a 48 ab 34 aa-f1 41 e1 5b 5c 89 75 b7 .4x.H.4..A.[\.u.
0060 - d2 54 a9 8b 63 ee 66 f3-e7 ee aa df 6b 61 ee 9b .T..c.f.....ka..
0070 - d1 89 28 c6 f1 96 53 d3-29 d0 7f d3 28 5b 52 b1 ..(...S.)...([R.
0080 - 0c fb 37 10 1d 23 a4 d1-6e 4a ff 39 f5 9c f7 a6 ..7..#..nJ.9....
0090 - ad 05 e3 a3 bb 98 04 f3-9d 23 6c ea 10 3f a2 22 .........#l..?."
00a0 - 39 76 0b 16 5b f6 af 0d-1a 2d 10 56 6e 72 d0 f1 9v..[....-.Vnr..
Start Time: 1633688139
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: yes
---
The certificate chain still uses DST Root CA X3 but I dont know if this is ok or not:
2 s:/C=US/O=Internet Security Research Group/CN=ISRG Root X1
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
Error-Message from all Soap-Clients i tried is:
PHP Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://xyz.de/api/v2_soap?wsdl=1' : failed to load external entity "https://xyz.de/api/v2_soap?wsdl=1"
Is the problem on server side, or more like an issue that ISRG Root X1 is not known on client side?
Problem solved, the problem is, that the System (Magento Version 1) is calling itself via Web to get the WSDL, and the System that is hosting Magento was using the outdated DST ROOT CA X3 plus did not know about the ISRG Root X1:
rm /etc/ssl/certs/DST_Root_CA_X3.pem
apt-get install ca-certificates -y
update-ca-certificates -f -v

Debugging SSL connection using openssl terminal command

I have a server app running on my computer listening on a certain port. When I try to use OpenSSL (on Mac, i upgraded via brew already from the default Mac version for OpenSSL).
openssl s_client -connect 0.0.0.0:80051 -showcerts -prexit -servername localhost -debug
Response
CONNECTED(00000003)
write to 0x7fe62b41b370 [0x7fe62b80d000] (118 bytes => 118 (0x76))
0000 - 16 03 01 00 71 01 00 00-6d 03 01 58 d2 84 72 d5 ....q...m..X..r.
0010 - 1b d3 47 9c 8e 6b b3 fb-10 a5 21 af 0e 5d 79 7b ..G..k....!..]y{
0020 - 54 77 4b 70 11 b0 77 5e-1e 9c e7 00 00 2e 00 39 TwKp..w^.......9
0030 - 00 38 00 35 00 16 00 13-00 0a 00 33 00 32 00 2f .8.5.......3.2./
0040 - 00 9a 00 99 00 96 00 05-00 04 00 15 00 12 00 09 ................
0050 - 00 14 00 11 00 08 00 06-00 03 00 ff 01 00 00 16 ................
0060 - 00 00 00 0e 00 0c 00 00-09 6c 6f 63 61 6c 68 6f .........localho
0070 - 73 74 00 23 st.#
0076 - <SPACES/NULS>
read from 0x7fe62b41b370 [0x7fe62b812600] (7 bytes => 0 (0x0))
85473:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-59.60.1/src/ssl/s23_lib.c:185:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 118 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---
On server
E0322 10:04:34.017891000 123145312870400 ssl_transport_security.c:947] Handshake failed with fatal error SSL_ERROR_SSL: error:1408A10B:SSL routines:ssl3_get_client_hello:wrong version number.
E0322 10:04:34.017964000 123145312870400 chttp2_server.c:123] Handshaking failed: {"created":"#1490191474.017913000","description":"Handshake failed","file":"../src/core/lib/security/transport/security_handshaker.c","file_line":274,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"}
I have tried passing -ssl3 and -tls1 in the OpenSSL command with no success. Any thoughts on how to process the info or use the openssl to debug further what might be causing ssl client connection issues to the server. Thanks
i upgraded via brew already from the default Mac version for OpenSSL...
0000 - 16 03 01 .... 03 01
The debug logs shows a ClientHello with TLS version 1.0 (0x0301). This suggests that an old version of OpenSSL was used and not the upgraded one, since this version 1.0.1 (released 2012) it supports TLS 1.2 and will use it by default.

SSH SubjectPublicKeyInfo from modulus and exponent

I'm extracting the modulus and exponent from a public SSH key with the goal of generating a PEM public key. Here is my code so far:
require "base64"
require "openssl"
def unpacked_byte_array(ssh_type, encoded_key)
prefix = [7].pack("N") + ssh_type
decoded = Base64.decode64(encoded_key)
# Base64 decoding is too permissive, so we should validate if encoding is correct
unless Base64.encode64(decoded).gsub("\n", "") == encoded_key && decoded.slice!(0, prefix.length) == prefix
raise PublicKeyError, "validation error"
end
data = []
until decoded.empty?
front = decoded.slice!(0,4)
size = front.unpack("N").first
segment = decoded.slice!(0, size)
unless front.length == 4 && segment.length == size
raise PublicKeyError, "byte array too short"
end
data << OpenSSL::BN.new(segment, 2)
end
return data
end
module OpenSSL
module PKey
class RSA
def self.new_from_parameters(n, e)
a = self.new # self.new(64) for ruby < 1.8.2
a.n = n # converted to OpenSSL::BN automatically
a.e = e
a
end
end
end
end
e, n = unpacked_byte_array('ssh-rsa', 'AAAAB3NzaC1yc2EAAAABIwAAAQEA3RC8whKGFx+b7BMTFtnIWl6t/qyvOvnuqIrMNI9J8+1sEYv8Y/pJRh0vAe2RaSKAgB2hyzXwSJ1Fh+ooraUAJ+q7P2gg2kQF1nCFeGVjtV9m4ZrV5kZARcQMhp0Bp67tPo2TCtnthPYZS/YQG6u/6Aco1XZjPvuKujAQMGSgqNskhKBO9zfhhkAMIcKVryjKYHDfqbDUCCSNzlwFLts3nJ0Hfno6Hz+XxuBIfKOGjHfbzFyUQ7smYnzF23jFs4XhvnjmIGQJcZT4kQAsRwQubyuyDuqmQXqa+2SuQfkKTaPOlVqyuEWJdG2weIF8g3YP12czsBgNppz3jsnhEgstnQ==')
rsa = OpenSSL::PKey::RSA.new_from_parameters(n, e)
puts rsa
The goal is to have a pure Ruby implementation of what ssh-keygen -f <file> -e -m pem does.
Now, comparing the results, they look very similar, but my code returns a few more bytes at the beginning of the key:
$ ssh-keygen -f ~/.ssh/id_rsa_perso.pub -e -m pem
-----BEGIN RSA PUBLIC KEY-----
MIIBCAKCAQEA3RC8whKGFx+b7BMTFtnIWl6t/qyvOvnuqIrMNI9J8+1sEYv8Y/pJ
Rh0vAe2RaSKAgB2hyzXwSJ1Fh+ooraUAJ+q7P2gg2kQF1nCFeGVjtV9m4ZrV5kZA
RcQMhp0Bp67tPo2TCtnthPYZS/YQG6u/6Aco1XZjPvuKujAQMGSgqNskhKBO9zfh
hkAMIcKVryjKYHDfqbDUCCSNzlwFLts3nJ0Hfno6Hz+XxuBIfKOGjHfbzFyUQ7sm
YnzF23jFs4XhvnjmIGQJcZT4kQAsRwQubyuyDuqmQXqa+2SuQfkKTaPOlVqyuEWJ
dG2weIF8g3YP12czsBgNppz3jsnhEgstnQIBIw==
-----END RSA PUBLIC KEY-----
$ ruby ssh2x509.rb
-----BEGIN PUBLIC KEY-----
MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA3RC8whKGFx+b7BMTFtnI
Wl6t/qyvOvnuqIrMNI9J8+1sEYv8Y/pJRh0vAe2RaSKAgB2hyzXwSJ1Fh+ooraUA
J+q7P2gg2kQF1nCFeGVjtV9m4ZrV5kZARcQMhp0Bp67tPo2TCtnthPYZS/YQG6u/
6Aco1XZjPvuKujAQMGSgqNskhKBO9zfhhkAMIcKVryjKYHDfqbDUCCSNzlwFLts3
nJ0Hfno6Hz+XxuBIfKOGjHfbzFyUQ7smYnzF23jFs4XhvnjmIGQJcZT4kQAsRwQu
byuyDuqmQXqa+2SuQfkKTaPOlVqyuEWJdG2weIF8g3YP12czsBgNppz3jsnhEgst
nQIBIw==
-----END PUBLIC KEY-----
Notice my output has the content of the ssh-keygen output, but with MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0A prepended.
What could cause these extra bytes, and how could I get the proper result?
It seems the output format for RSA keys in Ruby OpenSSL was changed in 1.9.3 from PKCS#1 (used by OpenSSH) to X509 (used by OpenSSL post 1.9.3):
https://redmine.ruby-lang.org/issues/4421
What is suggested in this bug report is to emulate the PKCS#1 with:
ary = [OpenSSL::ASN1::Integer.new(n), OpenSSL::ASN1::Integer.new(e)]
pub_key = OpenSSL::ASN1::Sequence.new(ary)
base64 = Base64.encode64(pub_key.to_der)
#This is the equivalent to the PKCS#1 encoding used before 1.9.3
pem = "-----BEGIN RSA PUBLIC KEY-----\n#{base64}-----END RSA PUBLIC KEY-----"
The monkey patching of OpenSSL::PKey::RSA is thus not necessary.
To solve this problem, you can analyze ASN1 structure.
For you output, it is
SEQUENCE(2 elem)
SEQUENCE(2 elem)
OBJECT IDENTIFIER1.2.840.113549.1.1.1
NULL
BIT STRING(1 elem)
SEQUENCE(2 elem)
INTEGER(2048 bit) 279069188856447290054297383130027286257044344789969750715307012565210…
INTEGER35
For ssh output, it is
SEQUENCE(2 elem)
INTEGER(2048 bit) 279069188856447290054297383130027286257044344789969750715307012565210…
INTEGER35
What does this mean? It means your RSA key is structured differently. In SSH, it just contains sequence of 2048 bit integer. Whereas, in your case, it also carries object identification.
Solution? Remove those starting bits which you can calculate by analyzing ASN1 structure.
Or analyze by hexdump that how many bytes are to be removed from your RSA public key.
Your RSA public key:
30 82 01 20 30 0D 06 09 2A 86 48 86 F7 0D 01 01
01 05 00 03 82 01 0D 00 **30 82 01 08 02 82 01 01
00 DD 10 BC C2** 12 86 17 1F 9B EC 13 13 16 D9 C8
5A 5E AD FE AC AF 3A F9 EE A8 8A CC 34 8F 49 F3
ED 6C 11 8B FC 63 FA 49 46 1D 2F 01 ED 91 69 22
80 80 1D A1 CB 35 F0 48 9D 45 87 EA 28 AD A5 00
27 EA BB 3F 68 20 DA 44 05 D6 70 85 78 65 63 B5
… skipping 160 bytes …
0F D7 67 33 B0 18 0D A6 9C F7 8E C9 E1 12 0B 2D
9D 02 01 23
SSH RSA public key
**30 82 01 08 02 82 01 01 00 DD 10 BC C2** 12 86 17
1F 9B EC 13 13 16 D9 C8 5A 5E AD FE AC AF 3A F9
EE A8 8A CC 34 8F 49 F3 ED 6C 11 8B FC 63 FA 49
46 1D 2F 01 ED 91 69 22 80 80 1D A1 CB 35 F0 48
9D 45 87 EA 28 AD A5 00 27 EA BB 3F 68 20 DA 44
… skipping 160 bytes …
74 6D B0 78 81 7C 83 76 0F D7 67 33 B0 18 0D A6
9C F7 8E C9 E1 12 0B 2D 9D 02 01 23
By analyzing this, you can see that you have to remove these:
30 82 01 20 30 0D 06 09 2A 86 48 86 F7 0D 01 01
01 05 00 03 82 01 0D 00
Means 24 bytes. Remove 24 bytes from your key.
Or you can use ASN1 parser and just extract sequence.

CertCreateCertificateContext returns CRYPT_E_ASN1_BADTAG / 8009310b

I realize this is a very similar post to others (e.g. this one), but there are details missing from the posts which might be significant for my case.
To start with, here's my simplified program:
#include "stdafx.h"
#include <windows.h>
#include <wincrypt.h>
int _tmain(int argc, _TCHAR* argv[])
{
// usage: CertExtract certpath
char keyFile[] = "C:\\Certificates\\public.crt";
BYTE lp[65536];
SECURITY_ATTRIBUTES sa;
HANDLE hKeyFile;
DWORD bytes;
PCCERT_CONTEXT certContext;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = FALSE;
hKeyFile = CreateFile(keyFile, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hKeyFile) {
if (ReadFile(hKeyFile, lp, GetFileSize(hKeyFile, NULL), &bytes, NULL) && bytes > 0) {
certContext = CertCreateCertificateContext(X509_ASN_ENCODING, lp, bytes);
if (certContext) {
printf("yay!");
CertFreeCertificateContext(certContext);
}
else {
printf("Could not convert certificate to internal form\n");
}
}
else {
printf("Failed to read key file: %s\n", keyFile);
}
}
else {
printf("Failed to open key file: %s\n", keyFile);
}
CloseHandle(hKeyFile);
return 0;
}
In order to create the certificate, I used the following steps with OpenSSL:
C:\Certificates>openssl genrsa -out private.key 1024
Loading 'screen' into random state - done
Generating RSA private key, 1024 bit long modulus
......................................++++++
................++++++
e is 65537 (0x10001)
C:\Certificates>openssl req -new -key private.key -out public.csr
Loading 'screen' into random state - done
C:\Certificates>copy private.key private.key.org
1 file(s) copied.
C:\Certificates>openssl rsa -in private.key.org -out private.key
writing RSA key
C:\Certificates>openssl x509 -req -days 365 -in public.csr -signkey private.key -ou
t public.crt
Loading 'screen' into random state - done
Signature ok
subject=/CN=My Signing Cert
Getting Private key
with the following conf file:
RANDFILE = .rnd
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
commonName = My Signing Cert
The certificate file looks like:
-----BEGIN CERTIFICATE-----
MIIBqzCCARQCCQDUJyWk0OxlRTANBgkqhkiG9w0BAQUFADAaMRgwFgYDVQQDDA9N
eSBTaWduaW5nIENlcnQwHhcNMTYwMTA1MjIzODU5WhcNMTcwMTA0MjIzODU5WjAa
MRgwFgYDVQQDDA9NeSBTaWduaW5nIENlcnQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A
MIGJAoGBAJobIhfSSMLEPeG9SOBelWHo4hjKXe8dT6cllPr6QXdXe2VNLh9fxVlx
spVGFQwjlF3OHYnmSQnY3m2b5wlFNYVuHvy8rUsZWOF4drSbiqWKh0TuJ+4MBeGq
EormTJ+kiGqNm5IVRrTu9OV8f0XQTGV1pxHircQxsGhxY5w0QTjjAgMBAAEwDQYJ
KoZIhvcNAQEFBQADgYEAedqjKfMyIFC8nUbJ6t/Y8D+fJFwCcdwojUFizr78FEwA
IZSas1b1bXSkA+QEooW7pYdBAfzNuD3WfZAIZpqFlr4rPNIqHzYa0OIdDPwzQQLa
3zPKqjj6QeTWEi5/ArzO+sTVv4m3Og3GQjMChb8H/GxsWdbComPVP82DTUet+ZU=
-----END CERTIFICATE-----
Converting the PEM-encoding to hex allows me to identify the parts of the certificate:
30 SEQUENCE //Certificate
(82 01 AB)
30 SEQUENCE //tbsCertificate
(82 01 14)
02 INTEGER //serialNumber
(09)
00 D4 27 25 A4 D0 EC 65 45
30 SEQUENCE //signature
(0D)
06 OBJECT IDENTIFIER
(09)
2A 86 48 86 F7 0D 01 01 05
05 NULL
(00)
30 SEQUENCE //issuer
(1A)
31 SET
(18)
30 SEQUENCE
(16)
06 OBJECT IDENTIFIER
(03)
55 04 03
0C UTF8String
(0F)
4D 79 20 53 69 67 6E 69 6E 67 20 43 65 72 74
30 SEQUENCE //validity
(1E)
17 UTCTime
(0D)
31 36 30 31 30 35 32 32 33 38 35 39 5A
17 UTCTime
(0D)
31 37 30 31 30 34 32 32 33 38 35 39 5A
30 SEQUENCE //subjectName
(1A)
31 SET
(18)
30 SEQUENCE
(16)
06 OBJECT IDENTIFIER
(03)
55 04 03
0C UTF8String
(0F)
4D 79 20 53 69 67 6E 69 6E 67 20 43 65 72 74
30 SEQUENCE //subjectPublicKeyInfo
(81 9F)
30 SEQUENCE //algorithmId
(0D)
06 OBJECT IDENTIFIER //algorithm
(09)
2A 86 48 86 F7 0D 01 01 01
05 NULL
(00)
03 BIT STRING //subjectPublicKey
(81 8D)
[00] //padding bits
30 SEQUENCE //RSAPublicKey
(81 89)
02 INTEGER //modulus
(81 81)
00 9A 1B 22 17 D2 48 C2 C4 3D E1 BD 48 E0 5E 95 61 E8 E2 18 CA 5D EF 1D 4F A7 25 94 FA FA 41 77 57 7B 65 4D 2E 1F 5F C5 59 71 B2 95 46 15 0C 23 94 5D CE 1D 89 E6 49 09 D8 DE 6D 9B E7 09 45 35 85 6E 1E FC BC AD 4B 19 58 E1 78 76 B4 9B 8A A5 8A 87 44 EE 27 EE 0C 05 E1 AA 12 8A E6 4C 9F A4 88 6A 8D 9B 92 15 46 B4 EE F4 E5 7C 7F 45 D0 4C 65 75 A7 11 E2 AD C4 31 B0 68 71 63 9C 34 41 38 E3 02 03 01 00 01
30 SEQUENCE //signatureAlgorithm
(0D)
06 OBJECT IDENTIFIER
(09)
2A 86 48 86 F7 0D 01 01 05
05 NULL
(00)
03 BIT STRING //signatureValue
(81 81)
[00] //padding bits
79 DA A3 29 F3 32 20 50 BC 9D 46 C9 EA DF D8 F0 3F 9F 24 5C 02 71 DC 28 8D 41 62 CE BE FC 14 4C 00 21 94 9A B3 56 F5 6D 74 A4 03 E4 04 A2 85 BB A5 87 41 01 FC CD B8 3D D6 7D 90 08 66 9A 85 96 BE 2B 3C D2 2A 1F 36 1A D0 E2 1D 0C FC 33 41 02 DA DF 33 CA AA 38 FA 41 E4 D6 12 2E 7F 02 BC CE FA C4 D5 BF 89 B7 3A 0D C6 42 33 02 85 BF 07 FC 6C 6C 59 D6 C2 A2 63 D5 3F CD 83 4D 47 AD F9 95
which appears to conform to the X.509 specs (as I would expect it to):
Certificate ::= {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier,
signatureValue BIT STRING
}
TBSCertificate ::= SEQUENCE {
version [0] Version DEFAULT v1, <-- what does this mean?
serialNumber INTEGER,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subjectName Name,
subjectPublicKeyInfo SubjectPublicKeyInfo
...
}
with the lone exception of the version part, which isn't clear to me whether it is optional or not (though it never seems to be added with certificates I create with OpenSSL).
I can open the certificate to import into a certificate store (and can successfully import to a store), so I don't think anything is specifically wrong with the file/encoding.
When I reach the call to CertCreateCertificateContext, my lp buffer looks like:
-----BEGIN CERTIFICATE-----\nMIIBqzCCARQCCQDUJyWk0OxlRTANBgkqhkiG9w0BAQUFADAaMRgwFgYDVQQDDA9N\neSBTaWduaW5nIENlcnQwHhcNMTYwMTA1MjIzODU5WhcNMTcwMTA0MjIzODU5WjAa\nMRgwFgYDVQQDDA9NeSBTaWduaW5nIENlcnQwgZ8wDQ...
and bytes = 639 -- which is the file size.
I've tried adding logic to strip out the certificate comments, but examples of importing a certificate in this manner don't indicate that should be necessary.
I've tried setting the dwCertEncodingType to X509_ASN_ENCODING | PKCS_7_ASN_ENCODING and PKCS_7_ASN_ENCODING out of desperation (though I don't believe I am using PKCS#7 encoding here...a little fuzzy on that).
Does anyone have any suggestions on what I might be doing incorrectly here? I appreciate it.
I figured out my issue. CertCreateCertificateContext is expecting the binary ASN.1 data, not the PEM-encoded certificate I created with openssl. I figured this out by using a Microsoft certificate generation tool and testing that certificate out:
C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin>makecert.exe -n "CN=Test Signing Cert" -b 0
1/06/2016 -e 01/06/2017 -len 1024 -r C:\Certificates\public_v2.crt
Succeeded
looking at the file in a hex editor, it looked precisely like the ASN.1 binary data. next, I used the Copy to File feature from the certificate viewer that launches when you double-click a certificate to copy my original public.crt file to a DER encoded binary X.509 (.CER) file and verified that my program began to work (that is, the CertCreateCertificateContext was now happy).
so, in case someone else is bumping up against the same issue I was having, here is a complete solution to importing a PEM-encoded certificate from a file into memory for use with the Crypto API:
#include "stdafx.h"
#include <windows.h>
#include <wincrypt.h>
#define LF 0x0A
int _tmain(int argc, _TCHAR* argv[])
{
char keyFile[] = "C:\\Certificates\\public.crt";
BYTE lp[65536];
SECURITY_ATTRIBUTES sa;
HANDLE hKeyFile;
DWORD bytes;
PCCERT_CONTEXT certContext;
BYTE *p;
DWORD flags;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = FALSE;
hKeyFile = CreateFile(keyFile, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hKeyFile) {
if (ReadFile(hKeyFile, lp, GetFileSize(hKeyFile, NULL), &bytes, NULL) && bytes > 0) {
p = lp + bytes;
if (CryptStringToBinary((char *)lp, p - lp, CRYPT_STRING_BASE64_ANY, p, &bytes, NULL, &flags) && bytes > 0) {
certContext = CertCreateCertificateContext(X509_ASN_ENCODING, p, bytes);
if (certContext) {
printf("yay!");
CertFreeCertificateContext(certContext);
}
else {
printf("Could not convert certificate to internal form\n");
}
}
else {
printf("Failed to convert from PEM");
}
}
else {
printf("Failed to read key file: %s\n", keyFile);
}
}
else {
printf("Failed to open key file: %s\n", keyFile);
}
CloseHandle(hKeyFile);
return 0;
}
Note:
because I'm lazy, I decode the PEM encoding to binary in the same BYTE array I used to load the file into -- for this simple test, it was expedient, but if you're looking to implement this sort of thing for real, I wouldn't recommend it

"ERROR: cannot verify www.youtube.com's certificate" with "wget 'http://www.youtube.com'"?

I seem to be having some kind of openssl/certificates issue I can't figure out. Using wget 'http://www.youtube.com' gives me the following certificates error (other sites like amazon and google work, though):
--2015-05-07 11:10:26-- http://www.youtube.com/
Resolving www.youtube.com... 74.125.239.102, 74.125.239.98, 74.125.239.101, ...
Connecting to www.youtube.com|74.125.239.102|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://www.youtube.com/ [following]
--2015-05-07 11:10:26-- https://www.youtube.com/
Connecting to www.youtube.com|74.125.239.102|:443... connected.
ERROR: cannot verify www.youtube.com's certificate, issued by 'CN=Google Internet Authority G2,O=Google Inc,C=US':
Unable to locally verify the issuer's authority.
To connect to www.youtube.com insecurely, use '--no-check-certificate'.
First I tried reinstalling openssl with
~ > brew uninstall openssl
~ > brew install openssl
Nothing changed.
I tried /usr/local/opt/openssl/bin/openssl s_client -connect youtube.com:443 -CAfile /usr/local/etc/openssl/cert.pem but this continues to give me a Verify return code: 20 (unable to get local issuer certificate) full output:
testenv3 > /usr/local/opt/openssl/bin/openssl s_client -connect youtube.com:443 -CAfile /usr/local/etc/openssl/cert.pem
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
i:/C=US/O=Google Inc/CN=Google Internet Authority G2
1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIHgzCCBmugAwIBAgIILW9oBp50RiIwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwNDIyMTMyMTQwWhcNMTUwNzIxMDAwMDAw
WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEVMBMGA1UEAwwMKi5n
b29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgDJKgSnX
rfthwCCB0gc5KDN02J+Uj2xgKeFusyLnCtCv/QYKJjXDXYceViX9aF+GSFZZe1GK
uNP0qYh8/v31zTz0SE5UaQyn9uqz33wwU43Af94J5nnjA6PCZrNnHzhOaDputEgO
y3UwEPSgatVhcVEgdqXeisQOnG7SpRuzfMs/HEsiSmc784+rSBAZKktspXDdh9BK
B84vT7MqdJQKYdqENyqzdnJiqqNieXlcVYDcCVqf/VqoS2zmq1UaZuhBBhi+Q8ef
C5XmniLVKnmAtRktwux1khRV4W1axoEShipaolhww8X2FyiYou0/IUUGRRMOfzwD
5myRr2feJkOFAwIDAQABo4IEUDCCBEwwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMIIDJgYDVR0RBIIDHTCCAxmCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lk
LmNvbYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYISKi5jbG91ZC5nb29nbGUuY29t
ghYqLmdvb2dsZS1hbmFseXRpY3MuY29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUu
Y2yCDiouZ29vZ2xlLmNvLmlugg4qLmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28u
dWuCDyouZ29vZ2xlLmNvbS5hcoIPKi5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5j
b20uYnKCDyouZ29vZ2xlLmNvbS5jb4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2ds
ZS5jb20udHKCDyouZ29vZ2xlLmNvbS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xl
LmVzggsqLmdvb2dsZS5mcoILKi5nb29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdv
b2dsZS5ubIILKi5nb29nbGUucGyCCyouZ29vZ2xlLnB0ghIqLmdvb2dsZWFkYXBp
cy5jb22CDyouZ29vZ2xlYXBpcy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESou
Z29vZ2xldmlkZW8uY29tggwqLmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CCiou
Z3Z0MS5jb22CCiouZ3Z0Mi5jb22CFCoubWV0cmljLmdzdGF0aWMuY29tggwqLnVy
Y2hpbi5jb22CECoudXJsLmdvb2dsZS5jb22CFioueW91dHViZS1ub2Nvb2tpZS5j
b22CDSoueW91dHViZS5jb22CFioueW91dHViZWVkdWNhdGlvbi5jb22CCyoueXRp
bWcuY29tggthbmRyb2lkLmNvbYIEZy5jb4IGZ29vLmdsghRnb29nbGUtYW5hbHl0
aWNzLmNvbYIKZ29vZ2xlLmNvbYISZ29vZ2xlY29tbWVyY2UuY29tggp1cmNoaW4u
Y29tggh5b3V0dS5iZYILeW91dHViZS5jb22CFHlvdXR1YmVlZHVjYXRpb24uY29t
MGgGCCsGAQUFBwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5nb29nbGUu
Y29tL0dJQUcyLmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMxLmdvb2ds
ZS5jb20vb2NzcDAdBgNVHQ4EFgQUiM602EJkc9+TR6CsmcXD7cBI35YwDAYDVR0T
AQH/BAIwADAfBgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAXBgNVHSAE
EDAOMAwGCisGAQQB1nkCBQEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5n
b29nbGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAUi0NYc8EEax2
6DpqB9ZWYQTbgmIADA2ksPZtJ1MUJXbENoUlILIcv4qFgoPXqZPDLhuBZ+aJmfXL
3H4Z4piBAZC11nGioZaubKxqYa/ujKgmnjYeGaFGPWocYZOw2RmZwp/RLaMP64JH
Y6QgyEZlbX//lV6e4PjFSnr0y90Ksrl1PsvwUFV8dTfhI079OXtqD6sqEEf+uRao
7HHH50ZKGkb1Aa5e8xXx9DOo6siyAEVRGb1+uxnGsPZW2v3UmNPXmp5YdKmPifxT
5lGe54TepRde2y+UvsyeFAjroSnm10fnkj777peFg/sK3Gs1tAbNgw6SDOPVnvBz
q59oNKUisw==
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4500 bytes and written 474 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: BE12D954ABDF74775FCCDBD467C6494D2F5F93FC5C582F6086B42CB7F5A3C5CD
Session-ID-ctx:
Master-Key: 57AB75014EBE5C3CF5B617033D2EAFCA29780953F00FAE65C7BA9945202474717AA713F7E79B51C88007DE2A88559F62
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 100800 (seconds)
TLS session ticket:
0000 - 6e 35 b6 f5 87 7f fc 8c-bd 57 35 a3 b9 89 15 4d n5.......W5....M
0010 - fe 9b d1 cf 05 7e b1 46-66 06 83 cd 83 ec ea f7 .....~.Ff.......
0020 - 3f 2a a5 56 97 b3 76 c1-0d eb a4 d4 57 fd bb 23 ?*.V..v.....W..#
0030 - a6 5a ea 63 17 cd 8d 47-f1 80 a5 d9 c8 74 d7 0f .Z.c...G.....t..
0040 - b2 f7 63 5a 9a fd 0f 2f-3d 95 96 07 54 89 51 cf ..cZ.../=...T.Q.
0050 - 7b d2 79 3f 9b ff 14 ed-af d8 cf dd 29 bd de 3d {.y?........)..=
0060 - 70 c1 ff 6b 5d d3 78 a7-62 f4 df 25 05 be 2c 94 p..k].x.b..%..,.
0070 - 96 20 54 a2 70 8d 25 5c-75 93 ab f1 0b 1a 2a 29 . T.p.%\u.....*)
0080 - 5b 1c 2c fb 64 80 73 84-c7 0a 27 f9 57 39 d0 81 [.,.d.s...'.W9..
0090 - df dd 17 ff 3e 0a 37 5e-32 d3 8b 65 49 6f a4 e9 ....>.7^2..eIo..
00a0 - cf 01 76 3b ..v;
Start Time: 1430847495
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
I also tried echo | openssl s_client -connect youtube.com:443 and here is that output:
(testenv3)testenv3 > echo | openssl s_client -connect youtube.com:443
CONNECTED(00000003)
depth=2 /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
i:/C=US/O=Google Inc/CN=Google Internet Authority G2
1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIHgzCCBmugAwIBAgIILW9oBp50RiIwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwNDIyMTMyMTQwWhcNMTUwNzIxMDAwMDAw
WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEVMBMGA1UEAwwMKi5n
b29nbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgDJKgSnX
rfthwCCB0gc5KDN02J+Uj2xgKeFusyLnCtCv/QYKJjXDXYceViX9aF+GSFZZe1GK
uNP0qYh8/v31zTz0SE5UaQyn9uqz33wwU43Af94J5nnjA6PCZrNnHzhOaDputEgO
y3UwEPSgatVhcVEgdqXeisQOnG7SpRuzfMs/HEsiSmc784+rSBAZKktspXDdh9BK
B84vT7MqdJQKYdqENyqzdnJiqqNieXlcVYDcCVqf/VqoS2zmq1UaZuhBBhi+Q8ef
C5XmniLVKnmAtRktwux1khRV4W1axoEShipaolhww8X2FyiYou0/IUUGRRMOfzwD
5myRr2feJkOFAwIDAQABo4IEUDCCBEwwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMIIDJgYDVR0RBIIDHTCCAxmCDCouZ29vZ2xlLmNvbYINKi5hbmRyb2lk
LmNvbYIWKi5hcHBlbmdpbmUuZ29vZ2xlLmNvbYISKi5jbG91ZC5nb29nbGUuY29t
ghYqLmdvb2dsZS1hbmFseXRpY3MuY29tggsqLmdvb2dsZS5jYYILKi5nb29nbGUu
Y2yCDiouZ29vZ2xlLmNvLmlugg4qLmdvb2dsZS5jby5qcIIOKi5nb29nbGUuY28u
dWuCDyouZ29vZ2xlLmNvbS5hcoIPKi5nb29nbGUuY29tLmF1gg8qLmdvb2dsZS5j
b20uYnKCDyouZ29vZ2xlLmNvbS5jb4IPKi5nb29nbGUuY29tLm14gg8qLmdvb2ds
ZS5jb20udHKCDyouZ29vZ2xlLmNvbS52boILKi5nb29nbGUuZGWCCyouZ29vZ2xl
LmVzggsqLmdvb2dsZS5mcoILKi5nb29nbGUuaHWCCyouZ29vZ2xlLml0ggsqLmdv
b2dsZS5ubIILKi5nb29nbGUucGyCCyouZ29vZ2xlLnB0ghIqLmdvb2dsZWFkYXBp
cy5jb22CDyouZ29vZ2xlYXBpcy5jboIUKi5nb29nbGVjb21tZXJjZS5jb22CESou
Z29vZ2xldmlkZW8uY29tggwqLmdzdGF0aWMuY26CDSouZ3N0YXRpYy5jb22CCiou
Z3Z0MS5jb22CCiouZ3Z0Mi5jb22CFCoubWV0cmljLmdzdGF0aWMuY29tggwqLnVy
Y2hpbi5jb22CECoudXJsLmdvb2dsZS5jb22CFioueW91dHViZS1ub2Nvb2tpZS5j
b22CDSoueW91dHViZS5jb22CFioueW91dHViZWVkdWNhdGlvbi5jb22CCyoueXRp
bWcuY29tggthbmRyb2lkLmNvbYIEZy5jb4IGZ29vLmdsghRnb29nbGUtYW5hbHl0
aWNzLmNvbYIKZ29vZ2xlLmNvbYISZ29vZ2xlY29tbWVyY2UuY29tggp1cmNoaW4u
Y29tggh5b3V0dS5iZYILeW91dHViZS5jb22CFHlvdXR1YmVlZHVjYXRpb24uY29t
MGgGCCsGAQUFBwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5nb29nbGUu
Y29tL0dJQUcyLmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMxLmdvb2ds
ZS5jb20vb2NzcDAdBgNVHQ4EFgQUiM602EJkc9+TR6CsmcXD7cBI35YwDAYDVR0T
AQH/BAIwADAfBgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAXBgNVHSAE
EDAOMAwGCisGAQQB1nkCBQEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5n
b29nbGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAUi0NYc8EEax2
6DpqB9ZWYQTbgmIADA2ksPZtJ1MUJXbENoUlILIcv4qFgoPXqZPDLhuBZ+aJmfXL
3H4Z4piBAZC11nGioZaubKxqYa/ujKgmnjYeGaFGPWocYZOw2RmZwp/RLaMP64JH
Y6QgyEZlbX//lV6e4PjFSnr0y90Ksrl1PsvwUFV8dTfhI079OXtqD6sqEEf+uRao
7HHH50ZKGkb1Aa5e8xXx9DOo6siyAEVRGb1+uxnGsPZW2v3UmNPXmp5YdKmPifxT
5lGe54TepRde2y+UvsyeFAjroSnm10fnkj777peFg/sK3Gs1tAbNgw6SDOPVnvBz
q59oNKUisw==
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
---
SSL handshake has read 3999 bytes and written 444 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : RC4-SHA
Session-ID: 10775C02A73AB2D86F618C26491521BAC0EF8FAB670C7BEFC7F1FAA223064A57
Session-ID-ctx:
Master-Key: B7D9845159D987F16A7E1A847C049E1E2A703590C4846731ACCB12B34A5056900BAFEF75A461E999A786B258C12E87AC
Key-Arg : None
Start Time: 1430785075
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
DONE
I don't know what else to do from here and I have little to no understanding of openssl and certificates. What exactly do I need to do to fix this?

Resources