How to create CSR with utf8 subject in openssl? - utf-8

I am trying to generate Certificate Signing Request with UTF-8 subject.
$ openssl req -utf8 -nodes -newkey rsa:2048 -keyout my.private_key.pem -out my.csr.pem -text
Generating a 2048 bit RSA private key
......................................................................................................................................................................+++
......+++
writing new private key to 'my.private_key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [PL]:
State or Province Name (full name) []:Zażółć gęślą jaźń
problems making Certificate Request
12376:error:0D07A07C:asn1 encoding routines:ASN1_mbstring_ncopy:illegal characters:a_mbstr.c:162:
Terminal encoding is UTF-8, I get the same problem when I use command line subject
(...) -subj /C=PL/ST=zażółć\ gęślą\ jaźń/O=my-company/CN=ThisIsMeForSure
When I skip the -utf8 switch, the CSR is generated with all the non-ascii characters replaced with hex notation (eg ó becomes \xC3\xB3). Such CSR cannot be read properly with php (openss_x509_parse) - the original ó is read as four bytes, representing two weird characters...
What am I doing wrong?

I've been successful with command
openssl req -new -utf8 -nameopt multiline,utf8 -config example.com.cnf -newkey rsa:2048 -nodes -keyout example.com.key -out example.com.csr
Where example.com.cnf is a configuration file in UTF-8:
[req]
prompt = no
distinguished_name = dn
req_extensions = ext
[dn]
CN = Описание сайта # Site description
emailAddress = envek#envek.name
O = Моя компания # My company
OU = Моё подразделение # My dept
L = Москва # Moscow
C = RU
[ext]
subjectAltName = DNS:example.com,DNS:*.example.com
Displayed correctly in Chrome, Firefox, and Safari.

Try using the string_mask option:
string_mask
This option masks out the use of certain string types in certain fields. Most users will not need to change this option.
It can be set to several values default which is also the default option uses PrintableStrings, T61Strings and BMPStrings if the pkix value is used then only PrintableStrings and BMPStrings will be used. This follows the PKIX recommendation in RFC2459. If the utf8only option is used then only UTF8Strings will be used: this is the PKIX recommendation in RFC2459 after 2003. Finally the nombstr option just uses PrintableStrings and T61Strings: certain software has problems with BMPStrings and UTF8Strings: in particular Netscape.

Any unicode work for me, from php file.
<? shell_exec('openssl req -new -md5 -utf8 -key C:/Temp/1.key -out C:/Temp/1.csr -subj "/C=MD/ST=ff/O=Religie/OU=Cen/CN=中国/emailAddress=test#religiasatanista.ro" -config C:/Temp/openssl.cnf'); ?>

Related

OpenSSL Subca and SAN Website Certificate

