Kasutaja tuvastamine veebis

Allikas: eid.eesti.ee

Kasutaja tuvastamine veebis

Mis puhul kasutaja tuvastamiseks eID-d kasutada

Enamus veebilehti kas ei vaja üldse kasutaja tuvastamist või siis jätab kasutaja meelde cookie abil, tuvastamata seejuures tema nime või emaili. Kui kasutajat on vaja reaalselt tuvastada, siis kasutatakse Eestis eeskätt järgmisi meetodeid:

  • Kasutajanime ja parooli küsimine.
  • Facebooki või Google või mõne analoogilise sotsiaalvõrgustiku teenuste tarvitamine kasutaja tuvastamiseks.
  • eID tarvitamine kasutaja tuvastamiseks.

eID eeliseks muude viiside ees on eeskätt oluliselt suurem turvalisus ja kasutaja reaalse nime ning isikukoodi teadasaamine ilma administraatoripoolse vajaduseta aktiivselt kasutajate andmebaasi hallata.

Pane tähele, et veebis kasutaja tuvastamine ID-kaardiga töötab väga erinevalt kasutaja tuvastamisest mobiil-ID-ga. Vaatame neid eraldi, alustades ID-kaardist.

Veebirakenduse kasutaja tuvastamine ID-kaardiga

Selleks, et ehitada veebirakendusele külge kasutaja tuvastamine ID-kaardi abil, on vaja teha kolme asja:

  • Panna kokku vajalikud sertifikaadifailid: mh on selleks vaja tellida Sertifitseerimiskeskuselt kinnitus oma serdifikaadifailile. Esialgseks testimiseks seda kinnitust vaja ei ole. Kui turvalisus on rakenduse jaoks oluline, siis võid soovida tõmmata ja regulaarselt uuendada ka tühistusnimekirjasid tühistatud ID-kaartidest.
  • Seadistada veebiserver kasutama turvalist https sidet koos eelnevalt kokkupandud sertifikaadifailidega ja tühistusnimekirjadega: otsest programeerimist siin vaja ei ole, veebiserveri (Apache, IIS, Nginx) standarfunktsionaalsuse seas on oskus ise brauseri kaudu ID-kaardiga üle võrgu suhelda.
  • Lisada oma veebirakendusele kasutaja ID-kaardilt loetud info küsimine nn keskkonnamuutujast (sinna paneb selle info veebiserver) ja selle info lahtiharutamine vajalikeks tükkideks: tüüpiliselt kasutaja nimi ja isikukood. Siin on vaja kas ise veidi programmeerida või kasutada alltoodud näiteprogrammide juppe.


Serveri serfikaadifailide kokkupanek

Sertifikaadifailide ise kokkupanekuks kasuta openssl rakendust Linuxis pluss standardseid Linuxi abi-utiliite nagu wget, cat jne. Kui sul neid ei ole, saad Debianis vajalikud utiliidid installeerida käsuga apt-get install openssl wget

Kõik järgnevad käsud leiad eID koodinäidete hoidlast failina serveriserdid.sh.

Tööprotsessis toodud failide konkreetsed nimed võid soovi korral ära muuta, kuid lihtsam on täita neid käske muutmata kujul:

Loo fail server.key

 openssl genrsa -out server.key 1024
 

Loo edaspidiseks signeerimiseks mõeldud fail server.csr, vastates mitmetele küsimustele:

 openssl req -new -key server.key -out server.csr

Loo katsetamiseks ise signeeritud fail server.crt. Seda ei pea veebiserver usaldusväärseks sertifikaadiks ning nõuab kasutajalt erikinnitust, et ta on ikka nõus selle sertifikaadiga saidile minema. Taoline kinnituse küsimine ei ole muidugi aktsepteeritav avalikult kasutuses veebilehel, küll on ta aga OK katsetamiseks:

 openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Ametliku ja usaldusväärse server.crt faili saad ise signeerimise asemel ametlikult sertifitseerimisorganisatsioonilt (Eestis näiteks AS Sertifitseerimiskeskus) tellides: mine lehele http://sk.ee/teenused/veebiserveri-sertifikaadid . Selliselt tellitud sertifikaadifaili korral ei anna brauser enam mingeid hoiatusi.

