Let’s Encrypt – without auto configuration

From the first moment I heard about Let's Encrypt I liked it and wanted to use it as fast as possible. But the more I read how they want to implement it, the more I dislike it.
Current project with automatic configuration is not what I want to use at all. I have many very complicated configs and I do not trust such tools enough to use them. I like UNIX's single purpose principle, tools should do one thing and do it well – nothing more.

But there is one neet tool that use Let's Encrypt API only leaving all configuration for me, it's acme-tiny python based script. I won’t copy/paste examples – documentation is written pretty well.

Generate ECDSA key with OpenSSL

After the last NSA scandal I’ve found some time to read some texts about PFS and ECDSA keys lately. I always used RSA keys but wanted to give a try to ECDSA so I wanted to give it a try (test performance, etc). Here is how I’ve done it.

Firstly find your favorite curve. A short tip about bit length and complexity could be found here. From it you will now that using 256 bit ECDSA key should be enough for next 10-20 years.

$ openssl ecparam -list_curves
  secp112r1 : SECG/WTLS curve over a 112 bit prime field
  secp112r2 : SECG curve over a 112 bit prime field
  secp128r1 : SECG curve over a 128 bit prime field
  secp128r2 : SECG curve over a 128 bit prime field
  secp160k1 : SECG curve over a 160 bit prime field
  secp160r1 : SECG curve over a 160 bit prime field
  secp160r2 : SECG/WTLS curve over a 160 bit prime field
  secp192k1 : SECG curve over a 192 bit prime field
  secp224k1 : SECG curve over a 224 bit prime field
  secp224r1 : NIST/SECG curve over a 224 bit prime field
  secp256k1 : SECG curve over a 256 bit prime field
  secp384r1 : NIST/SECG curve over a 384 bit prime field
  secp521r1 : NIST/SECG curve over a 521 bit prime field
  prime192v1: NIST/X9.62/SECG curve over a 192 bit prime field
  prime192v2: X9.62 curve over a 192 bit prime field
  prime192v3: X9.62 curve over a 192 bit prime field
  prime239v1: X9.62 curve over a 239 bit prime field
  prime239v2: X9.62 curve over a 239 bit prime field
  prime239v3: X9.62 curve over a 239 bit prime field
  prime256v1: X9.62/SECG curve over a 256 bit prime field
  sect113r1 : SECG curve over a 113 bit binary field
  sect113r2 : SECG curve over a 113 bit binary field
  sect131r1 : SECG/WTLS curve over a 131 bit binary field
  sect131r2 : SECG curve over a 131 bit binary field
  sect163k1 : NIST/SECG/WTLS curve over a 163 bit binary field
  sect163r1 : SECG curve over a 163 bit binary field
  sect163r2 : NIST/SECG curve over a 163 bit binary field
  sect193r1 : SECG curve over a 193 bit binary field
  sect193r2 : SECG curve over a 193 bit binary field
  sect233k1 : NIST/SECG/WTLS curve over a 233 bit binary field
  sect233r1 : NIST/SECG/WTLS curve over a 233 bit binary field
  sect239k1 : SECG curve over a 239 bit binary field
  sect283k1 : NIST/SECG curve over a 283 bit binary field
  sect283r1 : NIST/SECG curve over a 283 bit binary field
  sect409k1 : NIST/SECG curve over a 409 bit binary field
  sect409r1 : NIST/SECG curve over a 409 bit binary field
  sect571k1 : NIST/SECG curve over a 571 bit binary field
  sect571r1 : NIST/SECG curve over a 571 bit binary field
  c2pnb163v1: X9.62 curve over a 163 bit binary field
  c2pnb163v2: X9.62 curve over a 163 bit binary field
  c2pnb163v3: X9.62 curve over a 163 bit binary field
  c2pnb176v1: X9.62 curve over a 176 bit binary field
  c2tnb191v1: X9.62 curve over a 191 bit binary field
  c2tnb191v2: X9.62 curve over a 191 bit binary field
  c2tnb191v3: X9.62 curve over a 191 bit binary field
  c2pnb208w1: X9.62 curve over a 208 bit binary field
  c2tnb239v1: X9.62 curve over a 239 bit binary field
  c2tnb239v2: X9.62 curve over a 239 bit binary field
  c2tnb239v3: X9.62 curve over a 239 bit binary field
  c2pnb272w1: X9.62 curve over a 272 bit binary field
  c2pnb304w1: X9.62 curve over a 304 bit binary field
  c2tnb359v1: X9.62 curve over a 359 bit binary field
  c2pnb368w1: X9.62 curve over a 368 bit binary field
  c2tnb431r1: X9.62 curve over a 431 bit binary field
  wap-wsg-idm-ecid-wtls1: WTLS curve over a 113 bit binary field
  wap-wsg-idm-ecid-wtls3: NIST/SECG/WTLS curve over a 163 bit binary field
  wap-wsg-idm-ecid-wtls4: SECG curve over a 113 bit binary field
  wap-wsg-idm-ecid-wtls5: X9.62 curve over a 163 bit binary field
  wap-wsg-idm-ecid-wtls6: SECG/WTLS curve over a 112 bit prime field
  wap-wsg-idm-ecid-wtls7: SECG/WTLS curve over a 160 bit prime field
  wap-wsg-idm-ecid-wtls8: WTLS curve over a 112 bit prime field
  wap-wsg-idm-ecid-wtls9: WTLS curve over a 160 bit prime field
  wap-wsg-idm-ecid-wtls10: NIST/SECG/WTLS curve over a 233 bit binary field
  wap-wsg-idm-ecid-wtls11: NIST/SECG/WTLS curve over a 233 bit binary field
  wap-wsg-idm-ecid-wtls12: WTLS curvs over a 224 bit prime field
  Oakley-EC2N-3: 
	IPSec/IKE/Oakley curve #3 over a 155 bit binary field.
	Not suitable for ECDSA.
	Questionable extension field!
  Oakley-EC2N-4: 
	IPSec/IKE/Oakley curve #4 over a 185 bit binary field.
	Not suitable for ECDSA.
	Questionable extension field!