currently in my work, we have a PKI made with Microsoft Certificate Authority Role.
Root CA: Out of domain and turned off.
Sub CA: Domain connected, provides CRL (using IIS) and sign certificates for domain computers.
My idea is to reproduce the environment with Linux and Openssl. At least my first objective is for the internal webs.
I followed this tutorial https://jamielinux.com/docs/openssl-certificate-authority/ and everything works fine.
I create the Root CA and self-sign it.
I create the Subca, I sign it with the Root and verify that the certification chain is correct -> OK
The problem is when I try to create a website certificate with SAN (Subject Alternative Name) field. This is the way I create the csr and key files.
openssl req -nodes -new -newkey rsa:4096 \
-keyout test3.psc.local.key \
-out test3.psc.local.csr \
-addext "subjectAltName = DNS:test3.psc.local" \
-subj "/C=ES/ST=Barcelona/L=Barcelona/O=GRG-CA/OU=GRG-CA/emailAddress=your#email.dot/CN=test3.psc.local/"
If I check the CSR with OpenSSL command openssl x509 -noout -text -in test3.psc.local.csr the SAN field exist and has the value that I set in generation command (test3.psc.local).
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = ES, ST = Barcelona, L = Barcelona, O = GRG-CA, OU = GRG-CA, emailAddress = your#email.dot, CN = test3.psc.local
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (4096 bit)
Modulus:
00:dc:17:8c:c1:90:26:16:67:4e:16:b3:0c:9b:2b:
3d:ec:8e:94:47:b9:8c:b8:14:ac:be:09:b8:bb:f5:
d8:f2:79:26:a6:9d:2f:73:5b:48:64:cb:3a:c2:f6:
bd:6d:7f:fd:7e:f2:... bla bla bla
Exponent: 65537 (0x10001)
Attributes:
Requested Extensions:
X509v3 Subject Alternative Name:
DNS:test3.psc.local
Signature Algorithm: sha256WithRSAEncryption
b5:f0:7f:ba:ab:dc:f6:ee:37:c5:fa:14:27:6b:09:a8:b8:08:
0b:4f:ed:2a:44:72:cd:8d:50:47:79:7d:69:e3:73:cc:14:89:
b6:69:ff:61:bb:79:0a:41:12:32:c7:d1:6f:1d:a4:e4:cb:ef:
16:56:35:fd:44:0a:0c:70:fc:45:1f:7d:c2:d7:4c:ca:bd:66:
6d:e6:41:74:56:2c:... bla bla bla
When I try to sign the certificate with OpenSSL Subca I execute with this command.
openssl ca -config intermediate/sub-ca-openssl.cnf \
-extensions server_cert \
-days 375 -notext -md sha512 \
-in /root/ca/test3.psc.local.csr \
-out /root/ca/test3.psc.local.crt
But the SAN field isn't present, so Firefox, Chrome and others dont trust in certificate. Only IE11 trust.
Using configuration from intermediate/sub-ca-openssl.cnf
Enter pass phrase for /root/ca/intermediate/private/intermediate.key.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 4099 (0x1003)
Validity
Not Before: Oct 12 20:58:53 2022 GMT
Not After : Oct 22 20:58:53 2023 GMT
Subject:
countryName = ES
stateOrProvinceName = Barcelona
localityName = Barcelona
organizationName = GRG-CA
organizationalUnitName = GRG-CA
commonName = test3.psc.local
emailAddress = your#email.dot
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Server
Netscape Comment:
OpenSSL Generated Server Certificate
X509v3 Subject Key Identifier:
BC:11:0C:2E:08:FA:7D:91:16:1E:AC:0E:12:DA:80:69:64:F7:F1:58
X509v3 Authority Key Identifier:
keyid:7D:B8:7B:9E:59:4F:70:7B:F8:2C:1F:2B:0C:A2:E9:90:3C:D1:7A:71
DirName:/C=ES/ST=Barcelona/L=Barcelona/O=GRG-CA/OU=GRG-CA/CN=GRG Root CA
serial:10:00
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 CRL Distribution Points:
Full Name:
URI:http://pki.dominio.com/intermediate.crl
Certificate is to be certified until Oct 22 20:58:53 2023 GMT (375 days)
Sign the certificate? [y/n]:
Content of SUB CA config:
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /root/ca/intermediate
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/subordinate-ca-database.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
private_key = $dir/private/intermediate.key.pem
certificate = $dir/certs/intermediate.cert.pem
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate.crl.pem
crl_extensions = crl_ext
default_crl_days = 365
default_md = sha512
name_opt = ca_default
cert_opt = ca_default
default_days = 5840
preserve = no
policy = subca_policy
[ subca_policy ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha512
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = ES
stateOrProvinceName_default = Barcelona
localityName_default = Barcelona
0.organizationName_default = GRG-CA
organizationalUnitName_default = GRG-CA
#emailAddress_default =
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical,CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
crlDistributionPoints = URI:http://pki.dominio.com/intermediate.crl
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ crl_info ]
URI.0 = http://pki.dominio.com/sub-ca.crl
URI.1 = https://www.dominio.com/pki/sub-ca.crl
I've read that I need a SAN.conf with alternate names in SUBCA server for sign... and change all Alternate Names for every CSR (website) that I want to sign... but in Microsoft Subca I dont need to tell that fields when I sign the CSR (only on generation, same command as I write before).
There is a way to do that?
From the man page for OpenSSL's CA command:
copy_extensions
determines how extensions in certificate requests should be handled.
If set to none or this option is not present then extensions are
ignored and not copied to the certificate. If set to copy then any
extensions present in the request that are not already present are
copied to the certificate. If set to copyall then all extensions in
the request are copied to the certificate: if the extension is already
present in the certificate it is deleted first. See the WARNINGS
section before using this option.
The main use of this option is to allow a certificate request to
supply values for certain extensions such as subjectAltName.
Also, you should understand that using OpenSSL as a CA isn't the best idea. There is no logging, no multi-person control etc. - basically no security. Read the WARNINGS section of the same man page.