Hangi kesksed sertifikaadid, vt ka https://sk.ee/repositoorium/sk-sertifikaadid/

 wget http://sk.ee/upload/files/JUUR-SK.PEM.cer
 wget http://sk.ee/upload/files/EECCRCA.pem.cer
 wget http://sk.ee/upload/files/ESTEID-SK%202007.PEM.cer
 wget http://sk.ee/upload/files/ESTEID-SK%202011.pem.cer

Liida mitu sertifikaati üheks failiks:

 cat JUUR-SK.PEM.cer EECCRCA.pem.cer 'ESTEID-SK 2007.PEM.cer' 'ESTEID-SK 2011.pem.cer' > id.crt

Sisselogijate sertifikaatide kehtivuse kontroll

Lisaks meie äsja loodud sertifikaadifailidele on soovitav kasutada tühistusnimekirjasid: loetelu tühistatud ID-kaartidest, täpsemalt, tühistatud sertifikaatidest. Kui sinu rakenduse jaoks on OK kasutada ka tühistatud kaarte, ei ole sul tühistusnimekirju vaja.

Kui sertifikaadi kehtivus on oluline, tuleb seda eraldi kontrollida väljaandja käest; ei piisa vaid sertifikaadil oleva kehtivuse algus- ja lõppkuupäeva kontrollist, kuna sertifikaadi väljaandja võib selle teatud põhjustel varem kehtetuks tunnistada, peatada või peatamist lõpetada.

Märkus: Järgnev jutt kehtib vaid ID-kaardi ning Digi-ID puhul: Mobiil-ID sertifikaati kontrollib DigiDocService ning SSL/TLS seansis isikutuvastamine käib rakenduse tasemel.

Kehtivuse kontrolliks on kaks valikut:

  • Tühistusnimekiri (Certificate Revocation List) ehk CRL, mis on perioodiliselt allalaetav nimekiri kõikidest kehtetuks tunnistatud sertifikaatidest. AS Sertifitseerimiskeskuse tühistusnimekirjade kasutamine on tasuta.
  • Kehtivuskinnitus (Online Certificate Status Protocol) ehk OCSP, mis esitab päringu sertifikaadi kehtivuse kohta OCSP-serverile (edaspidi responder), mis annab vastuse reaalajas. AS Sertifitseerimiskeskuse kehtivuskinnituse teenuse kasutamine on tasuline.[1]

Kuigi tühistusnimekirjade kasutamine on tasuta ning neil on eelis käideldavuse osas (kui CRL-serverid muutuvad kättesaadamatuks, siis on ikkagi teada viimane kord allalaetud seis), ei ole nendes olev info reaalajaline esitus sertifikaatide kehtivusest. Värskeima kehtivusinfo saamiseks tuleb kasutada kehtivuskinnituse teenust, mis aga on tasuline ning responderi mitte-kättesaadavuse korral puudub igasugune info sertifikaatide kohta (ka mitte mõni hetk tagasi kehtinud). Iga veebiteenuse korral on vaja eraldi uurida nõudeid ning otsustada, kumb sobib paremini.

Tähelepanu: Tarkvaraarendajad on mõnikord kasutanud isikutuvastamise juures LDAP-teenust sertifikaatide kehtivuskontrolli vahendina. See on teenuse väärkasutus ja sellisena keelatud, isegi kui see (mõnikord) annab korrektseid tulemusi. LDAP-andmeedastus ei ole turvatud, mistõttu saab vastuseid võltsida või muuta, ning LDAP kataloog võib sisaldada ka kehtetuid sertifikaate.

Tühistusnimekirjade kokkupanek

Tühistusnimekirju on lihtsam ja odavam kasutada, kui kehtivuskinnitust. Muidugi, arenduse algetapis võid ka need esialgu realiseerimata jätta.

Kõik järgnevad käsud leiad eID koodinäidete hoidlast failina tyhistusnimekirjad.sh.

Tühistusnimekirjad saad kasutusele võtta nii:

Hangi tühistusnimekirjad. Vt ka http://sk.ee/repositoorium/CRL/ :

 wget http://www.sk.ee/crls/esteid/esteid2007.crl
 wget http://www.sk.ee/crls/juur/crl.crl
 wget http://www.sk.ee/crls/eeccrca/eeccrca.crl
 wget http://www.sk.ee/repository/crls/esteid2011.crl

