Use async-native-tls with a custom CA - ssl

I'm attempting to connect to a transparent Burp proxy using async-native-tls. The way the transparent Burp proxy works is that it generates a new TLS cert based on the SNI parameter of incoming TLS connections on the fly. These TLS certs it generates are all signed by a Burp CA.
When I run my code, I get an error from OpenSSL complaining about a self-signed certificate in the chain. That's totally expected. In fact, all TLS certificate chains have a self-signed certificate in the path -- the CA! I believe I've correctly configured the Burp CA certificate as an alternative to the system CA.
Below are the relevant snippets.
use async_native_tls::{Certificate, TlsConnector};
use http_client::hyper::HyperClient;
use http_client::{hyper, Config, HttpClient, Request};
use std::error::Error;
use std::sync::Arc;
let mut tls_builder = native_tls::TlsConnector::builder();
tls_builder
// This is important, as it's how Burp knows which certificate to present
.use_sni(true)
// This is important, as it indicates that Burp's CA should be trusted
.add_root_certificate(Certificate::from_pem(
std::fs::read("/tmp/ca.pem")?.as_slice(),
)?)
// These should not be required, but I've turned them on in despairation
.danger_accept_invalid_hostnames(true)
.danger_accept_invalid_certs(true)
.disable_built_in_roots(true)
.max_protocol_version(None)
.min_protocol_version(None);
let burp_proxy_tls = TlsConnector::from(tls_builder);
let burp_proxy_config = Config::default().set_tls_config(Some(Arc::new(burp_proxy_tls)));
let mut http_client = HyperClient::new();
http_client.set_config(burp_proxy_config)?;
let mut request = Request::get("https://127.0.0.1:8000/...");
request.append_header("Cookie", "...");
// Not strictly needed since it's also in SNI
request.append_header("Host", "...");
let mut response = http_client.send(request).await?;
When I connect via s_client, everything verifies OK:
$ openssl s_client -connect 127.0.0.1:8000 \
-servername www......com \
-CAfile /tmp/ca.pem \
</dev/null
CONNECTED(00000003)
depth=1 C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
verify return:1
depth=0 C = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = www......com
verify return:1
---
Certificate chain
0 s:C = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = www........com
i:C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Jan 10 02:29:14 2023 GMT; NotAfter: Jan 10 02:29:14 2024 GMT
1 s:C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
i:C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Jan 24 00:53:54 2014 GMT; NotAfter: Jan 24 00:53:54 2033 GMT
...
subject=C = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = www.......com
issuer=C = PortSwigger, ST = PortSwigger, L = PortSwigger, O = PortSwigger, OU = PortSwigger CA, CN = PortSwigger CA
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 2521 bytes and written 403 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
DONE
But then the program fails:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.15s
Running `target/debug/xxxxxx`
Error: error trying to connect: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1889: (self-signed certificate in certificate chain)
Caused by:
0: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1889: (self-signed certificate in certificate chain)
1: error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:1889:

Well, I never did figure out if this was possible with the async-native-tls library. I wasn't tied to that library so I switched to isahc since it was backed by CURL and I know I can get that to do what I want.
I did have to switch my burp proxy to port 443 because isahc doesn't support --connect-to yet, but I can work with that.
let http_client = HttpClient::builder()
.dns_resolve(ResolveMap::new().add("www.......com", 443, [127, 0, 0, 1]))
.ssl_ca_certificate(CaCertificate::file("/tmp/ca.pem"))
.ssl_options(SslOption::DANGER_ACCEPT_INVALID_CERTS)
.automatic_decompression(true)
.build()?;
let request = Request::get("https://www.......com/....")
.header("Cookie", cookies)
.body(())?;
let mut response = http_client.send(request)?;

Related

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1123)