openssl req utf8 strings

as others i'm struggling with utf8 in requests. sure i went through all preciding questions and answers. well here is my workout.
configuration:
[ req ]
default_bits = 2048
default_md = sha256
string_mask = utf8only
utf8 = yes
distinguished_name = DistName
attributes = Attr
[ DistName ]
commonName = Name (your official name)
commonName_default = hans nägli dödüé
stateOrProvinceName = State or Province Name (full name)
countryName = Country Code (2 letter code)
countryName_default = CH
[ Attr ]
subjectAltName = Name (international / latin)
subjectAltName_default = hans nägeli dädü
postalCode = zip code
localityName = Locality Name (eg, city)
emailAddress = Email Address
i verified this config file is utf8 and started thereafter using default values:
openssl req -verbose -config CsrPerson.cfg -new -key HansMuster-ecpem.key -passin pass:gugus -out HansMuster-pem.csr
i then had a look into the request using
openssl req -utf8 -noout -text -in HansMuster-pem.csr
showing
Certificate Request:
Data:
Version: 1 (0x0)
Subject: CN = hans n\C3\A4gli d\C3\B6d\C3\BC\C3\A9, ST = z\C3\BCrich, C = CH
Subject Public Key Info:
...snip...
NIST CURVE: P-384
Attributes:
postalCode :2222
localityName :Dörrhausen
X509v3 Subject Alternative Name:hans nägeli dädü
emailAddress :hans.naegeli#gmx.net
...snip...
using same source, same configuration, same procedure: subject/distinguished name has not been treated as utf8 but worked out well with attributes even with locality name which was entred by keyboard.
ASN1 definition of subject show a possible content as utf8 string. openssl version OpenSSL 1.1.0g 2 Nov 2017.
where have i been mistaken?
have fun
You can try the following:
openssl req -nameopt utf8 -noout -text -in HansMuster-pem.csr
This should only fix the display problem, you have to check if your other requirements are still met.
You can find more details about the "-nameopt" options here in the "NAME OPTIONS" section: https://www.openssl.org/docs/man1.0.2/man1/x509.html
Other related links:
How to create CSR with utf8 subject in openssl?

How to generate csr and crt files using openssl in ruby

So i'm using AWS Iot and have a server running ruby on rails in the backend. i need to generate some certs for the client and the example on the AWS website only provides a way to do it using the openssl command line. If possible i would like to use the open ssl library in ruby to do this to avoid making ruby run commands in the terminal which may cause issues.
These are the commands i want to replicate using ruby
openssl genrsa -out deviceCert.key 2048
openssl req -new -key deviceCert.key -out deviceCert.csr
openssl x509 -req -in deviceCert.csr -CA sampleCACertificate.pem -CAkey sampleCACertificate.key -CAcreateserial -out deviceCert.crt -days 99999 -sha256
The first line i found and think i can do
require 'openssl'
rsa_key = OpenSSL::PKey::RSA.new(2048)
but i'm stuck on the last 2 lines. Any ideas?
Here is an example to generate a self signed certificate.
require 'rubygems'
require 'openssl'
key = OpenSSL::PKey::RSA.new(1024)
public_key = key.public_key
subject = "/C=BE/O=Test/OU=Test/CN=Test"
cert = OpenSSL::X509::Certificate.new
cert.subject = cert.issuer = OpenSSL::X509::Name.parse(subject)
cert.not_before = Time.now
cert.not_after = Time.now + 365 * 24 * 60 * 60
cert.public_key = public_key
cert.serial = 0x0
cert.version = 2
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = cert
ef.issuer_certificate = cert
cert.extensions = [
ef.create_extension("basicConstraints","CA:TRUE", true),
ef.create_extension("subjectKeyIdentifier", "hash"),
# ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
]
cert.add_extension ef.create_extension("authorityKeyIdentifier",
"keyid:always,issuer:always")
cert.sign key, OpenSSL::Digest::SHA1.new
puts cert.to_pem
Source for Example
was able to eventually figure it out using this rdoc example
http://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/X509/Certificate.html#method-c-new