Konverteeri tühistusnimekirjad PEM formaati

 openssl crl -in esteid2007.crl -out esteid2007.crl -inform DER
 openssl crl -in crl.crl -out crl.crl -inform DER
 openssl crl -in eeccrca.crl -out eeccrca.crl -inform DER
 openssl crl -in esteid2011.crl -out esteid2011.crl -inform DER  

Loo tühistusnimekirjade symlingid, mille failinimi baseerub CRL faili hashil:

 ln -s crl.crl `openssl crl -hash -noout -in crl.crl`.r0
 ln -s esteid2007.crl `openssl crl -hash -noout -in esteid2007.crl`.r0
 ln -s eeccrca.crl `openssl crl -hash -noout -in eeccrca.crl`.r0
 ln -s esteid2011.crl `openssl crl -hash -noout -in esteid2011.crl`.r0  

Kui sa tühistusnimekirju regulaarselt ei uuenda, siis võib Apache varsti leida, et nimekirjad enam ei kehti, ning keelduda üldse ID-kaardiga autentimast.

Edaspidiseks tühistusnimekirjade automaatseks uuendamiseks vaata juhendeid:

Alternatiivina siintoodule võid vaadata ka

Veebiserveri konfigureerimine

Vaatame siinkohas põhjalikumalt Apache veebiserveri konfigureerimist. Microsoft IIS konfigureerimise juhendeid leiad sellelt AS Sertifitseerimiskeskuse lehelt.

Apache seadistamine

Apache seadistamiseks ID-kaardi jaoks on vaja teha kolme asja:

  • Seadistada Apache kasutama turvalist https protokolli täiesti standardsel moel. Sinu Apache võib juba olla selliselt seadistatud, siis ei ole vaja midagi muuta.
  • Seada https protokolli sätetes eelnevas loodud sertifikaadifailid ja soovi korral tühistusnimekirja kataloog.
  • Taaskäivitada Apache server ja katsetada kõigepealt, kas https töötab.

Seadistamiseks pead logima sisse root kasutajana või kasutama sudo käsku: teisiti Apachet konfigureerida ei saa. Järgnevalt seadistussammudest lähemalt.

Alternatiivina siintoodule võid vaadata ka

https protokoll

Kui sinu Apache server juba ei vasta https-ga algava urli avamisele, on vaja https seadistada. Mine Apache seadistuste kataloogi, mis Debianis on /etc/apache2. Debiani all on kõige lihtsam panna mods-enabled alamkataloogis symbolic lingi ssl.load ja ssl.conf failidele mods-available kataloogis, näiteks nii:

 /etc/apache2/mods-enabled# ln -s ../mods-available/ssl.load ssl.load
 /etc/apache2/mods-enabled# ln -s ../mods-available/ssl.load ssl.conf

samuti sites-enabled alamkataloogis symbolic lingi default-ssl failile sites-available kataloogis, näiteks nii:

 /etc/apache2/sites-enabled# ln -s ../sites-available/default-ssl default-ssl

Teistes distributsioonides võivad Apache seadistamise viisid olla küllaltki erinevad, näiteks võib sul olla vaja muuta hoopis httpd.conf faili. Üldjuhul pead tutvuma juhenditega oma Linuxi distributsiooni jaoks.

Peale seadistamist taaskäivita Apache, Debiani all nii:

 /etc/init.d/apache2 reload

https protokolli sätetes sertifikaadifailid

Sul on vaja sättida https-seadistuste failis olulised muutujad viitama varemloodud sertifikaadifailidele. Seadistuste fail on:

  • Debianis tüüpiliselt /etc/apache2/sites-available/default-ssl
  • Red Hati perekonnal /etc/httpd/conf.d/ssl.conf
  • Suse perekonnal loo ise fail, näiteks /etc/apache2/vhosts.d/www.domain.ee.conf

Teiste distributsioonide jaoks tutvu faili leidmiseks Apache seadistamise juhendiga. Hea alternatiivne juhend siintoodule on see juhend.

