23
Tags:
php
sikkerhed
krypto
x509
certifikater
Skrevet af
Bruger #2695
@ 07.05.2012
Introduktion
Denne femte artikel behandler nogle problemer, som vi introducerede med de asymmetriske krypterings algoritmer. Det bliver lidt teoretisk, men hæng på...jeg holder mig til de mest nødvendige funktioner.
I tredje artikel så vi på asymmetrisk kryptografi og på, hvordan det løste problemet med nøgleudveksling. Alice og Bob kan udveksle krypteringsnøgler, og selvom Eve lytter med, så kan hun ikke deltage i kommunikationen.
Men det er et meget urealistisk eksempel. Normalt vil Alice og Bob ikke kunne kommunikere så direkte ansigt til ansigt.
Alice og Bob kunne arbejde på hver deres side af jordkloden, men hvordan udveksler de så nøgler ?
Her kommer den uærlige postmand Mallory ind i billedet:
1) Bob og Alice vil kommunikere hemmeligt.
2) Bob give Mallory sin offentlige nøgle og beder ham om at levere den videre til Alice
3) Mallory tager over til Alice, men giver hende istedet sin egen offentlige nøgle
4) Alice krypterer en tilfældig hemmelig nøgle med, hvad hun tror er Bobs offentlige nøgle og giver den til Mallory
5) Mallory dekrypterer nøglen og rekrypterer den med Bobs nøgle
6) Mallory tager over til Bob og giver ham den nøgle, som er krypteret med hans offentlige nøgle
7) Alice og Bob kommunikerer nu ved hjælp af en delt nøgle, men Mallory kender den også
Dette kaldes et Man In The Middle (MITM) angreb, og er meget nemt at udføre under de rette omstændigheder.
I den virkelige verden vil Mallory nok være en router, som en hacker har overtaget, eller som administreres af en mindre pålidelig system administrator hos en internet udbyder.
Selv hvis Alice og Bob kunne mødes ansigt til ansigt, så kender de måske ikke hinanden. Hvis I møder en tilfældig person på gaden, som hævder, at han er mig, hvilken garanti har I så for, at det faktisk ér mig ?
Hvis han hiver et pas frem, så har I en rimelig sikkerhed. Et pas er svært at forfalskne, og det er udstedt af en myndighed, som vi bør kunne stole på. Vi kan bruge noget lignende i krypto verdenen.
Mød Trent
Trent er endnu en fiktiv person i historierne om kryptografi, og han er en myndighedsperson, som alle kender og stoler på, og alle har hans offentlige nøgle tatoveret på brystet. Nu sker følgende:
1) Alice og Bob vil kommunikere hemmeligt
2) Bob går til Trent og beder ham om at attestere, at hans nøgle faktisk tilhører ham
3) Trent tjekker Bob på kryds og tværs og signerer Bobs offentlige nøgle sammen med et dokument med Bobs identitet (navn, e-mail, osv.) og giver dette til Bob
4) Bob giver denne signatur og andre data til Mallory og beder ham om at levere det til Alice
5) Mallory leverer dataene til Alice
6) Alice tjekker, at signaturen faktisk tilhører Trent og at dataene matcher Trents signatur
7) Alice genererer en tilfældig nøgle som krypteres med Bobs offentlige nøgle og giver den til Mallory
8) Mallory leverer nøglen til Bob
9) Bob dekrypterer og kommunikerer nu med Alice
Mallory kan ikke længere substituere Bobs nøgle med sin egen, for Mallorys nøgle er ikke signeret af Trent, og selv hvis den var, så var Bobs identitet ikke signeret sammen med Mallorys nøgle. Det ville Trent aldrig gøre.
Certifikater
Der er to ting at bide mærke i i ovenstående historie, og den ene er, at vi skal binde vores identitet sammen med vores nøgle. Den anden er, at vi skal have vores identitet og nøgle signeret af en person, som alle kender og stoler på. Resultatet er et certifikat. Et certifikat er et dokument, som indeholder informationer om en person eller en server samt dennes offentlige nøgle. Certifikatet er derudover signeret af en autoritet, som har ansvaret for at verificere, at personen er den, som han siger (eller at serveren tilhører organisationen, som certifikatet udstedes til).
Første skridt er at sammenkæde vores identitet og offentlige nøgle i, hvad der kaldes et "certificate signing request" (herefter kaldet CSR). Det kan vi gøre med følgende script:
- <?php
- //Filename: certificate_signing_requiest.php
- if (count($argv) < 9) {
- echo "Usage: php " . $argv[0] . " <private key> <password> <name> <country> <locality> <organization> <state> <email>\n";
- } else {
- //Dette array indeholder oplysninger om personen eller serveren
- //som skal bruge certifikatet
- $dn = array(
- 'commonName' => $argv[3], //Dette er enten personens navn eller serverens hostname
- 'countryName' => $argv[4], //Dette er en landekode, f.eks. 'DK'
- 'localityName' => $argv[5], //Brug et bynavn her
- 'organizationName' => $argv[6], //Navn på firma eller organisation
- 'stateOrProvinceName' => $argv[7], //Stat/provins. Jeg plejer at bruge 'Jylland'
- 'emailAddress' => $argv[8] //Ja...hvad kan det mon være ?
- );
-
- //Indlæs vores private nøgle
- if ($private_key = openssl_pkey_get_private(file_get_contents($argv[1]), $argv[2])) {
- //Generer et CSR ud fra vores 'dn' array og private nøgle
- if ($csr = openssl_csr_new($dn, $private_key)) {
- //Eksporter til en variabel
- if (openssl_csr_export($csr, $csr_exportable)) {
- //Udskriv
- echo $csr_exportable;
- }
- }
- }
- }
- ?>
Nu sagde jeg tidligere, at det var vores offentlige nøgle, som skulle bruges i certifikatet, men hvorfor bruger vi så den private nøgle ?
Den offentlige nøgle kan udledes fra den private, og udover vores informationer og offentlige nøgle, så skal hele skidtet signeres med vores private nøgle. Den private nøgle bliver ikke lagt ind i certifikatet.
'$dn' arrayet indeholder vores oplysninger, og disse kaldes samlet set for et "distinguished name".
Vi prøver:
$ php certificate_signing_request.php
Usage: php certificate_signing_request.php <private key> <password> <name> <country> <locality> <organization> <state> <email>
$ php certificate_signing_request.php my_key 'very secret' 'Robert Chris Bang Larsen' 'DK' 'Aalborg' 'The Playground' 'Jylland' 'robert@the-playground.dk' > csr.pem
$ cat csr.pem
-----BEGIN CERTIFICATE REQUEST-----
MIIB1zCCAUACAQAwgZYxITAfBgNVBAMTGFJvYmVydCBDaHJpcyBCYW5nIExhcnNl
bjELMAkGA1UEBhMCREsxEDAOBgNVBAcTB0FhbGJvcmcxFzAVBgNVBAoTDlRoZSBQ
bGF5Z3JvdW5kMRAwDgYDVQQIEwdKeWxsYW5kMScwJQYJKoZIhvcNAQkBFhhyb2Jl
cnRAdGhlLXBsYXlncm91bmQuZGswgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
AMvVWwmVLQ3CYbbRIgdE3Wl1lvBsY9ciEaWcRW8HQyHkZwnUMWLG15dUap/qOlJK
XrjveaU67HLAB4U+9tzK4ebSnW94/EPSCvzPbsOL8WQt2Nr11lqbb+NozISrrTpX
851CdsSCVKUQFz+7aQWvpo2iNVdBhz62tbqxeK57pBAxAgMBAAGgADANBgkqhkiG
9w0BAQQFAAOBgQAcqzOvRjjkudVHC1I8beKafDe/BDgrp7ODs+ZCZiPsIOKNMDns
WoSKxrP264fmC09ZXSrInlz8Z1XHySiIU4mQhFfTH0a8UPedZoNWEXyma4f7W9e3
GYDC/oYtm6PRTkYl0e6I/dMqFywUiIvOMsKd75bMpg7lMXlwEizy4Zajdw==
-----END CERTIFICATE REQUEST-----
Nu har vi halvdelen af certifikatet, så nu mangler vi bare én, som kan signere det. Vi mangler Trent!
Certificate Authority
I den virkelige verden varetages rollen som Trent af såkaldte Certificate Authorities (herefter kaldet CAs).
Et CA er et firma eller organisation, som har retten til at signere CSRer og dermed udstede fuldgyldige certifikater. De skal til gengæld gøre alt hvad de kan, for at verificere, at den, som de udsteder certifikater til har retten til certifikatet.
Derudover bliver de et yndet hackermål, for hvis man kan få fat på et CAs private nøgle, så kan man udstede sine egne certifikater, som alle vil stole på, og man kan dermed udgive sig for at være hvem som helst...f.eks. Microsofts Update server.
Vi har alle CAs certifikater på vores maskiner (ikke tatoveret på brystet, men tæt på). På min Ubuntu server ligger de i '/etc/ssl/certs', men det er heller ikke unormalt, at certifikaterne er compilet ind i softwaren, som skal bruge dem.
Når vi skal tjekke, om et modtaget certifikat er signeret af én vi stoler på, så skal vi altså bare tjekke, om signaturen matcher én af de mange certifikater, som vi allerede har liggende.
Men nu gider vi ikke i denne artikel at gå ud og betale for at få udstedt et certifikat. Det er også en lang og bureaukratisk proces, men vi kan gøre noget andet. Vi kan signere certifikatet selv.
Self signed certificate
Hvad betyder det, at vi selv signerer vores certifikat ?
Det betyder, at jeg står inde for, at jeg er mig. Det er temmelig usikkert, men det kan bruges til to ting, nemlig testing og til at opbygge sin egen CA.
Hvis certifikaterne under '/etc/ssl/certs' er ægte certifikater, hvem er de så signeret af ?
De er ALLE self signed certificates, men nogen har gået igennem ild og vand for at sikre at de alligevel er ægte. Det må vi stole på. Vi kan selv signere vores eget certifikat, men vi kan nok ikke få det distribueret til hele verden, men det er måske heller ikke nødvendigt.
Koncekvensen, af at signere selv, er, at standard software pakker som f.eks. web browsere vil komme med en advarsel, hvis den støder på det, og derfor bør man ikke bruge self signed certificates på sit offentligt tilgængelige website, men det kan bruges lokalt til at teste med.
Derudover kan man opbygge sin egen CA til et mindre lukket netværk. Hvis man f.eks. har et VPN, hvor kun få udvalgte skal have adgang, så kan man give dem et self signed certificate som har signeret serverns certifikat, og så kan det være godt nok.
Men vi skal altså have et script, som kan bruges til at signere et CSR med et certifikat. Det kan vi med følgende:
- <?php
- //Filename: certificate_sign.php
- if (count($argv) < 5) {
- //Det sidste argument er valgfrit. Undlades det laver vi et self signed certificate
- echo "Usage: php " . $argv[0] . " <csr> <private key> <password> <days> [signing certificate]\n";
- } else {
- //Indlæs den private nøgle som skal bruges til at signere certifikatet
- if ($private_key = openssl_pkey_get_private(file_get_contents($argv[2]), $argv[3])) {
- //Indlæs vores CSR
- if ($csr = file_get_contents($argv[1])) {
- //Hvis denne er null laver vi et self signed certificate
- $signing_certificate = null;
- //Vi ønsker muligheden for at override visse parametre
- $config = array();
- //Enten har vi kun fem argumenter eller også skal vi kunne indlæse et certifikat, som skal bruges i signeringen
- if (count($argv) === 5 || $signing_certificate = openssl_x509_read(file_get_contents($argv[5]))) {
- //Hvis vi IKKE laver et self signed certificate
- if ($signing_certificate !== null) {
- //...så laver vi et "bruger" certifikat
- $config['x509_extensions'] = 'usr_cert';
- }
- //Signer
- if ($signed = openssl_csr_sign($csr, $signing_certificate, $private_key, $argv[4], $config)) {
- //Eksporter til en variabel
- if (openssl_x509_export($signed, $exportable)) {
- //Udskriv
- echo $exportable;
- }
- }
- }
- }
- }
- }
- ?>
Det endelige certifikat får en udløbsdato, som vi specificerer som det antal dage, fra dags dato, som certifikatet skal være gyldigt.
Specificerer vi et eksisterende certifikat som femte argument til scriptet, så bruges det til at signere med. Undlades det, laver vi et self signed certificate, som kan bruges til testing eller som CA i et lukket system.
OpenSSL bruger en konfigurationsfil til at udfylde visse dele af certifikatet. På min Ubuntu maskine er denne konfigurations fil /etc/ssl/openssl.cnf. Pr. default når man signerer et certifikat, så får man et CA certifikat, og det ønsker vi ikke, at alle har. Kun hvis vi laver et self signed certificate, så hvis der specificeres et certifikat til at signere med, så overrider vi hvilke X509 udviddelser, der skal bruges, i vores tilfælde 'usr_cert'. Denne skal være i konfigurationsfilen, og hvis ikke den er det, så virker det ikke. Kig i din konfigurationsfil, hvis ovenstående ikke virker, eller lad være med at override. Konfigurationsfilen er meget fleksibel, og vi kan bruge den til mange ting, også styre nøjagtigt, hvad certifikatet må bruges til (SSL server, SSL klient, signering af mails, etc.), men det er lidt mere avanceret, så det må du selv lige læse op på, hvis det er nødvendigt.
Vi prøver det:
$ php certificate_sign.php
Usage: php certificate_sign.php <csr> <private key> <password> <days> [signing certificate]
$ php certificate_sign.php csr.pem my_key 'very secret' 365 > cert.pem
$ cat cert.pem
-----BEGIN CERTIFICATE-----
MIIDmzCCAwSgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBljEhMB8GA1UEAxMYUm9i
ZXJ0IENocmlzIEJhbmcgTGFyc2VuMQswCQYDVQQGEwJESzEQMA4GA1UEBxMHQWFs
Ym9yZzEXMBUGA1UEChMOVGhlIFBsYXlncm91bmQxEDAOBgNVBAgTB0p5bGxhbmQx
JzAlBgkqhkiG9w0BCQEWGHJvYmVydEB0aGUtcGxheWdyb3VuZC5kazAeFw0xMjA1
MDcxMTI5MzRaFw0xMzA1MDcxMTI5MzRaMIGWMSEwHwYDVQQDExhSb2JlcnQgQ2hy
aXMgQmFuZyBMYXJzZW4xCzAJBgNVBAYTAkRLMRAwDgYDVQQHEwdBYWxib3JnMRcw
FQYDVQQKEw5UaGUgUGxheWdyb3VuZDEQMA4GA1UECBMHSnlsbGFuZDEnMCUGCSqG
SIb3DQEJARYYcm9iZXJ0QHRoZS1wbGF5Z3JvdW5kLmRrMIGfMA0GCSqGSIb3DQEB
AQUAA4GNADCBiQKBgQDL1VsJlS0NwmG20SIHRN1pdZbwbGPXIhGlnEVvB0Mh5GcJ
1DFixteXVGqf6jpSSl6473mlOuxywAeFPvbcyuHm0p1vePxD0gr8z27Di/FkLdja
9dZam2/jaMyEq606V/OdQnbEglSlEBc/u2kFr6aNojVXQYc+trW6sXiue6QQMQID
AQABo4H2MIHzMB0GA1UdDgQWBBTsfxRA5T45cacaXAOT+Rgg+oM7qTCBwwYDVR0j
BIG7MIG4gBTsfxRA5T45cacaXAOT+Rgg+oM7qaGBnKSBmTCBljEhMB8GA1UEAxMY
Um9iZXJ0IENocmlzIEJhbmcgTGFyc2VuMQswCQYDVQQGEwJESzEQMA4GA1UEBxMH
QWFsYm9yZzEXMBUGA1UEChMOVGhlIFBsYXlncm91bmQxEDAOBgNVBAgTB0p5bGxh
bmQxJzAlBgkqhkiG9w0BCQEWGHJvYmVydEB0aGUtcGxheWdyb3VuZC5ka4IBADAM
BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAIBOkzSQq37hDt/qElAkw/i1
K1KoSOfF5S97tgIK4Oop9S3MY+BDF6/gWBiHvWEwtdGAzeDS0rr3D0k8dTsppxyC
Lr+Cm9OpSsD0lctQgXIwhE4VrA0+jtnPlSkuo4VroPDwBR6iHcs4Y/uSTDM5cZoN
ex+HTLDvMwGLQ1S3QIXx
-----END CERTIFICATE-----
Vi kan nu slette vores CSR, det skal ikke bruges længere.
Lad os lave et script, som kan fortælle lidt om, hvad et certifikat indeholder:
- <?php
- //Filename: certificate_info.php
- if (count($argv) < 2) {
- echo "Usage: php " . $argv[0] . " <certificate>\n";
- } else {
- //Indlæs certifikatet
- if ($cert = openssl_x509_read(file_get_contents($argv[1]))) {
- //Eksporter med lidt ekstra informationer
- if (openssl_x509_export($cert, $exported, false)) {
- //Udskriv
- echo $exported;
- }
- }
- }
- ?>
Vi prøver det af på vores nye certifikat:
$ php certificate_info.php
Usage: php certificate_info.php <certificate>
$ php certificate_info.php cert.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 0 (0x0)
Signature Algorithm: md5WithRSAEncryption
Issuer: CN=Robert Chris Bang Larsen, C=DK, L=Aalborg, O=The Playground, ST=Jylland/emailAddress=robert@the-playground.dk
Validity
Not Before: May 7 11:29:34 2012 GMT
Not After : May 7 11:29:34 2013 GMT
Subject: CN=Robert Chris Bang Larsen, C=DK, L=Aalborg, O=The Playground, ST=Jylland/emailAddress=robert@the-playground.dk
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:cb:d5:5b:09:95:2d:0d:c2:61:b6:d1:22:07:44:
dd:69:75:96:f0:6c:63:d7:22:11:a5:9c:45:6f:07:
43:21:e4:67:09:d4:31:62:c6:d7:97:54:6a:9f:ea:
3a:52:4a:5e:b8:ef:79:a5:3a:ec:72:c0:07:85:3e:
f6:dc:ca:e1:e6:d2:9d:6f:78:fc:43:d2:0a:fc:cf:
6e:c3:8b:f1:64:2d:d8:da:f5:d6:5a:9b:6f:e3:68:
cc:84:ab:ad:3a:57:f3:9d:42:76:c4:82:54:a5:10:
17:3f:bb:69:05:af:a6:8d:a2:35:57:41:87:3e:b6:
b5:ba:b1:78:ae:7b:a4:10:31
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
EC:7F:14:40:E5:3E:39:71:A7:1A:5C:03:93:F9:18:20:FA:83:3B:A9
X509v3 Authority Key Identifier:
keyid:EC:7F:14:40:E5:3E:39:71:A7:1A:5C:03:93:F9:18:20:FA:83:3B:A9
DirName:/CN=Robert Chris Bang Larsen/C=DK/L=Aalborg/O=The Playground/ST=Jylland/emailAddress=robert@the-playground.dk
serial:00
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: md5WithRSAEncryption
80:4e:93:34:90:ab:7e:e1:0e:df:ea:12:50:24:c3:f8:b5:2b:
52:a8:48:e7:c5:e5:2f:7b:b6:02:0a:e0:ea:29:f5:2d:cc:63:
e0:43:17:af:e0:58:18:87:bd:61:30:b5:d1:80:cd:e0:d2:d2:
ba:f7:0f:49:3c:75:3b:29:a7:1c:82:2e:bf:82:9b:d3:a9:4a:
c0:f4:95:cb:50:81:72:30:84:4e:15:ac:0d:3e:8e:d9:cf:95:
29:2e:a3:85:6b:a0:f0:f0:05:1e:a2:1d:cb:38:63:fb:92:4c:
33:39:71:9a:0d:7b:1f:87:4c:b0:ef:33:01:8b:43:54:b7:40:
85:f1
-----BEGIN CERTIFICATE-----
MIIDmzCCAwSgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBljEhMB8GA1UEAxMYUm9i
ZXJ0IENocmlzIEJhbmcgTGFyc2VuMQswCQYDVQQGEwJESzEQMA4GA1UEBxMHQWFs
Ym9yZzEXMBUGA1UEChMOVGhlIFBsYXlncm91bmQxEDAOBgNVBAgTB0p5bGxhbmQx
JzAlBgkqhkiG9w0BCQEWGHJvYmVydEB0aGUtcGxheWdyb3VuZC5kazAeFw0xMjA1
MDcxMTI5MzRaFw0xMzA1MDcxMTI5MzRaMIGWMSEwHwYDVQQDExhSb2JlcnQgQ2hy
aXMgQmFuZyBMYXJzZW4xCzAJBgNVBAYTAkRLMRAwDgYDVQQHEwdBYWxib3JnMRcw
FQYDVQQKEw5UaGUgUGxheWdyb3VuZDEQMA4GA1UECBMHSnlsbGFuZDEnMCUGCSqG
SIb3DQEJARYYcm9iZXJ0QHRoZS1wbGF5Z3JvdW5kLmRrMIGfMA0GCSqGSIb3DQEB
AQUAA4GNADCBiQKBgQDL1VsJlS0NwmG20SIHRN1pdZbwbGPXIhGlnEVvB0Mh5GcJ
1DFixteXVGqf6jpSSl6473mlOuxywAeFPvbcyuHm0p1vePxD0gr8z27Di/FkLdja
9dZam2/jaMyEq606V/OdQnbEglSlEBc/u2kFr6aNojVXQYc+trW6sXiue6QQMQID
AQABo4H2MIHzMB0GA1UdDgQWBBTsfxRA5T45cacaXAOT+Rgg+oM7qTCBwwYDVR0j
BIG7MIG4gBTsfxRA5T45cacaXAOT+Rgg+oM7qaGBnKSBmTCBljEhMB8GA1UEAxMY
Um9iZXJ0IENocmlzIEJhbmcgTGFyc2VuMQswCQYDVQQGEwJESzEQMA4GA1UEBxMH
QWFsYm9yZzEXMBUGA1UEChMOVGhlIFBsYXlncm91bmQxEDAOBgNVBAgTB0p5bGxh
bmQxJzAlBgkqhkiG9w0BCQEWGHJvYmVydEB0aGUtcGxheWdyb3VuZC5ka4IBADAM
BgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAIBOkzSQq37hDt/qElAkw/i1
K1KoSOfF5S97tgIK4Oop9S3MY+BDF6/gWBiHvWEwtdGAzeDS0rr3D0k8dTsppxyC
Lr+Cm9OpSsD0lctQgXIwhE4VrA0+jtnPlSkuo4VroPDwBR6iHcs4Y/uSTDM5cZoN
ex+HTLDvMwGLQ1S3QIXx
-----END CERTIFICATE-----
Vi kan se, at Issuer og Subject er éns, og det betyder, at det er et self signed certificate. Vi kan nu bruge vores certifikat til f.eks. at enable SSL i vores web server.
Det gør vi med følgende Apache konfiguration:
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/my_key
SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase
Yderligere kan vi se under "X509v3 Basic Constraints" at det er et CA certifikat, hvilket betyder, at vi kan bruge certifikatet til at signere andre certifikater.
Prøv evt. at se indholdet af en af CA certifikaterne i '/etc/ssl/certs'.
Lad os se, om vi kan signere en andens CSR:
:) robert-workstation:~/code/php_crypto/5 $ php create_keypair.php 'meget hemmelig' poul
:) robert-workstation:~/code/php_crypto/5 $ php certificate_signing_request.php poul 'meget hemmelig' 'Poul Poulsen' DK Odense 'The Playground' Fyn 'poul@the-playground.dk' > poul_csr.pem
:) robert-workstation:~/code/php_crypto/5 $ php certificate_sign.php poul_csr.pem my_key 'very secret' 365 cert.pem > poul_cert.pem
:) robert-workstation:~/code/php_crypto/5 $ php certificate_info.php poul_cert.pem Certificate:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 0 (0x0)
Signature Algorithm: md5WithRSAEncryption
Issuer: CN=Robert Chris Bang Larsen, C=DK, L=Aalborg, O=The Playground, ST=Jylland/emailAddress=robert@the-playground.dk
Validity
Not Before: May 7 12:16:58 2012 GMT
Not After : May 7 12:16:58 2013 GMT
Subject: CN=Poul Poulsen, C=DK, L=Odense, O=The Playground, ST=Fyn/emailAddress=poul@the-playground.dk
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:b8:ec:33:8a:ad:ec:7d:f9:dd:3b:2e:78:1e:f0:
2c:e4:17:ec:36:f3:68:28:49:96:ff:fd:a1:d2:b1:
77:e9:7b:0a:d8:de:67:ff:6f:4f:1c:0e:be:0d:f1:
59:42:fb:53:88:44:0d:c5:d1:75:d5:40:2d:1f:65:
fa:96:c3:13:b8:59:3b:f6:4e:31:d3:bf:e5:37:b8:
f3:ca:eb:12:f1:b4:35:09:d5:ab:77:1a:b2:62:29:
72:f5:3d:f9:4b:a5:bd:f0:54:6d:7e:d8:77:0f:c8:
55:48:7f:b5:d8:ba:42:39:5f:0f:9c:d3:40:66:1e:
76:0c:9d:82:f0:2b:5b:f9:5d
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
30:FB:6B:16:8C:0D:D3:C4:4A:E1:59:38:D3:D7:D6:75:6C:01:BF:BB
X509v3 Authority Key Identifier:
keyid:EC:7F:14:40:E5:3E:39:71:A7:1A:5C:03:93:F9:18:20:FA:83:3B:A9
Signature Algorithm: md5WithRSAEncryption
44:38:96:7b:f5:a3:55:be:9c:aa:ae:4c:93:6b:cb:0c:66:1c:
1b:28:7e:5c:5c:01:37:d3:4b:ab:a0:32:8d:dc:18:ad:16:d9:
b9:5c:da:d3:e7:25:f7:dd:d7:ee:cf:6e:ec:dd:84:02:72:ed:
15:7f:da:b5:45:c3:48:53:82:b1:aa:96:da:c4:84:f3:e3:5d:
39:07:57:db:f7:c8:6e:9f:82:53:5a:9a:d4:27:58:70:94:b6:
5b:37:bd:5f:f1:7d:65:f9:e7:7b:0a:21:87:ab:46:54:29:32:
43:33:d6:1e:98:61:02:87:71:94:48:9e:63:40:73:03:90:bf:
f6:af
-----BEGIN CERTIFICATE-----
MIIDDDCCAnWgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBljEhMB8GA1UEAxMYUm9i
ZXJ0IENocmlzIEJhbmcgTGFyc2VuMQswCQYDVQQGEwJESzEQMA4GA1UEBxMHQWFs
Ym9yZzEXMBUGA1UEChMOVGhlIFBsYXlncm91bmQxEDAOBgNVBAgTB0p5bGxhbmQx
JzAlBgkqhkiG9w0BCQEWGHJvYmVydEB0aGUtcGxheWdyb3VuZC5kazAeFw0xMjA1
MDcxMjE2NThaFw0xMzA1MDcxMjE2NThaMIGDMRUwEwYDVQQDEwxQb3VsIFBvdWxz
ZW4xCzAJBgNVBAYTAkRLMQ8wDQYDVQQHEwZPZGVuc2UxFzAVBgNVBAoTDlRoZSBQ
bGF5Z3JvdW5kMQwwCgYDVQQIEwNGeW4xJTAjBgkqhkiG9w0BCQEWFnBvdWxAdGhl
LXBsYXlncm91bmQuZGswgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALjsM4qt
7H353TsueB7wLOQX7DbzaChJlv/9odKxd+l7CtjeZ/9vTxwOvg3xWUL7U4hEDcXR
ddVALR9l+pbDE7hZO/ZOMdO/5Te488rrEvG0NQnVq3casmIpcvU9+UulvfBUbX7Y
dw/IVUh/tdi6QjlfD5zTQGYedgydgvArW/ldAgMBAAGjezB5MAkGA1UdEwQCMAAw
LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
A1UdDgQWBBQw+2sWjA3TxErhWTjT19Z1bAG/uzAfBgNVHSMEGDAWgBTsfxRA5T45
cacaXAOT+Rgg+oM7qTANBgkqhkiG9w0BAQQFAAOBgQBEOJZ79aNVvpyqrkyTa8sM
ZhwbKH5cXAE300uroDKN3BitFtm5XNrT5yX33dfuz27s3YQCcu0Vf9q1RcNIU4Kx
qpbaxITz4105B1fb98hun4JTWprUJ1hwlLZbN71f8X1l+ed7CiGHq0ZUKTJDM9Ye
mGECh3GUSJ5jQHMDkL/2rw==
-----END CERTIFICATE-----
Super. Issuer og Subject er ikke den samme og Poul har ikke 'CA:TRUE'.
Validering
Godt så. Nu har vi muligheden for at generere certifikater, men vi skal også kunne tjekke, om et certifikat er validt.
Det kan man ikke som sådan, men man kan tjekke, om certifikatet er validt til et specifikt formål. At udstede certifikater til specifikke formål er lidt avanceret, så det dækker jeg ikke, men vi kan tjekke, om det er validt til et hvilket som helst formål, og det kan vi med følgende kode:
- <?php
- //Filename: certificate_validate.php
- if (count($argv) < 3) {
- echo "Usage: php " . $argv[0] . " <certificate> <ca certificate>\n";
- } else {
- //Indlæs certifikatet
- if ($cert = openssl_x509_read(file_get_contents($argv[1]))) {
- //Vi specificerer to lokationer for CA certifikater.
- //Et bibliotek som indeholder certifikater samt
- //vores eget CA certifikat
- $ca_key_locations = array(
- '/etc/ssl/certs', //Fjern denne linje hvis kun vores eget CA certifikat skal tjekkes
- $argv[2]
- );
-
- //Vi tjekker, om det specificerede certifikat er brugbart
- if (openssl_x509_checkpurpose($cert, X509_PURPOSE_ANY, $ca_key_locations) === TRUE) {
- echo "Valid\n";
- } else {
- echo "Invalid\n";
- }
- }
- }
- ?>
Vi prøver det af:
$ php certificate_validate.php
Usage: php certificate_validate.php <certificate> <ca certificate>
$ php certificate_validate.php poul_cert.pem cert.pem
Valid
$ php certificate_validate.php cert.pem cert.pem
Valid
Det virker !!
Men kan Poul signere certifikater ? Lad os prøve.
$ php create_keypair.php 'mere hemmeligt' peter
$ php certificate_signing_request.php peter 'mere hemmeligt' Peter DK Aarhus Evil Jylland 'peter@the-playground.dk' > peter_csr.pem
$ php certificate_sign.php peter_csr.pem poul 'meget hemmelig' 365 poul_cert.pem > peter_cert.pem
$ php certificate_validate.php peter_cert.pem cert.pem
Invalid
$ php certificate_validate.php peter_cert.pem poul_cert.pem
Invalid
Poul kan altså godt signere, men validitetstjekket fejler fordi Pouls certifikat ikke har 'CA:TRUE'.
Web of Trust
Det, vi indtil nu har dækket, er en del af PKI (Public Key Infrastructure) og kaldes chain of trust. Man kan kæde certifikater sammen så vores CA certifikat signere Pouls certifikat med tilladelse til at signere. Poul signerer så Peters, som signerer Karins, som signerer Oskars. Hvis alle i kæden har tilladelse til at signere, så stoler vi på Oskars certifikat.
Programmerne PGP og GPG og et par andre bruger noget andet, nemlig Web of Trust. Her er der ikke ét rod certifikat som alle stoler på. Istedet har alle mulighed for at signere alle andres nøgler, og man kan godt have mange til at signere den samme nøgle.
Modtager du en nøgle fra en fremmed (lad os kalde ham Poul), hvordan ved du så, at det faktisk ér Poul ?
Du kigger på, hvem der har signeret hans nøgle. Måske har din bedste ven Peter signeret den, og så er der da noget, der tyder på, at den er god nok, for vi stoler på Peter.
Til visse OpenSource sammenkomster vil der endda være arrangeret såkaldte "key signing parties", som ikke handler om druk, men om at tjekke hinandens oplysninger og signere hinandens GPG nøgler.
OpenSSL har ikke noget, som kan håndtere dette, men det kunne man jo selv implementere.
Afslutning
Nu ved vi alt om digitale certifikater....eller rettere, vi har lige nøjagtigt skrabet overfladen. Det er et stort emne, men vi har sandsynligvis ikke behov for meget mere. Vi kan nu udveksle nøgler og være rimelig sikre på, at de tilhører, hvem vi tror, de gør.
Der ér problemer med digitale certifikater. Mange steder "stoler" vi på folk. Vi stoler på, at CAerne gør sit arbejde med at baggrundstjekke, men det er ikke altid de gør det, og der er mange CAer. Bare én fejler, så er der et problem. Og hvis bare én CA mister sin nøgle, så er der et problem.
Dan Kaminsky, kendt for "hullet" i DNS, opridser her en hel del af problemerne:
www.youtube.com/watch?v=AG8XZto7APoDen er værd at se.
Hvad skal vi se på i næste artikel ?
Det ved jeg ikke endnu, men jeg finder nok på noget. Till then.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (0)
Du skal være
logget ind for at skrive en kommentar.