Decrypt PKCS7 in Ruby on Rails

I try to decrypt PKCS7 data, but always receive error OpenSSL::PKCS7::PKCS7Error - wrong content type on method "pkcs7.decrypt(key, cer)".
example:
cer = OpenSSL::X509::Certificate.new(File.read("path/cert.cer"))
key = OpenSSL::PKey::RSA.new(File.read("path/private.key"), "111111")
crypted_data = File.read('path/pkcs7') # contains xml-file and signature "-----BEGIN PKCS7----- ... -----END PKCS7-----"
pkcs7 = OpenSSL::PKCS7.new(crypted_data)
decrypted_data = pkcs7.decrypt(key, cer) # error is here
need help! how to get data from the encrypted string?
updated:
on bash I can solve this task by following code:
openssl smime -verify -noverify -inform PEM -nointern -certfile "path/cert.cer" -CAfile "path/cert.cer" < path/pkcs7
returns xml file.
Solution founded!!!
cert_store = OpenSSL::X509::Store.new
my_cert = OpenSSL::X509::Certificate.new(File.read("remote.cer"))
signature = OpenSSL::PKCS7.new(File.read('pkcs7-resp.file'))
signature.verify([my_cert], cert_store, nil, OpenSSL::PKCS7::NOVERIFY)
signature.data

Why is this Ruby SSL-enabled server/client test working?