Seadistuste fail koosneb reeglina põhiliselt suurest hulgast kommentaaridest. Siin allpool oleme võtnud Debianis vaikimisi olnud default-ssl faili, muutnud ära olulised muutujad, kustutanud asjasse mittepuutuvad kommentaarid ja jätnud kõik muu muutmata.

Olulised seatud muutujad on

  • SSLEngine on
  • SSLCertificateFile /etc/apache2/eid/server.crt
  • SSLCertificateKeyFile /etc/apache2/eid/server.key
  • SSLCACertificateFile /etc/apache2/eid/id.crt
  • SSLCARevocationPath /etc/apache2/eid/
  • SSLVerifyClient require
  • SSLVerifyDepth 3

Seejuures olid meie loodud sertifikaadifailid pandud kataloogi /etc/apache2/eid/, kuid nad võiksid samahästi olla ka mõnes muus kataloogis, näiteks /etc/ssl/certs/ : peamine, et seatud failipathid vastaksid reaalsusele.

NB! Väga oluline aspekt on SSLCARevocationPath /etc/apache2/eid/ seadmine: kui see on seatud, siis peab ta olema kataloog, kus asuvad varemloodud hashidest koosnevate nimedega tühistusnimekirja failid. Kui need failid aeguvad, ei ole Apache enam nõus kasutajat tuvastama. Alternatiiv pidevale failide uuendamisele on mitte seada SSLCARevocationPath muutujat, jättes ta välja kommenteerituks. Sel juhul aktsepteerib Apache ka tühistatud ID-kaarte, mis ei pruugi aga paljude rakenduste jaoks olla suurem probleem.

Terviknäide:

<IfModule mod_ssl.c>
<VirtualHost _default_:443>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www
        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride None
                Order allow,deny
                allow from all
        </Directory>
        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        <Directory "/usr/lib/cgi-bin">
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        </Directory>
        ErrorLog ${APACHE_LOG_DIR}/error.log
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn
        CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined
        #   SSL Engine Switch:
        #   Enable/Disable SSL for this virtual host.
        SSLEngine on
        #   A self-signed (snakeoil) certificate can be created by installing
        #   the ssl-cert package. See
        #   /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
        #   If both key and certificate are stored in the same file, only the
        #   SSLCertificateFile directive is needed.
        SSLCertificateFile   /etc/apache2/eid/server.crt 
        SSLCertificateKeyFile /etc/apache2/eid/server.key 
        #   Certificate Authority (CA):
        #   Set the CA certificate verification path where to find CA
        #   certificates for client authentication or alternatively one
        #   huge file containing all of them (file must be PEM encoded)
        #   Note: Inside SSLCACertificatePath you need hash symlinks
        #         to point to the certificate files. Use the provided
        #         Makefile to update the hash symlinks after changes.
        #SSLCACertificatePath /etc/ssl/certs/
        SSLCACertificateFile /etc/apache2/eid/id.crt 

        #   Certificate Revocation Lists (CRL):
        #   Set the CA revocation path where to find CA CRLs for client
        #   authentication or alternatively one huge file containing all
        #   of them (file must be PEM encoded)
        #   Note: Inside SSLCARevocationPath you need hash symlinks
        #         to point to the certificate files. Use the provided
        #         Makefile to update the hash symlinks after changes.
        SSLCARevocationPath /etc/apache2/eid/
        #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl

        #   Client Authentication (Type):
        #   Client certificate verification type and depth.  Types are
        #   none, optional, require and optional_no_ca.  Depth is a
        #   number which specifies how deeply to verify the certificate
        #   issuer chain before deciding the certificate is not valid.
        SSLVerifyClient require
        SSLVerifyDepth 3 

        <FilesMatch "\.(cgi|shtml|phtml|php)$">
                SSLOptions +StdEnvVars
        </FilesMatch>
        <Directory /usr/lib/cgi-bin>
                SSLOptions +StdEnvVars
        </Directory>
        #   "force-response-1.0" for this.
        BrowserMatch "MSIE [2-6]" \
                nokeepalive ssl-unclean-shutdown \
                downgrade-1.0 force-response-1.0
        # MSIE 7 and newer should be able to use keepalive
        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
</VirtualHost>
</IfModule>

Peale seadistamist taaskäivita Apache, Debiani all nii:

 /etc/init.d/apache2 reload