Now generate new private key with chosen curve (prime256v1 looks fine, like: c2pnb272w1, sect283k1, sect283r1 or secp256k1, etc)

$ openssl ecparam -out ec_key.pem -name prime256v1 -genkey

And generate self-signed certificate that could be directly used:

$ openssl req -new -key ec_key.pem -x509 -nodes -days 365 -out cert.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) [AU]:PL
State or Province Name (full name) [Some-State]:example.pl  
Locality Name (eg, city) []:example.pl
Organization Name (eg, company) [Internet Widgits Pty Ltd]:example.pl
Organizational Unit Name (eg, section) []:example.pl
Common Name (e.g. server FQDN or YOUR name) []:example.pl
Email Address []:hostmaster@example.pl

Certyfikaty nazwaSSL na własnym serwerze

Od jakiegoś czasu można kupić w NetArcie certyfikaty SSL, a niedawno zrobili na nie promocję – 15zł za pierwszy rok (za certyfikat na jedną stronkę). Tzw. tanie i dobre. Po wyrobieniu certyfikatu i zapisaniu z panelu klienta mam pliczki: stonka.crt i netart_rootca.crt, które wrzucamy do Apachego, powiedzmy tak:

SSLCertificateFile /etc/ssl/certs/stonka.crt
SSLCertificateKeyFile /etc/ssl/private/priv.key
SSLCACertificateFile /etc/ssl/certs/netart_rootca.crt

Certyfikat działa w Chromie ale nie weryfikuje się w Firefoxie i Internet Explorerze. FF wyświetla błąd: sec_error_unknown_issuer – co oznacza brak certyfikatu wystawcy gdzieś w łańcuchu certyfikatów. W FAQ zero jak chodzi o konfigurację certyfikatów na serwerze poza NetArt’em…

Przeglądnąłem informacje certyfikatu rootca:

openssl x509 -in netart_rootca.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            46:53:b1:a6:1e:ba:2d:c7:a3:2e:f9:39:5a:4e:f8:8c
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, CN=Certum Global Services CA
        Validity
            Not Before: Jul  6 10:31:40 2012 GMT
            Not After : Jul  4 10:31:40 2022 GMT
        Subject: C=PL, O=NetArt Sp\xC3\xB3\xC5\x82ka Akcyjna S.K.A., OU=http://nazwa.pl, CN=nazwaSSL
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
                Modulus (2048 bit):
                    00:cc:91:f5:f7:01:09:4f:75:c8:09:c7:14:8f:e4:
                    1a:99:78:20:99:40:59:6f:10:2f:ff:fe:d0:10:ff:
                    06:a3:39:3d:c4:f1:4b:07:cf:22:39:20:80:43:50:
                    c1:af:b4:01:71:a0:a3:30:11:52:d3:d2:98:d9:c2:
                    69:f7:e3:00:d9:19:3f:3d:b3:3b:52:75:e3:d3:0c:
                    ab:ff:57:01:3a:83:5c:f5:02:bb:28:fe:90:38:8e:
                    a2:84:cf:61:48:e7:99:e0:72:24:b6:11:58:4a:18:
                    57:0d:34:18:5e:35:c8:b3:ac:04:5f:8d:38:2f:a2:
                    cf:d2:dc:74:d8:41:02:ec:e0:db:0c:54:81:a4:7a:
                    c5:34:d5:19:86:b6:1e:65:f7:3c:f6:b2:dd:3a:b5:
                    b7:91:61:18:fd:81:2c:8a:68:d7:d6:a8:33:b7:47:
                    b8:f9:48:ad:35:ee:11:93:f9:c2:a9:fa:94:8e:4f:
                    bb:d1:1e:a7:64:74:b4:f9:0f:88:a7:11:a7:33:1a:
                    c2:b1:14:0c:12:a8:6b:82:44:78:4e:d5:79:8f:5c:
                    60:29:47:4c:36:35:52:c7:ad:6c:c0:20:39:93:f1:
                    c8:b3:3b:d9:c6:ec:dd:22:45:27:a2:50:12:07:f8:
                    fe:38:79:24:89:b9:f7:de:e0:c6:e9:64:e3:f4:0b:
                    fa:c7
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 CRL Distribution Points: 
                URI:http://crl.certum.pl/gsca.crl

            Authority Information Access: 
                CA Issuers - URI:http://repository.certum.pl/gsca.cer

            X509v3 Authority Key Identifier: 
                keyid:45:C5:B2:86:4E:CC:DD:29:97:E4:DD:14:C4:6E:AE:4D:B8:C1:77:F8

            X509v3 Subject Key Identifier: 
                9D:CE:F0:5A:B4:CB:25:CF:36:A5:82:5D:8F:F7:7F:98:46:19:37:2E
            X509v3 Key Usage: critical
                Certificate Sign, CRL Sign
            X509v3 Certificate Policies: 
                Policy: X509v3 Any Policy
                  CPS: https://www.certum.pl/CPS

    Signature Algorithm: sha1WithRSAEncryption
        53:01:c7:87:ad:ac:d7:52:32:1f:79:5d:87:f0:01:88:8e:99:
        3f:07:d8:e4:bc:84:0a:8d:5f:d5:d5:62:c2:9b:79:33:46:f9:
        8a:d9:b2:96:ed:35:8a:29:3b:5f:38:7a:6a:70:1d:8b:84:1a:
        a3:90:81:f7:2e:60:77:78:f0:d0:84:a3:e9:8a:3c:ef:8a:34:
        6b:b1:9c:e8:e1:76:f4:87:1e:7b:3c:18:6f:98:70:2c:2a:8a:
        22:f5:ba:96:52:7e:26:62:8b:96:03:32:22:f9:80:d7:f1:dd:
        9e:c2:79:b4:17:0d:40:ff:50:6a:28:6f:e8:6f:11:8a:f9:b4:
        65:2b:52:86:31:50:c7:4d:e6:f3:be:de:6a:d1:89:90:27:61:
        6c:1c:7d:90:1f:9a:ed:02:d4:01:22:5e:8b:0b:c9:99:34:f1:
        1d:04:f4:d6:d0:71:7c:8f:0c:31:a3:2f:20:ad:35:c8:d3:b4:
        0b:38:74:89:a5:d3:55:72:e9:af:b0:b8:9f:02:c9:85:69:01:
        d8:7e:00:44:25:91:2c:5e:5b:9f:ed:52:a8:bb:5d:94:20:f4:
        c4:82:35:de:e5:d3:05:3c:14:d5:08:80:e4:74:47:e3:fa:f7:
        8c:73:40:a8:2d:ea:1f:96:c8:e3:03:2c:62:08:cc:44:02:46:
        a5:81:c2:0a

