Hitchhiker’s Guide To Certificates
Wolfgang Jung (post@wolfgang-jung.net)
whoami
- einer der Micromata Gründer
- arbeite derzeit bei Polyas
- Schwerpunkte: Security, Infrastruktur, Linux, Scala
Sicherheit im Netz
- Verschlüsseln ist gut
- Aber: Woher den Schlüssel nehmen
- Symmetrisch
- Public Key/Private Key
MitM
Vertrauen aka "Wessen Schlüssel ist das?"
DANE
DNS-based Authentication of Named Entities
CAs
Certification Authorities
- Externer Dienstleister, der Identität zu Public Key prüft
- Erzeugt ein Zertifikat für den Public Key
- Begrenzte Lebensdauer (aka Gelddruckmaschine)
- Begrenzter Einsatzzweck (aka Gelddruckmaschine)
- EV Zertifikate (aka Gelddruckmaschine)
- Kann Zertifikate zurückrufen (aka
Pech
gehabt)
Broken by design, but
- Jede CA ist immer vollständig gültig
- Certification Transparency (CT):
- Wenigstens grobe Verstöße werden sichtbar
- CAA (setzt DNSSEC voraus) begrenzt die Aussteller
(Selbstverpflichtung)
Was ist denn nun ein Zertifikat?
- Basiert auf dem Public-Key des Inhabers
- Niemand außer des Inhabers sollte den Private-Key kennen
- Kann sowohl Client als auch Server betreffen!
- Distinguished Name des Ausstellers
- Distinguished Name des Inhabers
- Gültig von-bis
- Seriennummer (vergeben vom Aussteller)
- Public Key Verfahren (z.B. RSA)
- Public Key des Inhabers
- Signaturverfahren (z.B. sha256WithRSAEncryption)
- Erweiterungen: KeyUsage, Constraints, SAN, Revocation
Lists, OCSP Responder, SCT (Signed Certificate Timestamp)
Woher weiß die CA, für wen sie ein Zertifikat ausstellt?
- Lösung CSR (Certificate Signing request)
- Enthält den X500 Namen des Inhabers
- Public Key Verfahren (z.B. RSA)
- Public Key des Inhabers
- Gewünschte Erweiterungen: SAN?, KeyUsage, etc.
- Signaturverfahren (z.B. sha256WithRSAEncryption)
- Signatur über diese Daten (via Private Key des Inhabers)
- Vorteil: CA kann Besitz des Private Keys prüfen, ohne ihn zu kennen
Intermediate CA
- Besondere Form der CA: wurde von CA signiert
- Vorteil: Nur Root-CA muss bekannt gemacht werden
- Intermediate CA kann/muss vom Server mitgesendet werden, da üblicherweise nicht auf
dem Client bekannt
- Root-CA kann auf Airgap bzw. Hardware Modul liegen
- Intermediate-CA kann eingeschränkt werden z.B. nur E-Mail Zertifikate können
ausgestellt werden
Wie erzeugt man nun Keys, CSRs etc? MacOS
- Klicki-Bunti: Schlüsselbund -> Zertifikatsassistent
Windows
- certmgr.msc
Schlüssel erzeugen (RSA)
> openssl genrsa -out foo.key 4096
Generating RSA private key, 4096 bit long modulus
.........................................................................++
..................++
e is 65537 (0x010001)
Zertifikatsanforderung (CSR) erzeugen:
> openssl req -new -sha256 -key foo.key -out foo.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]:DE
State or Province Name (full name) [Some-State]:Hesse
Locality Name (eg, city) []:Kassel
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Polyas GmbH
Organizational Unit Name (eg, section) []:Test
Common Name (e.g. server FQDN or YOUR name) []:localhost
...
CSR kann mittels openssl req -text -in foo.csr
angeschaut werden.
CSR in Skript erzeugen
req.conf:
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = DE
ST = Hesse
L = Kassel
O = Polyas GmbH
OU = Tests
CN = localhost
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1=foobar
IP.1=1.2.3.4
openssl req -new -sha256 -key foo.key -out foo.csr -config req.conf
Formate für Zertifikate/Keys
Andere Formate
- PKCS#8: Enthält nur einen private Key
openssl pkcs8 -in foo.key \
-nocrypt -out foo.p8
- PKCS#12: Enthält private Key und Zertifikatskette
openssl pkcs12 -in foo.key \
-CAfile chain.pem \
-nodes -chain \
-out identity.p12
- "Raw" Public Key
openssl x509 -pubkey -noout -in foo.crt > pubkey.pem
Self signed certificate
Einfachste Form des Zertifikats:
openssl req -newkey rsa:4096 -nodes -keyout foo.key -x509 -days 365 -out foo.crt
Kurzform von:
openssl genrsa -out foo.key 4096
openssl req -new -sha256 -key foo.key -out foo.csr
openssl x509 -req -sha256 -days 365 -in foo.csr -signkey foo.key -out foo.crt
Zertifikat prüfen
openssl x509 -text -noout -in foo.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
9e:05:fc:de:8c:b9:4d:01
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = DE, ST = Hesse, L = Kassel, O = Polyas GmbH, OU = foo, CN = foo
Validity
Not Before: Aug 13 23:43:22 2018 GMT
Not After : Aug 20 23:43:22 2018 GMT
Subject: C = DE, ST = Hesse, L = Kassel, O = Polyas GmbH, OU = foo, CN = foo
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:d0:24:19:48:ff:4b:61:2c:d3:42:bb:09:f8:6c:
...
34:c1:8b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage:
Digital Signature, Key Encipherment, Data Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Alternative Name:
DNS:foo
Signature Algorithm: sha256WithRSAEncryption
bb:40:64:1b:1d:a9:09:48:d6:9e:90:34:c2:66:2d:06:5b:0c:
...
c2:9c:25:21:a7:f7:9c:27
Eigene Root-CA?
- Auch nur ein self-signed Zertifikat
> openssl req -x509 -new -extensions v3_ca \
-subj "/C=DE/ST=Hesse/L=Kassel/O=POLYAS GmbH/OU=CA/CN=POLYAS CA" \
-key selfSignCA.key -days 10000 -out selfSignCA.crt
> openssl pkcs12 -export -inkey selfSignCA.key -in selfSignCA.crt \
-out selfSignCA.p12
- üblicherweise dem Betriebssystem nicht bekannt
- Installation in Zertifikatsspeicher
- Oder: Aktivierung auf Applikationsebene z.B. play
play.ws.ssl {
trustManager = {
stores = [
{ type = "PEM", path = "conf/selfSignCA.crt" }
{ path: ${java.home}/lib/security/cacerts }
]
}
}
Zertifikate eines Servers testen
> openssl s_client -connect google.de:443 -servername google.de -showcerts
CONNECTED(00000005)
depth=2 OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
verify return:1
depth=1 C = US, O = Google Trust Services, CN = Google Internet Authority G3
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = *.google.de
verify return:1
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=*.google.de
i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
-----BEGIN CERTIFICATE-----
MIIEhzCCA2+gAwIBAgIITY5Z/D6ZRaQwDQYJKoZIhvcNAQELBQAwVDELMAkGA1UE
...
JGYmyIvgUsLO5Xo=
-----END CERTIFICATE-----
1 s:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
i:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
-----BEGIN CERTIFICATE-----
MIIEXDCCA0SgAwIBAgINAeOpMBz8cgY4P5pTHTANBgkqhkiG9w0BAQsFADBMMSAw
...
c7o835DLAFshEWfC7TIe3g==
-----END CERTIFICATE-----
---
Server certificate
subject=/C=US/ST=California/L=Mountain View/O=Google LLC/CN=*.google.de
issuer=/C=US/O=Google Trust Services/CN=Google Internet Authority G3
---
Serverzertifikate lokal testen
> openssl s_server -accept 9992 \
-key w.jung@wolfgang-jung.net.key \
-cert w.jung@wolfgang-jung.net.crt \
-CAfile IdeasInLogicCA/selfSignCA.crt -WWW
> openssl s_client -connect pong:9992 -CAfile IdeasInLogicCA/selfSignCA.crt
Using default temp DH parameters
ACCEPT
ACCEPT
140736242467776:error:1417C0C7:SSL routines:tls_process_client_certificate:peer did not return a certificate:ssl/statem/statem_srvr.c:2882:
Client-Auth
nginx.conf:
...
log_format combined_sslclient '$remote_addr - $remote_user [$time_local] "$request" \
$status $body_bytes_sent "$http_referer" "$http_user_agent" \
"$ssl_client_s_dn($ssl_client_serial)"';
...
site.conf:
server {
ssl_certificate /etc/letsencrypt/live/wolfgang-jung.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wolfgang-jung.net/privkey.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/wolfgang-jung.net/fullchain.pem;
ssl_client_certificate /etc/nginx/client_certs/ca.crt;
ssl_verify_client optional;
listen 443 ssl http2;
access_log /var/log/nginx/wolfgang-jung.net-access.log combined_sslclient;
...
}
Client-Auth
> openssl s_client -connect wolfgang-jung.net:443 -servername wolfgang-jung.net \
-key w.jung@wolfgang-jung.net.key -cert w.jung@wolfgang-jung.net.crt \
-CAfile IdeasInLogicCA/selfSignCA.crt
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = wolfgang-jung.net
verify return:1
---
Certificate chain
0 s:/CN=wolfgang-jung.net
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGJjCCBQ6gAwIBAgISA8Uwxad/1gkqvfyWBVmRPzWbMA0GCSqGSIb3DQEBCwUA
...
FvDzUtL/Jc35A9cmdxth3ox/tdsxOMZZRfwDXEm1ubvSGW1oAP+cf36D
-----END CERTIFICATE-----
subject=/CN=wolfgang-jung.net
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
Acceptable client certificate CA names
/C=DE/ST=Hesse/L=Kassel/O=Ideas In Logic GbR/OU=Local CA/CN=Ideas in Logic internal CA
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Shared Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Peer signing digest: SHA512
Server Temp Key: ECDH, P-384, 384 bits
---
SSL handshake has read 5212 bytes and written 4077 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
access.log:
87.191.133.92 - - [15/Aug/2018:13:40:14 +0200] "GET / HTTP/2.0" 304 0 "-" \
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) ...." \
"CN=w.jung@wolfgang-jung.net,OU=Wolfgang Jung,O=Wolfgang Jung,L=Kassel,ST=Hesse,C=DE(A179C4773E6065E0)"
Mutual SSL lokal testen
> openssl s_server -accept 9992 -Verify 1 \
-key w.jung@wolfgang-jung.net.key \
-cert w.jung@wolfgang-jung.net.crt \
-CAfile IdeasInLogicCA/selfSignCA.crt -WWW
> openssl s_client -connect pong:9992 -key w.jung@wolfgang-jung.net.key \
-cert w.jung@wolfgang-jung.net.crt -CAfile IdeasInLogicCA/selfSignCA.crt
Using default temp DH parameters
ACCEPT
depth=1 C = DE, ST = Hesse, L = Kassel, O = Ideas In Logic GbR, OU = Local CA, CN = Ideas in Logic internal CA
verify return:1
depth=0 C = DE, ST = Hesse, L = Kassel, O = Wolfgang Jung, OU = Wolfgang Jung, CN = w.jung@wolfgang-jung.net
verify return:1
> openssl s_client -connect pong:9992 -CAfile IdeasInLogicCA/selfSignCA.crt
ACCEPT
140736242467776:error:1417C0C7:SSL routines:tls_process_client_certificate:peer did not return a certificate:ssl/statem/statem_srvr.c:2882:
openssl was noch?
- Prüfsummen / Signaturen:
> openssl dgst -r -sha384 file
f861caf733f5dab899c6903a7f1aedd12bd4e4dde7c76e8afcf9e07cd984579dd668a60c9defee0a6490b3294972681f *file
> openssl dgst -r -sha384 -hmac MySecretKey file
b398e60376030fbe3f3998b9495ac21e32238ec85ed8158465adb001c9a8defa3bc2641feb8e67703f3b2f90f13990dc *file
> openssl dgst -r -sha384 -sign foo.key -out sig file
> openssl dgst -r -sha384 -verify pubkey.pem -signature sig file
Verified OK
- Verschlüsselung:
> openssl aes-128-cbc -k SharedKey -e -a < file
U2FsdGVkX19wedpEWuvRd1kwUnrC6DCK5qkRqeuxffk=
> openssl aes-128-cbc -k SharedKey -d -a
Mein Text
- Zufall:
> openssl rand -hex 16
8ccd23881e30f1115b84c633c557f6c2
Fragen?