IIS konfigureerimine

IIS konfigureerimise juhend AS Sertifitseerimiskeskuselt

Oma rakendusele kasutajainfo küsimise lisamine

Eelkirjeldatud moel seadistatud veebiserver nõuab brauseri kaudu ise kasutajalt PIN sisestamist, kontrollib sertifikaati ja salvestab ID-kaardilt loetud info standardsel moel serverisüsteemi nn keskkonnamuutujatesse, kust veebirakendused info kätte saavad. Olulised muutujad on seejuures

  • SSL_CLIENT_S_DN mille oodatav väärtus on taoline (nimed ja isikukood erinevad): /C=EE/O=ESTEID/OU=authentication/CN=SMITH,JOHN,37504170511/SN=SMITH/GN=JOHN/serialNumber=37504170511
  • SSL_CLIENT_VERIFY mille väärtus peab olema SUCCESS

Seejuures tuleb tähele panna mitut olulist nüanssi, muidu võib kasutajate äratundmine ebaõnnestuda. Kõigepealt, eelmainitud SSL_CLIENT_S_DN väärtuse paneb Apache kokku OPENSSL teegi abil, lugedes kõigepealt sisse kasutaja ID-kaardil olevate väljade sisu, siis kodeerides teksti ümber ja organiseerides väljad formaati /nimi=väärtus/nimi=väärtus/....

Erinevad OPENSSL versioonid on kasutanud samade väljade jaoks erinevaid nimesid: näiteks

  • OPENSSL 0.9.6 perenimi oli S ja isikukood SN,
  • alates 0.9.7 on perenimi SN ja isikukood serialNumber (väga tõenäoliselt kasutab sinu OPENSSL seda kodeeringut).

Enda arvutis oleva versiooni tuvastamiseks kasuta openssl version. Kui veebiserveris olev apache ei kasuta openssli vaid näiteks NSS-i (mod_nss) või gnutls (mod_gnutls), siis võib kogu kodeering hoopis teistsugune olla.

Teiseks kodeerib Apache koos OPENSSL-ga sertifikaadis leiduvad täpitähed ilma täpitähtedeta ASCII-stringiks, üldjuhul kodeerides mitte-ASCII sümbolid formaati \x01 jne, kus 01 on sümboli esitus heksas ehk kuueteistkümnendsüsteemis.

Kolmandaks on täpitähtede kodeerimise viis sertifikaatides endis erinev vanematel ja uuematel ID-kaartidel:

  • varasematel sertifikaatidel on tegu UCS-2/UTF-16 kujul tähtedega, kus kõik tähed on kahebaidised ja mitte-täpitähtede esimene bait on 0.
  • uuematel sertifikaatidel on tegu UTF-8 kujul tähtedega, kus mitte-täpitähed on ühebaidised ja täpitähed reeglina kahebaidised.

Konkreetse näitena on SSL_CLIENT_S_DN muutujas uuema sertifikaadi korral nimi "MÄNNIK" esitatud kui M\xC3\x84NNIK

Muude väljade osas SSL_CLIENT_S_DN muutujas tasub veel tähele panna, et

  • Kasutaja sertifikaadi korrektsuse aspektist ei ole vaja muutujate väärtusi tingimata kontrollida,
  • Tekst algab üldjuhul /C=EE/O=ESTEID, kuid see järjekord ja nimed on määratud OPENSSL poolt ja ei ole 100% garantiid, et nad on nimelt sellised.
  • Digi-ID puhul on O väli teistsugune: "O=ESTEID (DIGI-ID)", mobiil-ID sertidel "O=ESTEID (MOBIIL-ID)", kuigi Apache nendega üldiselt kokku ei puutu.
  • Ei ole välistatud, et osadel sertifikaatidel ilmneb OU=authentication asemel OU=Authentication


Järgnevad kolm näite-veebirakendust PHP-s, Pythonis ja Rubys loevad keskkonnamuutujast vajalikud väärtused, teisendavad tähestikud ja harutavad välja isiku eesnime, perenime ja isikukoodi, mis seejärel veebilehel kuvatakse.