CA NetArtu nie jest domyślnie zainstalowane w żadnej przeglądarce więc nic dziwnego – ale są tam klucze Unizeto/Certum – dorzucę więc klucz CA (Chrome najwidoczniej sam potrafi to zrobić):

wget http://repository.certum.pl/gsca.cer
openssl x509 -inform der -in gsca.cer -out gsca.pem
cat gsca.pem >> netart_rootca.crt

Restart Apachego i przeglądarki już nie krzyczą. Mogliby się tylko wysilić na jakąś instrukcję albo udostępnienie od razu cabudle.crt z wszystkimi potrzebnymi certami.

Konwersja formatu certyfikatu dla telefonów Nokia

Chciałem zaimportować mój certyfikat self-signed do Nokii E72 by nie krzyczała przy sprawdzaniu poczty. Potrzebowałem certyfikatu w formacie DER, a miałem w PEM – chwilę szukałem jak dokonać konwersji, więc ku pamięci zapisuję kilka gotowych poleceń:

  1. Konwersja certyfikatu z PEM na DER
    openssl x509 -in in.crt -inform PEM -out out.crt -outform DER
  2. Konwersja certyfikatu z DER na PEM
    openssl x509 -in in.crt -inform DER -out out.crt -outform DER
  3. Konwersja klucza z formatu PEM na DER
    openssl rsa -in in.crt -inform PEM -out out.crt -outform DER
  4. Konwersja klucza z formatu DER na PEM
    openssl rsa -in in.crt -inform DER -out out.crt -outform PEM

Po konwersji certyfikat w formacie DER wystarczy wrzucić na kartę i otworzyć z menadżera plików, zainstalować.

Certyfikaty SelfSigned

Certyfikaty oparte o SSL stanowią obecnie podstawę bezpieczeństwa wielu usług sieciowych zaczynając od HTTP, przez POPS, IMAPS, itd… Niestety zakupienie certyfikatu w organizacjach jak VeriSgin czy Thawte jest dość kosztowe, a jeżeli potrzebujemy kilka certyfikatów to często na lokalne potrzeby jest to po prostu nie opłacalne.

Postaram się przedstawić wersję “ekonomiczną” certyfikacji 🙂

Generowanie Certificate Signing Request

Pierwszym etapem generowania certyfikatu jest przygotowanie Certificate Signing Request, czyli czegoś w rodzaju “prośby” o certyfikat. Nasza “prośba” po podpisaniu przez centrum autoryzacyjne stanie się certyfikatem.

Do wygenerowania Request’u potrzebny jest najpierw klucz prywatny, który generujemy np. tak:

openssl genrsa -aes256 -out priv.key 4096

Powyższe polecenie poprosi nas dwa razy o hasło, które trzeba zapamiętać (albo zapisać i zamknąć w sejfie) – zalecam wykorzystanie pseudolosowego ciągu znaków o długości minimum 10 znaków.

Po genrsa możemy użyć kilku opcji wybierając w ten sposób algorytm szyfrujący – do wyboru są: des, des3, aes128, aes192, aes256. Ja wybrałem 256-bitowego AES’a – najmocniejszy z tych algorytmów.

Ostatni parametr do długość klucza. Można użyć innej wartości np. 1024. Klucz wygeneruje się szybciej ale będzie prostszy do złamania. Z moich doświadczeń wynika, że niektóre aplikacje mogą mieć problem z obsługą długiego klucza (np. jak użyty w tym przykładzie), wtedy użycie mniejszej wartości może być konieczne (lepsze słabsze zabezpieczenie niż żadne).

Warto ograniczyć uprawnienia do wygenerowanego klucza prywatnego tak by tylko właściciel miał do niego dostęp:

chmod 400 priv.key