import time
import logging
import paho.mqtt.client as mqtt
from OpenSSL import SSL
import os
import ssl
log = logging.getLogger('RemoTV.hardware.l298n')
logging.basicConfig(level=logging.DEBUG)
sleeptime = 0.2
rotatetimes = 0.4
StepPinForward = None
StepPinBackward = None
StepPinLeft = None
StepPinRight = None
def setup(robot_config):
global StepPinForward
global StepPinBackward
global StepPinLeft
global StepPinRight
global sleeptime
global rotatetimes
sleeptime = robot_config.getfloat('l298n', 'sleeptime')
rotatetimes = robot_config.getfloat('l298n', 'rotatetimes')
log.debug("GPIO mode : %s", str(GPIO.getmode()))
GPIO.setwarnings(False)
GPIO.cleanup()
if robot_config.getboolean('tts', 'ext_chat'): # ext_chat enabled, add motor commands
extended_command.add_command('.set_rotate_time', set_rotate_time)
extended_command.add_command('.set_sleep_time', set_sleep_time)
# TODO passing these as tuples may be unnecessary, it may accept lists as well.
StepPinForward = tuple(map(int, robot_config.get('l298n', 'StepPinForward').split(',')))
StepPinBackward = tuple(map(int, robot_config.get('l298n', 'StepPinBackward').split(',')))
StepPinLeft = tuple(map(int, robot_config.get('l298n', 'StepPinLeft').split(',')))
StepPinRight = tuple(map(int, robot_config.get('l298n', 'StepPinRight').split(',')))
def on_message(client, userdata, message):
payload = message.payload.decode('utf-8')
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(11, GPIO.OUT)
GPIO.setup(15, GPIO.OUT)
GPIO.setup(16, GPIO.OUT)
GPIO.setup(36, GPIO.OUT)
GPIO.setup(35, GPIO.OUT)
if payload == 'f':
GPIO.output(12, GPIO.HIGH)
time.sleep(sleeptime)
GPIO.output(12, GPIO.LOW)
if payload == 'b':
GPIO.output(11, GPIO.HIGH)
time.sleep(sleeptime)
GPIO.output(11, GPIO.LOW)
if payload == 'l':
GPIO.output(15, GPIO.HIGH)
time.sleep(sleeptime * rotatetimes)
GPIO.output(15, GPIO.LOW)
if payload == 'r':
GPIO.output(16, GPIO.HIGH)
time.sleep(sleeptime * rotatetimes)
GPIO.output(16, GPIO.LOW)
if payload == 'z':
GPIO.output(36, GPIO.HIGH)
time.sleep(sleeptime * rotatetimes)
GPIO.output(36, GPIO.LOW)
if payload == 'x':
GPIO.output(35, GPIO.HIGH)
time.sleep(sleeptime * rotatetimes)
GPIO.output(35, GPIO.LOW)
ca_cert_path = "fullchain1.pem"
client = mqtt.Client()
# Set the TLS/SSL parameters for the client
client.tls_set(
ca_certs=ca_cert_path,
certfile='cert1.pem',
keyfile='privkey1.pem',
cert_reqs=ssl.CERT_REQUIRED,
tls_version=SSL.SSLv23_METHOD
)
client.username_pw_set(username="not posting my passwd", password="lol ahah")
# client.tls_insecure_set(False)
client.on_message = on_message
client.connect('clawclan.co.uk',8083)
client.subscribe("clawmachine/controls")
client.loop_forever()
Thats the python code that I'm using to connect to my mqtt broker, I have been through multiple issues as tlsv1.3 isn't supported by pyopenssl or something, I have spent days trying to get this code to work and fixing issues, and this one has been making me lose my mind hahahahahahahahah.
My mosquitto config:
allow_anonymous false
password_file /home/pi/claw/passwordfile.txt
listener 1883 localhost
listener 8883
certfile /home/pi/claw/cert1.pem
cafile /home/pi/claw/chain1.pem
keyfile /home/pi/claw/privkey1.pem
listener 8083
protocol websockets
certfile /home/pi/claw/cert1.pem
cafile /home/pi/claw/chain1.pem
keyfile /home/pi/claw/privkey1.pem
This is the error I'm getting when I run the .py file
pi#raspberrypi:~/claw $ python3 cac.py
Traceback (most recent call last):
File "/home/pi/claw/cac.py", line 102, in <module>
client.connect('clawclan.co.uk', 8083)
File "/home/pi/.local/lib/python3.9/site-packages/paho/mqtt/client.py", line 914, in connect
return self.reconnect()
File "/home/pi/.local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1073, in reconnect
sock.do_handshake()
File "/usr/lib/python3.9/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get issuer certificate (_ssl.c:1123)
If u want me to add anything, just ask, as I will be just checking for responses, for the rest of the day