Kui isikutuvastus või konvertimine ebaõnnestuvad, antakse teade "Authentication failed". Mitte mingit täiendavat tarkvara peale siintoodud lähtekoodide näidetes vaja ei lähe.

Eelduseks on uuem OPENSSL, koodinäited toetavad nii vanemat UCS2/UTF16 kui uuemat UTF8 kujul sertifikaate.

Pane veel tähele, et kasutajat võib tuvastada ID-kaardiga kas igal järjekordsel veebilehe avamisel (mis ei ole kõige kiirem) või ühekordselt, säilitades kasutajainfot edaspidi näiteks cookie-põhises sessioonis (traditsiooniline põhimõte). Nende variantide hea selgituse leiad Kuutõrvaja juhendist.

Kõik järgnevad koodinäited leiad ka eID koodinäidete hoidlast.

PHP näiterakendus

<?php 
header ("Content-Type: text/html; charset=utf-8");
  
// Get user information obtained by Apache from the Estonian ID card.
// Return list [last_name,first_name,person_code] or False if fails. 

function get_user () {
  // get relevant environment vars set by Apache
  // SSL_CLIENT_S_DN example:
  //  /C=EE/O=ESTEID/OU=authentication/CN=SMITH,JOHN,37504170511/
  //  SN=SMITH/GN=JOHN/serialNumber=37504170511
  $ident=getenv("SSL_CLIENT_S_DN");  
  $verify=getenv("SSL_CLIENT_VERIFY");
  // check and parse the values
  if (!$ident || $verify!="SUCCESS") return False;
  $ident=certstr2utf8($ident); // old cards use UCS-2, new cards use UTF-8
  if (strpos($ident,"/C=EE/O=ESTEID")!=0) return False;
  $ps=strpos($ident,"/SN=");
  $pg=strpos($ident,"/GN=");
  $pc=strpos($ident,"/serialNumber=");
  if (!$ps || !$pg || !$pc) return False;
  $res=array(substr($ident,$ps+4,$pg-($ps+4)), 
             substr($ident,$pg+4,$pc-($pg+4)), 
             substr($ident,$pc+14,strlen($ident)-$pc+14));
  return $res;
}  

// Convert names from UCS-2/UTF-16 to UTF-8.
// Function taken from help.zone.eu.

function certstr2utf8 ($str) {
  $str = preg_replace ("/\\\\x([0-9ABCDEF]{1,2})/e", "chr(hexdec('\\1'))", $str);       
  $result="";
  $encoding=mb_detect_encoding($str,"ASCII, UCS2, UTF8");
  if ($encoding=="ASCII") {
    $result=mb_convert_encoding($str, "UTF-8", "ASCII");
  } else {
    if (substr_count($str,chr(0))>0) {
      $result=mb_convert_encoding($str, "UTF-8", "UCS2");
    } else {
      $result=$str;
    }
  }
  return $result;
}

//  Actual script to run

$user=get_user();
if (!$user) echo ("Authentication failed.");
else {
  echo "Last name: " . $user[0] . "<br>";
  echo "First name: " . $user[1] . "<br>";
  echo "Person code: " . $user[2] . "<br>";
}

?>

Pythoni näiterakendus: pane see katseks serveri cgi-bin kataloogi

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, re

def get_user():
  """Get user information obtained by Apache from the Estonian ID card.
     Returns list [last_name,first_name,person_code] or None if fails. 
  """
  # get relevant environment vars set by Apache
  # SSL_CLIENT_S_DN example:
  # /C=EE/O=ESTEID/OU=authentication/CN=SMITH,JOHN,37504170511/
  # SN=SMITH/GN=JOHN/serialNumber=37504170511
  ident=os.getenv('SSL_CLIENT_S_DN')
  verify=os.getenv('SSL_CLIENT_VERIFY')
  # check and parse the values
  if not ident or verify!="SUCCESS": return None
  ident=str2utf8(ident) # old cards use UCS-2, new cards use UTF-8
  if not ident.startswith("/C=EE/O=ESTEID"): return None
  ps=ident.find("/SN=")
  pg=ident.find("/GN=")
  pc=ident.find("/serialNumber=")
  if ps<=0 or ps<=0 or pc<=0: return None
  res=[ident[ps+4:pg], ident[pg+4:pc], ident[pc+14:]]
  return res