I'm working through creating an SSL-enabled server in Ruby, along with a corresponding Ruby client to use with the server. In order to test, I created my own Root CA certificate with the following commands.
$:~/devel/ssl-test/ssl/CA$ openssl genrsa -out TestCA.key 2048
Generating RSA private key, 2048 bit long modulus
............+++
...........................+++
e is 65537 (0x10001)
$:~/devel/ssl-test/ssl/CA$ openssl req -new -key TestCA.key -out TestCA.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
$:~/devel/ssl-test/ssl/CA$ openssl x509 -req -days 365 -in TestCA.csr -out TestCA.crt -signkey TestCA.key
Signature ok
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
Getting Private key
I then generated an SSL certificate for my server:
$:~/devel/ssl-test/ssl/keys$ openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
.+++
............................................+++
e is 65537 (0x10001)
$:~/devel/ssl-test/ssl/keys$ cd ../csrs/
$:~/devel/ssl-test/ssl/csrs$ openssl req -new -key ../keys/server.key -out server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:my.secure.test
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
$:~/devel/ssl-test/ssl/csrs$ cd ../certs/
$:~/devel/ssl-test/ssl/certs$ openssl ca -in ../csrs/server.csr -cert ../CA/TestCA.crt -keyfile ../CA/TestCA.key -out server.crt
Using configuration from /usr/lib/ssl/openssl.cnf
I am unable to access the ./demoCA/newcerts directory
./demoCA/newcerts: No such file or directory
$:~/devel/ssl-test/ssl/certs$ mkdir -p demoCA/newcerts
$:~/devel/ssl-test/ssl/certs$ touch demoCA/index.txt
$:~/devel/ssl-test/ssl/certs$ echo "01" > demoCA/serial
$:~/devel/ssl-test/ssl/certs$ openssl ca -in ../csrs/server.csr -cert ../CA/TestCA.crt -keyfile ../CA/TestCA.key -out server.crt
Using configuration from /usr/lib/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Oct 25 16:25:05 2011 GMT
Not After : Oct 24 16:25:05 2012 GMT
Subject:
countryName = AU
stateOrProvinceName = Some-State
organizationName = Internet Widgits Pty Ltd
commonName = my.secure.test
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
48:50:B5:04:11:02:F1:40:97:58:BF:5F:8B:27:50:10:C0:3F:EE:D9
X509v3 Authority Key Identifier:
DirName:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
serial:81:44:16:06:5C:EB:5E:71
Certificate is to be certified until Oct 24 16:25:05 2012 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
After that, I created a simplistic SSL-enabled server to use the SSL certificate I just created.
require 'socket'
require 'openssl'
require 'thread'
server = TCPServer.new(1337)
context = OpenSSL::SSL::SSLContext.new
context.cert = OpenSSL::X509::Certificate.new(File.open('ssl/certs/server.crt'))
context.key = OpenSSL::PKey::RSA.new(File.open('ssl/keys/server.key'))
secure = OpenSSL::SSL::SSLServer.new(server, context)
puts 'Listening securely on port 1337...'
loop do
Thread.new(secure.accept) do |conn|
begin
while request = conn.gets
$stdout.puts '=> ' + request
response = "You said: #{request}"
$stdout.puts '<= ' + response
conn.puts response
end
rescue
$stderr.puts $!
end
end
end
When started, it seems to work fine...
$:~/devel/ssl-test$ ruby server.rb
Listening securely on port 1337...
I then created a non-SSL capable client just to ensure it was denied connectivity.
require 'socket'
require 'thread'
client = TCPSocket.new('127.0.0.1', 1337)
Thread.new do
begin
while response = client.gets
$stdout.puts response
end
rescue
$stderr.puts "Error from client: #{$!}"
end
end
while request = $stdin.gets
request = request.chomp
client.puts request
end
When I run this via the following:
$:~/devel/ssl-test$ ruby client.rb
hello
Error from client: Connection reset by peer
Correspondingly, I get the following from the server:
$:~/devel/ssl-test$ ruby server.rb
Listening securely on port 1337...
/usr/local/rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/openssl/ssl-internal.rb:164:in `accept': SSL_accept returned=1 errno=0 state=SSLv2/v3 read client hello A: unknown protocol (OpenSSL::SSL::SSLError)
from /usr/local/rvm/rubies/ruby-1.9.2-head/lib/ruby/1.9.1/openssl/ssl-internal.rb:164:in `accept'
from server.rb:16:in `block in <main>'
from server.rb:15:in `loop'
from server.rb:15:in `<main>'
This was all expected. Next, I modified the client code to use an SSL context.
require 'socket'
require 'openssl'
require 'thread'
client = TCPSocket.new('127.0.0.1', 1337)
context = OpenSSL::SSL::SSLContext.new
secure = OpenSSL::SSL::SSLSocket.new(client, context)
secure.sync_close = true
secure.connect
Thread.new do
begin
while response = secure.gets
$stdout.puts response
end
rescue
$stderr.puts "Error from client: #{$!}"
end
end
while request = $stdin.gets
request = request.chomp
secure.puts request
end
I fully expected this to fail as well during the handshake process, but it did not... I got the following result:
$:~/devel/ssl-test$ ruby client.rb
hello
You Said: hello
Why did this work? I was assuming it would fail because I didn't think the client would have any idea about the Root CA I created and signed the server SSL certificate with, and therefore wouldn't be able to verify the server's certificate. What am I missing? When I created and signed the server's certificate and it was "committed", did this somehow make it available to the OpenSSL library? I was expecting to have to somehow tell the SSL context in the client where to look for the Root CA I created for testing purposes...
As a follow-up test, I copied my client code over to a different machine that definitely knows nothing about the Root CA I created for this test, changed the IP address the client connects to, and ran the test again. This test produced the same results - the client was able to communicate with the server when I assumed it wouldn't be able to. Any ideas?
Depending on the version of Ruby you are using, the default verify mode for the SSLContext object may not be enforcing certificate verification. You can force the verify mode with:
context = OpenSSL::SSL::SSLContext.new
context.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
This should cause the client's connection attempt to fail, as expected.

Resources