OpenSSL SSL_get_verify_result returns error 18 for google.com

I'm writing my own C/C++ library to handle TLS streams. And I'm stuck on OpenSSL refusing to verify google.com's cert. This seems to only happen to google.com. openssl s_client -showcerts -connect google.com:443 can correctly verify google.com's certificate
depth=2 OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
verify return:1
depth=1 C = US, O = Google Trust Services, CN = GTS CA 1O1
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = *.google.com
verify return:1
---
Certificate chain
0 s:C = US, ST = California, L = Mountain View, O = Google LLC, CN = *.google.com
i:C = US, O = Google Trust Services, CN = GTS CA 1O1
But my code
...
SSL_CTX_set_default_verify_paths(ctx);
...
// create socket
SSL_set_verify(ssl, SSL_VERIFY_NONE, nullptr);
// handshake, etc...
...
SSL_get_verify_result(ssl); // always return X509_V_DEPTH_ZERO_SELF_SIGNED_CERT
Why the command successfully validates the certificate but my code can't?
Thanks.

Apache Kafka with SSL is working but SSL errors against localhost in kafka log (drives me nuts)

i have a Kafka problem, that drives me nuts.
We have a 4 nodes cluster. We used to work without SSL in our development stage. --> no problem.
For release, we switched on SSL for both listeners. --> Everything is working fine (application + kafka manager CMAK + Monitoring)
But we get one an error in our kafka broker serverlog in all environements (test, release, prod). Something is polling, and i don´t know what it is, or where to look:
It starts with:
[2020-10-16 10:50:27,866] INFO AdminClientConfig values:
bootstrap.servers = [127.0.0.1:10092]
client.dns.lookup = default
client.id =
connections.max.idle.ms = 300000
metadata.max.age.ms = 300000
metric.reporters = []
metrics.num.samples = 2
metrics.recording.level = INFO
metrics.sample.window.ms = 30000
receive.buffer.bytes = 65536
reconnect.backoff.max.ms = 1000
reconnect.backoff.ms = 50
request.timeout.ms = 120000
retries = 5
retry.backoff.ms = 100
sasl.client.callback.handler.class = null
sasl.jaas.config = null
sasl.kerberos.kinit.cmd = /usr/bin/kinit
sasl.kerberos.min.time.before.relogin = 60000
sasl.kerberos.service.name = null
sasl.kerberos.ticket.renew.jitter = 0.05
sasl.kerberos.ticket.renew.window.factor = 0.8
sasl.login.callback.handler.class = null
sasl.login.class = null
sasl.login.refresh.buffer.seconds = 300
sasl.login.refresh.min.period.seconds = 60
sasl.login.refresh.window.factor = 0.8
sasl.login.refresh.window.jitter = 0.05
sasl.mechanism = GSSAPI
security.protocol = PLAINTEXT
security.providers = null
send.buffer.bytes = 131072
ssl.cipher.suites = null
ssl.enabled.protocols = [TLSv1.2, TLSv1.1, TLSv1]
ssl.endpoint.identification.algorithm = https
ssl.key.password = null
ssl.keymanager.algorithm = SunX509
ssl.keystore.location = null
ssl.keystore.password = null
ssl.keystore.type = JKS
ssl.protocol = TLS
ssl.provider = null
ssl.secure.random.implementation = null
ssl.trustmanager.algorithm = PKIX
ssl.truststore.location = null
ssl.truststore.password = null
ssl.truststore.type = JKS
(org.apache.kafka.clients.admin.AdminClientConfig)
Then massive SSL error polling:
[2020-10-16 10:48:11,799] INFO [SocketServer brokerId=2] Failed authentication with /127.0.0.1 (SSL handshake failed) (org.apache.kafka.common.network.Selector)
[2020-10-16 10:48:13,141] INFO [SocketServer brokerId=2] Failed authentication with /127.0.0.1 (SSL handshake failed) (org.apache.kafka.common.network.Selector)
[2020-10-16 10:48:14,476] INFO [SocketServer brokerId=2] Failed authentication with /127.0.0.1 (SSL handshake failed) (org.apache.kafka.common.network.Selector)
Then Timeout:
[2020-10-16 10:48:20,890] INFO [AdminClient clientId=adminclient-25] Metadata update failed (org.apache.kafka.clients.admin.internals.AdminMetadataManager)
org.apache.kafka.common.errors.TimeoutException: Timed out waiting for a node assignment.
[2020-10-16 10:48:20,892] INFO [AdminClient clientId=adminclient-25] Metadata update failed (org.apache.kafka.clients.admin.internals.AdminMetadataManager)
org.apache.kafka.common.errors.TimeoutException: The AdminClient thread has exited.
After 1-2 minutes, it starts again.
Our Broker config:
# Maintained by Ansible
zookeeper.connect=ZOOKEEPER1:2181,ZOOKEEPER2:2181,ZOOKEEPER3:2181
log.dirs=KAFKKALOGDIR
broker.id=2
confluent.license.topic.replication.factor=3
log.segment.bytes=1073741824
socket.receive.buffer.bytes=102400
socket.send.buffer.bytes=102400
offsets.topic.replication.factor=3
num.network.threads=8
transaction.state.log.replication.factor=3
transaction.state.log.min.isr=2
confluent.support.metrics.enable=False
zookeeper.connection.timeout.ms=18000
num.io.threads=16
socket.request.max.bytes=104857600
log.retention.check.interval.ms=300000
group.initial.rebalance.delay.ms=0
confluent.metadata.topic.replication.factor=3
num.recovery.threads.per.data.dir=2
default.replication.factor=3
num.partitions=10
log.retention.hours=168
confluent.support.customer.id=anonymous
listener.security.protocol.map=INTERNAL:SSL,EXTERNAL:SSL
listeners=INTERNAL://:10091,EXTERNAL://:10092
advertised.listeners=INTERNAL://BROKERURL:10091,EXTERNAL://BROKERURL:10092
## Inter Broker Listener Configuration
inter.broker.listener.name=INTERNAL
listener.name.internal.ssl.truststore.location=LOCATION
listener.name.internal.ssl.truststore.password=PASSWORD
listener.name.internal.ssl.keystore.location=LOCATION
listener.name.internal.ssl.keystore.password=PASSWORD
listener.name.internal.ssl.key.password=PASSWORD
listener.name.external.ssl.truststore.location=LOCATION
listener.name.external.ssl.truststore.password=PASSWORD
listener.name.external.ssl.keystore.location=LOCATION
listener.name.external.ssl.keystore.password=PASSWORD
listener.name.external.ssl.key.password=PASSWORD
## Metrics Reporter Configuration
confluent.metrics.reporter.security.protocol=SSL
confluent.metrics.reporter.ssl.truststore.location=LOCATION
confluent.metrics.reporter.ssl.truststore.password=PASSWORD
What i did:
-disabled our monitoring agent (thought the agent is polling without SSL) --> nothing
-Add an additional localhost listener with PLAINTEXT 127.0.0.1 --> got massive problems with error "no matching leader for topic XY"
So, i don´t know how to continue - maybe someone has an idea
many thanks
Your AdminClientConfig specifies security.protocol=PLAINTEXT - that doesn't seem right given you want to enable SSL. https://kafka.apache.org/11/javadoc/org/apache/kafka/common/security/auth/SecurityProtocol.html shows the possible options for that variable.
You also have sasl.jaas.config=null, which I don't believe is correct either.
https://www.confluent.io/blog/apache-kafka-security-authorization-authentication-encryption/ provides a good walk-through of how to setup security with Kafka.
Edited to add (in response to followup question): AdminClient is a Java class which is instantiated from your connect-distributed.properties file. When you search your service logfile for AdminClient you will see something like this:
[2020-09-16 02:58:14,180] INFO AdminClientConfig values:
bootstrap.servers = [servernames-elided:9092]
client.dns.lookup = default
client.id =
connections.max.idle.ms = 300000
default.api.timeout.ms = 60000
metadata.max.age.ms = 300000
metric.reporters = []
metrics.num.samples = 2
metrics.recording.level = INFO
metrics.sample.window.ms = 30000
receive.buffer.bytes = 65536
reconnect.backoff.max.ms = 1000
reconnect.backoff.ms = 50
request.timeout.ms = 20000
retries = 2147483647
retry.backoff.ms = 500
sasl.client.callback.handler.class = null
sasl.jaas.config = [hidden]
sasl.kerberos.kinit.cmd = /usr/bin/kinit
sasl.kerberos.min.time.before.relogin = 60000
sasl.kerberos.service.name = null
sasl.kerberos.ticket.renew.jitter = 0.05
sasl.kerberos.ticket.renew.window.factor = 0.8
sasl.login.callback.handler.class = null
sasl.login.class = null
sasl.login.refresh.buffer.seconds = 300
sasl.login.refresh.min.period.seconds = 60
sasl.login.refresh.window.factor = 0.8
sasl.login.refresh.window.jitter = 0.05
sasl.mechanism = PLAIN
security.protocol = SASL_SSL
security.providers = null
send.buffer.bytes = 131072
ssl.cipher.suites = null
ssl.enabled.protocols = [TLSv1.2, TLSv1.1, TLSv1]
ssl.endpoint.identification.algorithm = https
ssl.key.password = null
ssl.keymanager.algorithm = SunX509
ssl.keystore.location = null
ssl.keystore.password = null
ssl.keystore.type = JKS
ssl.protocol = TLS
ssl.provider = null
ssl.secure.random.implementation = null
ssl.trustmanager.algorithm = PKIX
ssl.truststore.location = null
ssl.truststore.password = null
ssl.truststore.type = JKS
(org.apache.kafka.clients.admin.AdminClientConfig:347)
Note that sasl.jaas.config = [hidden] - that's because the username and password for accessing the cluster are stored in the properties file directly, like so:
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username=\"someUsernameThisIs\" password=\"notMyRealPassword\";
Note that the escaping for the doublequotes is necessary for the configuration parser.