def str2utf8(s):
  """Convert names from UCS-2/UTF-16 to UTF-8.""" 
  try:
    s=re.sub("/\\\\x([0-9ABCDEF]{1,2})/e", "chr(hexdec('\\1'))", s);
    if s.find("\x00")>0: 
      x=s.decode(encoding="utf-16") 
      s=x.encode(encoding="utf-8")    
      return s
    return s
  except:
    return "" # conversion failed    

# Actual script to run  

print("Content-type: text/html; charset=utf-8\n\n")
user=get_user()
if not user: 
  print("Authentication failed.")
else:
  print("Last name: "+user[0]+"<br>")
  print("First name: "+user[1]+"<br>")
  print("Person code: "+user[2]+"<br>")

Ruby näiterakendus: pane see katseks serveri cgi-bin kataloogi

#!/usr/bin/ruby

require 'iconv'

# Get user information obtained by Apache from the Estonian ID card.
# Return list [last_name,first_name,person_code] or nil if fails. 

def get_user
  # Get user information obtained by Apache from the Estonian ID card.
  #  Returns list [last_name,first_name,person_code] or nil if fails. 
  # get relevant environment vars set by Apache
  # SSL_CLIENT_S_DN example:
  # /C=EE/O=ESTEID/OU=authentication/CN=SMITH,JOHN,37504170511/
  # SN=SMITH/GN=JOHN/serialNumber=37504170511
  ident=ENV["SSL_CLIENT_S_DN"]
  verify=ENV["SSL_CLIENT_VERIFY"];
  # check and parse the values
  if !ident or verify!="SUCCESS"
    return nil
  end    
  ident=str2utf8(ident) # old cards use UCS-2, new cards use UTF-8
  if ident.index("/C=EE/O=ESTEID")!=0
    return nil
  end  
  ps=ident.index("/SN=")
  pg=ident.index("/GN=")
  pc=ident.index("/serialNumber=")
  if !ps or !pg or !pc
    return nil
  end  
  res=[ident[ps+4..pg-1], ident[pg+4..pc-1], ident[pc+14..-1]]
  return res
end  

# Convert names from UCS-2/UTF-16 to UTF-8.

def str2utf8(s)
  begin
    s=s.gsub("/\\\\x([0-9ABCDEF]{1,2})/e", "chr(hexdec('\\1'))")
    if s.index("\x00")
      conv=Iconv.new("UTF-8//IGNORE","UTF-16")
      s=conv.iconv(s) 
      return s
    end  
    return s
  rescue
    return "" # conversion failed 
  end  
end    

# Actual script to run

puts "Content-type: text/html; charset=utf-8\n\n"
user=get_user()
if !user 
  puts "Authentication failed."
else
  puts "Last name: "+user[0]+"<br>"
  puts "First name: "+user[1]+"<br>"
  puts "Person code: "+user[2]+"<br>"
end  

Ligipääsukontroll programmi kasutamata

Apache veebiserveri abil on võimalik lubada ligipääs mingile kataloogile ainult ID-kaardiga ning kindlatele kasutajatele ka ilma mingit programmi kasutamata. Selline meetod ei ole üldjuhul kõige sobivam: ta sobib eeskätt väikesele ning harva muutuvale hulgale inimestele ligipääsuõiguse andmiseks.

Allolevate näidete jaoks peab olema Apache varemkirjeldatud viisil seadistatud, mh peab kindlasti olema seatud SLVerifyClient require. Seejärel on vaja seadistusfaili viia sisse järgmine rida (näitena):

SSLRequire %{SSL_CLIENT_S_DN_CN} in {"MÄNNIK,MARI-LIIS,47101010033", "PERENIMI,EESNIMI,ISIKUKOOD"}

Kui ligipääs on vaja lubada suurele hulgale inimestele, siis on ligipääsufaile mugavam muuta kui seadistusfaile. Seame üles Basic autentimise ning kasutame FakeBasicAuth'i:

AuthType Basic
AuthName "Ainult ID-kaardiga"
AuthBasicProvider file                  # Siin saab ilmselgelt kasutada ka mõnda teist moodulit
AuthUserFile /kuskil/kaust/httpd.passwd # See fail peab olema turvalises kohas, kus teised seda lugeda ega muuta ei saa
Require valid-user