Przy okazji tworzenia klucza prywatnego warto wspomnieć, że jeżeli będziemy chcieli go użyć w tak przygotowanej postaci np. w Apache’m to przy każdym starcie Apache będzie nas prosić o podanie hasła odbezpieczającego klucz prywatny. Niby to bezpieczne ale z drugiej strony przez takie zabezpieczenie Apache nie podniesie się samodzielnie np. po awarii. Rozwiązaniem jest przygotowanie odszyfrowanej wersji klucza prywatnego, z której będzie korzystał Apache. Robi się to tak:

openssl rsa -in priv.key -out priv.unsecure.key
chmod 400 priv.unsecure.key

Klucz priv.unsecure.key podany w konfiguracji programu nie będzie wymagał hasła. Koniecznie należy uniemożliwić dostęp do tego pliku wszystkim z wyjątkiem root’a!

openssl req -new -key priv.key -out request.csr

Co dalej?

Ok. Mamy już request’a, warto w tym miejscu wspomnieć co możemy z nim zrobić:

  1. Możemy taki plik przesłać do centrum autoryzacji (CA) celem podpisania i wygenerowania certyfiaktu. Klucze publiczne CA takich jak Thawte, VeriSign, itp są dołączane do przeglądarek internetowych, OS’ów, etc. dzięki temu strony internetowe (bądź inne usługi) zabezpieczone takimi certyfikatami weryfikują się bez żadnej dodatkowej akcji ze strony użytkownika. Warto wziąć pod uwagę to rozwiązanie, jeżeli np. chcemy zabezpieczyć sklep internetowy – my odpuścimy to rozwiązanie ze względu na koszty 🙂
  2. Drugą opcją jest możliwość samodzielnego podpisania certyfikatu tworząc tzw. SelfSigned Certificate. To zalecana opcja jeżeli mamy tylko jedną stronę/usługę. Użytkownik raz doda sobie nasz certyfikat jako zaufany i będzie mógł korzystać z szyfrowania do woli. Metoda ta robi się problematyczna gdy trzeba zarządzać większą liczbą certyfikatów.
  3. Ostatnia opcja to utworzenie własnego CA (czyli specjalnego certyfikatu), którym będziemy podpisywać wygenerowane przez nas Requesty. Ma to tę zaletę, że wystarczy rozdystrybuować klucz publiczny CA i będzie to wystarczające do weryfikacji wszystkich naszych certyfikatów.

Tworzenie certyfikatów SelfSigned

Zaczniemy od prostszej wersji czyli podpiszemy nasz request wygenerowanym przez nas wcześniej kluczem prywatnym tworzac tzw. SelfSigned Certificate. Aby to zrobić potrzebne jest takie polecenie:

openssl x509 -req -days 365 -in request.csr \
 -signkey priv.key -out certificate.crt

Tak oto wygenerowaliśmy certyfikat certificate.crt ważny przez 365 dni (tutaj dowolność ustawień ale 1 rok to sensowny okres).

Właściwości certyfikatu można sprawdzić np. tak:

openssl x509 -noout -text -in certificate.crt

Tworzenie własnego CA

Najpierw należy utworzyć klucz prywatny naszego CA, robi się to dokładnie tak samo jak w przypadku generowanego wcześniej klucza prywatnego dla serwera. Później musimy wygenerować requesta (analogicznie jak w przypadku certyfikatu SelfSigned). Czyli dwa polecenia:

openssl genrsa -aes256 -out ca.key 4096
openssl req -new -x509 -days 365 \
 -key ca.key -out ca.crt

Skoro mamy już certyfikat naszego CA, możemy podpisać wcześniej wygenerowany Request dla serwera:

openssl x509 -req -days 365 -in request.csr -CA ca.crt \
 -CAkey ca.key -set_serial 01 -out certificate.crt

Ogólnie podpisywanie przebiega podobnie jak przy certyfikatach SelfSigned ale jak widać wykorzystywane są klucze naszego CA i pojawia się nowy parametr: set_serial, którego wartość musi być inna dla każdego podpisanego przez to CA certyfikatu. Najprościej aby serial przyjmował numer kolejno wygenerowanego certyfikatu.

Jeżeli wiemy, że będziemy generować więcej tego typu certyfikatów warto przygotować sobie skrypt, który zadba o prawidłową wartość pola serial.

Podsumowanie

Certyfikaty przygotowane w ten sposób można wrzucić do Apache, postfix’a, itd… i w ten sposób szyfrując ruch.