error on line 1 of config file 'v3.ext' when generating a self-signed ceertificate

I'm attempting to create a self signed SSL cert and when I go to generate the SSL cert I got the following error:
error on line 1 of config file 'v3.ext'
The command I'm using to generate the cert is:
openssl x509 -req -sha256 -extfile v3.ext -days 365 -in server.csr -signkey server.key -out server.crt
And my v3.ext file is as follows:
$ cat v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = #alt_names
 
[alt_names]
DNS.1 = <common_name>
$
So I guess my question is what's wrong with my v3.ext. The guide I'm following is here:
https://ksearch.wordpress.com/2017/08/22/generate-and-import-a-self-signed-ssl-certificate-on-mac-osx-sierra/
Your conf file looks odd to me. The format I’ve always used for self signed or pki signed certs is along these lines:
[ req ]
default_bits = 4096
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = GB
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = England
localityName = Locality Name (eg, city)
localityName_default = Brighton
organizationName = Organization Name (eg, company)
organizationName_default = Hallmarkdesign
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
commonName_default = localhost
[ req_ext ]
subjectAltName = #alt_names
[alt_names]
DNS.1 = your-website.dev
DNS.2 = another-website.dev

SubjectAltName is not getting added in the CSR

Does the CSR generated contains the SubjectAltName I have configured the openssl.cnf file to support extensions and when i dump the CSR i can see subject is available not the SubjectAltName
This is how CSR is generated
openssl req -new -sha256 -key ./private.key -out ./cert.csr -config ./openssl.cnf
and to view information of the CSR i used
openssl req -noout -text -in cert.csr
The output is
bash:/home/ubuntu# openssl req -noout -text -in cert.csr
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=sd, ST=sd, O=Internet Widgits Pty Ltd
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (3072 bit)
Modulus:
00:ae:6f:5d:75:f6:7a:af:2f:af:2b:39:dc:f7:b6:
d0:61:3d:49:f7:50:a2:a6:d1:99:d8:ce:a6:24:87:
1f:4e:ad:02:58:c9:34:12:78:22:f3:99:29:69:c6:
66:78:06:4e:bc:f6:e1:f6:f6:bb:f6:52:97:a4:14:
d7:9d:51:03:07:20:5d:10:88:35:db:32:7a:14:9c:
ea:e3:55:02:7a:20:bc:3c:24:c5:db:e8:82:12:c5:
16:78:cb:fa:0f:79:02:30:f3:23:c1:6b:55:e1:c7:
06:78:30:ac:4c:63:6e:74:5d:28:58:69:20:92:90:
a2:3c:d3:ad:20:c5:64:e3:22:4c:8a:e0:ad:04:60:
2d:c0:3f:d9:05:84:9b:53:1f:17:ac:9e:49:48:68:
08:c6:1d:c5:fe:df:28:64:b1:6d:15:f1:90:c0:4f:
fe:52:c1:8e:2f:d6:20:81:84:db:ed:43:6b:a7:8c:
37:58:a1:7a:fb:a9:4a:80:be:f0:27:d4:4b:13:ac:
56:74:6e:5d:0d:a0:09:8d:96:89:92:8f:b0:af:07:
d8:92:6b:ea:09:15:f6:0c:68:24:30:33:7f:a3:d9:
e6:45:1b:95:aa:79:63:29:60:b2:2b:19:ed:ee:aa:
c7:5f:ce:eb:3c:62:1d:79:6a:20:ec:16:38:3b:d4:
06:04:db:7c:16:da:1b:cb:5c:67:ff:10:69:03:3e:
cd:ee:94:50:45:f4:5c:bb:3b:61:41:fb:00:56:18:
8c:76:09:37:b0:40:53:85:12:8e:36:a9:58:0f:4d:
72:82:a4:79:85:27:2f:36:1e:21:53:ba:f4:23:75:
f1:f6:8b:24:30:d2:e7:47:77:f3:82:6c:73:8d:d4:
d4:ad:af:91:a7:4d:e5:66:38:6c:e1:d1:5f:cb:b8:
59:7f:26:49:80:8f:2f:f6:24:02:4d:92:b3:e4:bd:
ef:e7:69:02:7c:a5:cf:cc:39:ca:c8:42:6c:5f:3e:
77:9c:c1:9a:7b:e4:61:8c:20:eb
Exponent: 65537 (0x10001)
Attributes:
a0:00
Signature Algorithm: sha256WithRSAEncryption
0c:ef:3a:db:29:88:f6:c0:ce:f2:67:ba:61:35:3e:5f:6a:5a:
2b:85:5f:e1:48:60:60:cb:96:77:8d:30:3b:fe:34:02:4c:04:
78:a0:d3:ec:df:6e:43:02:92:ae:5c:6f:3c:60:fa:b7:36:d7:
bc:d2:4b:1b:5d:61:67:d1:09:3d:6c:ee:56:81:cd:14:be:c9:
33:b9:32:c7:eb:1d:59:f6:5c:98:6c:ae:92:27:94:15:d1:74:
0e:55:8f:2f:9c:6e:9f:85:80:c7:b6:d7:5b:a1:41:82:f4:a8:
73:08:de:45:5f:76:23:60:71:81:f4:ed:e0:cf:f1:14:d4:1c:
a6:c5:f9:a4:b6:e5:d6:01:01:7c:6a:3d:aa:a2:87:25:7c:c5:
e2:d2:0a:12:83:33:65:71:dd:43:7e:35:50:f9:99:77:72:8c:
56:5a:d7:37:cb:a1:ea:87:a9:5f:a9:9d:c7:ae:35:59:85:02:
3e:bd:ae:5e:c7:7a:95:31:bf:b2:0d:c8:0c:d9:45:6e:29:02:
2a:6b:cd:5e:73:b9:31:7a:3e:95:c1:28:f7:0b:f5:26:36:eb:
f4:ac:cc:1d:ef:01:ee:fd:a1:8b:eb:bc:f4:46:9d:42:1e:6f:
81:2f:7a:fc:90:9e:20:24:c1:79:e9:85:04:cb:23:f4:8a:8e:
70:33:48:50:dd:0a:30:00:bf:71:7e:15:31:23:dc:a7:b2:92:
dd:37:d9:83:b5:1b:3c:84:17:ce:49:17:04:2b:6d:0a:7c:51:
fa:e8:d6:97:a8:c1:96:6c:eb:c6:f1:2f:69:27:b8:c2:75:fc:
f7:5b:d2:b8:bf:e6:d9:da:6d:3f:de:da:27:46:4d:3f:6a:b0:
f8:b9:1a:cf:3c:29:67:7f:c4:be:bd:c1:37:db:cd:ae:d5:27:
d3:2d:bc:71:ed:f1:d6:b5:bd:9b:ef:8b:08:c4:d2:c4:ef:ca:
61:d2:c0:19:04:26:07:02:d3:39:56:57:05:48:a9:3d:d9:40:
f6:2f:67:df:dd:55
My openssl.cnf file setting alt_names enabeled
HOME = .
RANDFILE = $ENV::HOME/.rnd
oid_section = new_oids
[ new_oids ]
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = ./demoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several ctificates with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
RANDFILE = $dir/private/.rand # private random number file
x509_extensions = usr_cert # The extentions to add to the cert
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
# Extension copying option: use with caution.
copy_extensions = copy
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy = policy_match
# For the CA policy
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
# Passwords for private keys if not present they will be prompted for
# input_password = secret
# output_password = secret
# This sets a mask for permitted string types. There are several options.
# default: PrintableString, T61String, BMPString.
# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
# utf8only: only UTF8Strings (PKIX recommendation after 2004).
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
# MASK:XXXX a literal mask value.
# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
string_mask = utf8only
# req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd
# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd
organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
# SET-ex3 = SET extension number 3
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ usr_cert ]
# These extensions are added when 'ca' signs a request.
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
subjectAltName = #alternate_names
keyUsage = digitalSignature, keyEncipherment
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
# This is what PKIX recommends but some broken software chokes on critical
# extensions.
#basicConstraints = critical,CA:true
# So we do this instead.
basicConstraints = CA:true
[ crl_ext ]
# CRL extensions.
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
# issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always
[ proxy_cert_ext ]
# These extensions should be added when creating a proxy certificate
# This goes against PKIX guidelines but some CAs do it and some software
# requires this to avoid interpreting an end user certificate as a CA.
basicConstraints=CA:FALSE
nsComment = "OpenSSL Generated Certificate"
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
[ tsa ]
default_tsa = tsa_config1 # the default TSA section
[ tsa_config1 ]
# These are used by the TSA reply generation only.
dir = ./demoCA # TSA root directory
serial = $dir/tsaserial # The current serial number (mandatory)
crypto_device = builtin # OpenSSL engine to use for signing
signer_cert = $dir/tsacert.pem # The TSA signing certificate
# (optional)
certs = $dir/cacert.pem # Certificate chain to include in reply
# (optional)
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
default_policy = tsa_policy1 # Policy if request did not specify it
# (optional)
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
digests = md5, sha1 # Acceptable message digests (mandatory)
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
clock_precision_digits = 0 # number of digits after dot. (optional)
ordering = yes # Is ordering defined for timestamps?
# (optional, default: no)
tsa_name = yes # Must the TSA name be included in the reply?
# (optional, default: no)
ess_cert_id_chain = no # Must the ESS cert id chain be included?
# (optional, default: no)
[ alternate_names ]
DNS.1 = test.xyz.com
To make this work, you need to make a couple of changes to your config. First, you need to uncomment the req_extensions value within the req section, i.e.:
# req_extensions = v3_req # The extensions to add to a certificate request
Needs to become:
req_extensions = v3_req # The extensions to add to a certificate request
Then, in that v3_req section:
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
You need to also add that subjectAltName (just like you have in your v3_ca section), so:
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = #alternate_names
You may also need to duplicate the subjectKeyIdentifier = hash value from the v3_ca section that v3_req section as well.
The key here is to realize that the SubjectAltName (SAN) extension is treated, by the openssl csr tool, as a request extension, rather than an x509 extension. Confusing, I know.
To wrap up, here's the configuration I used, based on the above, with all of the settings unrelated to openssl csr stripped out:
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
default_md = sha256
distinguished_name = req_distinguished_name
attributes = req_attributes
string_mask = utf8only
req_extensions = v3_req
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = AU
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Internet Widgits Pty Ltd
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
subjectAltName = #alternate_names
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
subjectAltName = #alternate_names
keyUsage = digitalSignature, keyEncipherment
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
[ alternate_names ]
DNS.1 = test.xyz.com