SSLOptions +FakeBasicAuth
Kui nüüd alustada SSL/TLS seanssi serveriga, siis mod_ssl üritab läbi viia Basic autentimist, kus kasutajanimeks on kliendisertifikaadil olev Distinguished Name ning parooliks "password". Seega on vaja lisada ligipääsufaili vastavad read iga inimese jaoks. Seda saab lihtsalt teha htpasswd utiliidiga:
htpasswd -b /kuskil/kaust/httpd.passwd <DN> password
Sobivas formaadis Distinguished Name saab leida openssl utiliidiga:
openssl x509 -noout -subject -in <sertifikaat>

Testkaardi DN on näiteks /C=EE/O=ESTEID/OU=authentication/CN=M\xC3\x84NNIK,MARI-LIIS,47101010033/SN=M\xC3\x84NNIK/GN=MARI-LIIS/serialNumber=47101010033.

Tähelepanu: FakeBasicAuth tõttu ei saa parooliks "password" asemel midagi muud kasutada. Kuna kellegi nime ning isikukoodi teada saamine pole keeruline, siis on ka autentimisel kasutatava DN-i ja parooli leidmine lihtne. Seetõttu peab serveri kindlasti niimoodi seadistama, et kaitstud kaustale ei oleks võimalik ilma SSL/TLS-ita ligi pääseda. Siis isegi, kui keegi üritab kasutada teise DN-i, asendatakse see tema sertifikaadilt loetuga.

Veebirakenduse kasutaja tuvastamine mobiil-ID-ga

Isikutuvastamine Mobiil-ID abil toimub järgmiselt:[2][3][4]

  1. Luuakse tavaline SSL/TLS seanss ilma kliendisertifikaati küsimata.
  2. Kasutaja sisestab oma telefoninumbri ja/või isikukoodi ning viimase välja andnud riigi koodi. Need andmed edastatakse teenusele DigiDocService MobileAuthenticate päringuga.
  3. DigiDocService kontrollib OCSP-protokolli vahendusel, et kasutaja Mobiil-ID isikutuvastuse sertifikaat kehtib.
  4. DigiDocService teeb samaaegselt järgmist:
    • Saadab mobiiloperaatorile isikutuvastuse päringu (mis edastab selle kasutaja telefonile);
    • Tagastab kontrollkoodi ja kasutaja sertifikaadi.
      • NB! Teenus tagastab kõigest tuvastamisel oleva isiku sertifikaadi -- see ei tähenda veel, et kasutaja oleks autenditud!
  5. Rakendus kuvab kasutajale neljakohalise isikutuvastuspäringu kontrollkoodi.
  6. Rakendus hakkab perioodiliselt käima DigiDocService'i käest isikutuvastuse olekut küsimas GetMobileAuthenticateStatus päringuga.
    • Olekupäring on võimalik teha ka sünkroonselt, s.t DigiDocService hoiab ühendust avatuna ning ei tagasta midagi enne, kui mobiiltelefonilt on tulnud vastus.
  7. Kasutaja telefonil kuvatakse teade isikutuvastuspäringu kohta
  8. Kasutaja veendub, et telefonil kuvatav kontrollkood langeb kokku rakenduse poolt kuvatavaga ning sisestab Mobiil-ID PIN1.
  9. Teenuse poolt saadetud väljakutse (challenge) allkirjastatakse SIM-kaardil oleva salajase võtmega ning tulemus saadetakse mobiiloperaatorile, mis edastab selle DigiDocService'ile.
  10. Järgmine kord, kui rakendus tuleb teenuselt päringu olekut küsima, vastab teenus, et kasutaja on autenditud ning tagastab allkirja.

Kasutamise näiteid näeb avalduste kasutusmallis ning SK näiterakenduse leiab siit.


Rakenduse näide ja lähtekood AS Sertifitseerimiskeskuselt

  1. http://www.sk.ee/teenused/kehtivuskinnituse-teenus/
  2. http://www.id.ee/index.php?id=30389
  3. http://www.sk.ee/upload/files/DigiDocService_spec_est.pdf
  4. http://www.sk.ee/upload/files/DigiDocService_spec_eng.pdf