TEA - šifrovaná autorizace bezpečným heslem

Jedním ze základních bezpečnostních prvků síťového spojení s protistranou je ověření totožnosti Clienta, který se pokouší navázat spojení na server. Při použití standardní cesty přes výzvy k zadání jména a následně hesla je faktická bezpečnost velmi nízká, protože jmného i heslo putují sítí ve standardním TCP/IP paketu bez jakéhokoliv zabezpečení proti odposlechu. Abychom se této bezpečnostně neověřené autorizaci vyhnuli, používáme ve všech produktech TEA (The Tiny Encryption Algorithm). Jedná se o jednoduchý kryptovací algoritmus, který heslo zašifruje náhodně vygenerovaným číslem, které pošle server a teprve zašifrované heslo posílá skrz TCP/IP síť. Právě algoritmus šifrování, komprese a dekomprese hesla popisuje tento článek..

 
Obsah článku : - Jak probíhá proces autorizace
- Šifrovací algoritmus TEA
- BASE64
- Implementace algoritmu TEA / Base64 v systému
- TEA autorizační kalkulačka v HTML / Javascript
- Popis výpočtu TEA v C++
- HW produkty podporující TEA autorizaci

 

Jak probíhá proces autorizace

Jednou z potřebných funkcí při implementaci přístupových práv k jakémukoliv zařízení je ověření uživatele či celého spojení. Lze k němu použít systém statických uživatelských jmen a hesel. Nevýhodou tohoto řešení je, že se heslo přenáší po síti a je tedy odposlechnutelné.
Vhodnější je používat některou metodu jednorázově použitelných hesel. Buď lze použít seznam hesel a každé heslo použít jen jednou a po použití zahodit, nebo použít generátor hesel. Další možností je použití metod kryptografie.

Veškeré naše finální produkty používají k ověřování spojení, popř. uživatele metodu založenou na symetrické kryptografii. Metoda ověřování je jednoduchá, nicméně velmi bezpečná. Server používá k ověření spojení princip sdíleného tajemství. Toto tajemství (klíč, heslo) se však nepřenáší po síti. Proces autorizace probíhá následným způsobem :

  • Klient zažádá o otevření spojení.
  • Server zasílá v odpovědi na požadavek 64ti bitové náhodné číslo.
  • Klient toto přijaté číslo zašifruje pomocí uloženého klíče (= faktického hesla) a výsledek zašle zpět serveru
  • Server přijme odpověď, zpětným algoritmem ji spolu s náhodným číslem, které předtím zaslal Clientovi odšifruje a porovná výsledný klíč (= faktické heslo), pokud je heslo OK, pokračuje v komunikaci.
    Pokud heslo není OK, zavře spojení..

Šifrovací klíč je 128mi bitový. Vzhledem k jeho velikosti by případný útočník musel zachytit k jeho rozluštění takové množství dvojic dotaz/odpověd, které přesahuje fyzickou životnost zařízení. Cestou k získání správného klíče však může být fyzické odcizení jednoho ze zařízení, které klíč musí znát. Z tohoto důvodu je vhodné defaultní heslo změnit!.
Algoritmus lze rovněž, jako jakýkoliv jiný oslabit nevhodnými hesly, uhodnutelnými slovníkovým útokem.

Šifrovací algoritmus TEA

Naše zařízení používají k šifrování algoritmus TEA, který lze stručne charakterizovat asi takto :
  • TEA je zkratka pro „The Tiny Encryption Algorithm“, vymyšlen Davidem Wheelerem a Rogerem Needhamem z Počítačových Laboratoří University v Cambridge.
  • TEA je jednoduchá a stručná, nicméně bezpečná a rozumně rychlá šifra.
  • TEA je bloková šifra, používá 64ti bitové bloky dat šifrované 128mi bitovým klíčem.
  • TEA je symetrická šifra, to znamená že pro zašifrování i odšifrování se používá stejný klíč.
  • TEA je jedním z rodiny šifrovacích algoritmů Feistel (někdy též nazývaný DES-like) používajících nedestruktivní operace a transpozice, v případě TEA operací XOR a sčítání.
  • TEA je iterační bloková šifra, to znamená, že celé šifrování je prováděno v několika krocích, používajících pro každý krok stejnou transformaci.

Feistel transformace rozděluje šifrovaná data na dvě poloviny. Každá polovina je podrobena příslušné funkci a xorována s druhou polovinou. Algoritmus transformace je doplněn přičítáním konstanty delta k šifrovanému textu, pomáhajícímu „zatemnit“ šifrovací klíč. Server používá především směr nezašifrovaný_text -> zašifrovaný_text, obdobné je to i v případě klienta.

Ukažme si na příkladě JavaScriptu, vyjmutého z programu pro ověřování klienta, náznak celé činnosti.

function encipher(str)
{
var sum = 0;
var delta = 0x9E3779B9;
var n = 32;
var s = base64Decode(str);
var y = s.charCodeAt(3)+ (s.charCodeAt(2) << 8) + (s.charCodeAt(1) << 16) + (s.charCodeAt(0) << 24);
var z = s.charCodeAt(7)+ (s.charCodeAt(6) << 8) + (s.charCodeAt(5) << 16) + (s.charCodeAt(4) << 24);
var w;
if(str.length != 12) {
return "Missing character";
} else if((
(s.charCodeAt(0) + s.charCodeAt(1) + s.charCodeAt(2) +
s.charCodeAt(3) + s.charCodeAt(4) + s.charCodeAt(5) +
s.charCodeAt(6) + s.charCodeAt(7) + s.charCodeAt(8))
& 0xFF) != 0)
{
return "Checksum Error";
} else {
while (n-- > 0) {
sum += delta
y += (((z << 4) + keyA) ^ (z + sum) ^ (((z >> 5) & 0x07FFFFFF) + keyB))
z += (((y << 4) + keyC) ^ (y + sum) ^ (((y >> 5) & 0x07FFFFFF) + keyD))
}
w = (y>>24 & 0xFF) + (y>>16 & 0xFF) + (y>>8 & 0xFF) + (y & 0xFF) +
(z>>24 & 0xFF) + (z>>16 & 0xFF) + (z>>8 & 0xFF) + (z & 0xFF);
w &= 0xFF;
w = 0x100 - w;
s = (String.fromCharCode(y>>24 & 0xFF, y>>16 & 0xFF, y>>8 & 0xFF, y & 0xFF) +
String.fromCharCode(z>>24 & 0xFF, z>>16 & 0xFF, z>>8 & 0xFF, z & 0xFF) +
String.fromCharCode(w & 0xFF));
return base64Encode(s);
}
}

TEA Padlock Logo are all copyright © David A. G. Gillies 1995-1998. All rights reserved.

Jednoduchým pohledem na prvních pár řádků však zjistíme, že předávaná data pro zašifrování předávaná serverem Clientovi a zpět nejsou 64ti bitová, ale 72 bitová, resp. předávaná jako 12ti znakový řetězec. Jak je to tedy ve skutečnosti ?

Server předává dotaz ve formě 12 znakového tišťitelného řetězce v kódování Base64. Tento řetězec je procedurou base64Decode() převeden na 72ti bitové binární číslo. Toto binární číslo v prvních 64 bitech obsahuje vlastní data a ve zbývajícím bytu je kontrolní suma. Vlastní datová část se po kontrole, zda byla správně zadána zašifruje pomocí smyčky:

while (n-- > 0) {
sum += delta
y += (((z << 4) + keyA) ^ (z + sum) ^ (((z >> 5) & 0x07FFFFFF) + keyB))
z += (((y << 4) + keyC) ^ (y + sum) ^ (((y >> 5) & 0x07FFFFFF) + keyD))
}

Jak již bylo řečeno TEA je iterační šifra, šifrovací smyčka se vykonává celkem 32krát. Vlastní 64ti bitová data jsou v algoritmu rozdělena, jak vyplývá z charakteru šifry, do 2 částí (x,y) po 32bitech. Rovněž klíč je rozdělen na 32bitové části (keyA, keyB, keyC, keyD).

Získaná zašifrovaná 64ti bitová data se doplní kontrolní sumou na 72bitů a převedou pomocí Base64Encode() na 12 znakový, tištitelný řetězec. Tento řetězec je vrácen serveru jako odpověď.

BASE64

Pro převod binárních dat do formy tištitelného řetězce je možno použít několika metod. Jednou z nejpoužívanějších je metoda BASE64, popsaná např. v RFC1341. BASE64, někdy též nazývaná Radix64 kódování, používá pro přenos transformaci založenou na převodu tří bytů (osmibitových znaků) na čtyři "šestibitové" znaky. Tyto šestibitové znaky jsou převedeny pomocí překladové tabulky na tištitelný tvar ve formě 7mi bitových (popř. 8mi bitových) ASCII znaků.

Kódování BASE64 používá tuto tabulku:

překladová_tabulka[0..63] = "ABCD...XYZabcd...xyz0123...789+/"

Demonstraci algoritmu BASE64, předvedeme na jeho implementaci v JavaScriptu od Roberta Graham, použitou v Javaskriptové verzi TEA autorizačního kalkulátoru. (Zde popisovaná verze byla v některých částech zjednodušena, pro obecné použití použijte prosím originál od jejího autora).

function base64ToAscii(c)
{
var result = 0;
if (0 <= c && c <= 25) { result = String.fromCharCode(c + 65); } // 65 = 'A'
else if (26 <= c && c <= 51) { result = String.fromCharCode(c - 26 + 97); } // 97 = 'a'
else if (52 <= c && c <= 61) { result = String.fromCharCode(c - 52 + 48); } // 48 = '0'
else if (c == 62) { result = '+'; }
else if( c == 63 ){ result = '/'; }
else { result = '='; }
return result;
}

Funkce base64ToAscii převádí 6ti bitovou vnitřní binární reprezentaci kódu BASE64 na jeho znakový, tištitelný, tvar.

function base64Encode(str)
{
var result = "";
var i = 0;
var sextet = 0;
var leftovers = 0;
var octet = 0;
for (i=0; i < str.length; i++) {
octet = str.charCodeAt(i);
switch( i % 3 ) {
case 0:
sextet = ( octet & 0xFC ) >> 2 ;
leftovers = octet & 0x03 ;
break;
case 1:
sextet = ( leftovers << 4 ) | ( ( octet & 0xF0 ) >> 4 );
leftovers = octet & 0x0F ;
break;
case 2:
sextet = ( leftovers << 2 ) | ( ( octet & 0xC0 ) >> 6 ) ;
leftovers = ( octet & 0x3F ) ;
break;
}
result = result + base64ToAscii(sextet);
if( (i % 3) == 2 ) result = result + base64ToAscii(leftovers);
}
return result.toString();
}

Base64 JavaScript implementation: Copyright © 2000 by Robert Graham (RobertGraham.com)

Funkce base64Encode je o něco složitější, v závislosti na pozici modulo 3 převádí jednotlivé trojice bytů na jejich BASE64 reprezentaci. Tato funkce je zjednodušená, a neuvažuje potřebné zarovnání délky převáděného stringu.

Implementace algoritmu TEA / Base64 v systému

Implementace obou algoritmů, nastíněná v předchozím odstavci Šifrovací algoritmus TEA je rozložena do celkem 5 modulů, která používají naše zařízení.

  • Base64encode - konvertujícímu trojici bytů na čtveřici znaků v Base64 representaci.
  • Base64decode - konvertující čtveřici znaků v Base64 reprezentaci na trojici bytů.
  • TEAcommon - pomocné aritmetické procedury, optimalizované pro moduly TEAencipher, TEAdecipher.
  • TEAencipher - zašifruje text, zadaný v 64bitové proměnné salt, zadaným klíčem.
  • TEAdecipher - odšifruje text, zadaný v 64bitové proměnné salt, zadaným klíčem.

Funkcí z těchto modulů, doplněné o funkci rand8, generující 8bytové náhodné číslo, využívá varinta funkce telnet/auth, která je výkonným modulem realizujícím přenos dat z TCP spojení z/do sériové linky. Autorizovaná verze telnetu používá principu vygenerování 8mi bytového náhodného čísla, doplnění kontrolní sumou a jeho odeslání jako sekvence 12 znaků v kódování Base64 protistraně. Těchto 12 znaků se posílá okamžitě po navázání spojení. Jako odpověď je vyžadováno od protistrany zaslání odpovědi získané zašifrováním zaslaného 8mi bytového náhodného čísla a jeho vrácení opět jako 12ti znakové zprávy v kódování Base64.

Zobrazme tuto situaci na ukázce Telnetového spojení klienta z Win98 (Tera Term Pro - IP 192.168.0.11) a našeho zařízení v roli Serveru (IP 192.168.0.8) ve funkci konvertoru Telnet 2 Serial se zapnutou TEA autorizací. Win98 si nejprve zjišťují MAC adresu serveru a poté standartním TCP handshakem otevírají spojení.

arp who-has 192.168.0.8 tell 192.168.0.11
arp reply 192.168.0.8 is-at 0:0:e8:ee:10:35
192.168.0.11.2041 > 192.168.0.8.23: S
192.168.0.8.23 > 192.168.0.11.2041: S ack
192.168.0.11.2041 > 192.168.0.8.23: . ack 1

Server po korektním otevření TCP/IP spojení "lustruje" klienta pomocí mechanismu popsaného v předchozích odstavcích. Odesílá proto náhodně vygenerovaná data ("sůl") jako výzvu pro ověření zda protistrana zná příslušný šifrovací klíč.

192.168.0.8.23 > 192.168.0.11.2041: P 1:13(12) ack 1
706c 4657 3359 6750 6f79 7478 "plFW3YgPoytx"

Po navázání spojení, tj. obvykle před vlastní odpovědí, zadanou uživatelem, klient telnetu předává pomocí mechanismu Network Virtual Terminal parametry spojení. (samozřejmě pouze pokud má Server zpracování NVT kódů povoleno, jinak jsou řídicí kódy považovány za platná data a autorizace je ukončena chybou!)

192.168.0.11.2041 > 192.168.0.8.23: P 1:16(15) ack 13
fffb 18 <WILL TERMINAL TYPE>
fffd 03 <DO SUPPRESS GO AHEAD>
fffb 03 <WILL SUPPRESS GO AHEAD>
fffd 01 <DO ECHO>
fffb 1f <WILL NAWS>
192.168.0.8.23 > 192.168.0.11.2041: . ack 16

Uživatel pomocí mechanismu Copy/Paste přenesl data z okna terminálu do autorizační kalkulačky a vypočtenou odpověď zpět pomocí Copy/Paste do okna terminálu. V případě, že přijatá odpověď nesouhlasí s kontrolním výpočtem v Serveru, je navázané spojení ukončeno. V tomto případě, jak je vidět z přijatého Ack od serveru, byla odpověď správná a spojení přechází do standartního režimu konverze sériové linky na Ethernet.

192.168.0.11.2041 > 192.168.0.8.23: P 16:28(12) ack 13
346b 6438 7852 4743 7734 6934 "4kd8xRGCw4i4"
192.168.0.8.23 > 192.168.0.11.2041: . ack 28

TEA autorizační kalkulačka v HTML / Javascript

Následuje textový výpis HTML stránky, která umožňuje počítat TEA autorizaci pomocí JAVASCRIPTu.

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>WEB51 autorization</title>
</head>
<body>
<h1>WEB51 autorization</h1>
<!-- last change 2002-AUG-1 -->
<!-- hhmts start -->
<SCRIPT><!--
/*
Base64
JavaScript implementation: Copyright (c) 2000 by Robert Graham (RobertGraham.com)
Tiny Encryption Algorithm
Algorithm: David Wheeler, Roger Needham, Cambridge University
www.ftp.cl.cam.ac.uk/ftp/papers/djw-rmn/djw-rmn-tea.html
JavaScript implementation: Radek Benedikt (benedikt@lphard.cz)
*/

// BEGIN of KEY
// in the next 4 lines is hardwired TEA key

var keyA = 0x01020304; //key 0.. 3
var keyB = 0x05060708; //key 4.. 7
var keyC = 0x090A0B0C; //key 8..11
var keyD = 0x0D0E0F10; //key 12..15

// END of KEY

function base64ToAscii(c)
{
var result = 0;
if (0 <= c && c <= 25) { result = String.fromCharCode(c + 65); } // 65 = 'A'
else if (26 <= c && c <= 51) { result = String.fromCharCode(c - 26 + 97); } // 97 = 'a'
else if (52 <= c && c <= 61) { result = String.fromCharCode(c - 52 + 48); } // 48 = '0'
else if (c == 62) { result = '+'; }
else if( c == 63 ){ result = '/'; }
else { result = '='; }
return result;
}

function base64Decode(str)
{
var result = "";
var i = 0;
var x = 0;
var y = 0;
var z = 0;
var count = -1;
for (i=0; i < str.length; i++) {
c = str.charAt(i);
if ('A' <= c && c <= 'Z') x = str.charCodeAt(i) - 65; // 65 = 'A'
else if ('a' <= c && c <= 'z') x = str.charCodeAt(i) - 97 + 26; // 97 = 'a'
else if ('0' <= c && c <= '9') x = str.charCodeAt(i) - 48 + 52; // 48 = '0'
else if (c == '+') x = 62;
else if (c == '/') x = 63;
else continue;
count++;
switch (count % 4) {
case 0:
y = x;
continue;
case 1:
z = (y << 2) | (x >> 4);
y = x & 0x0F;
break;
case 2:
z = (y << 4) | (x >> 2);
y = x & 0x03;
break;
case 3:
z = (y << 6) | x;
y = 0;
break;
}
result = result + String.fromCharCode(z);
}
return result.toString();
}

function base64Encode(str)
{
var result = "";
var i = 0;
var sextet = 0;
var leftovers = 0;
var octet = 0;
for (i=0; i < str.length; i++) {
octet = str.charCodeAt(i);
switch( i % 3 ) {
case 0:
sextet = ( octet & 0xFC ) >> 2 ;
leftovers = octet & 0x03 ;
break;
case 1:
sextet = ( leftovers << 4 ) | ( ( octet & 0xF0 ) >> 4 );
leftovers = octet & 0x0F ;
break;
case 2:
sextet = ( leftovers << 2 ) | ( ( octet & 0xC0 ) >> 6 ) ;
leftovers = ( octet & 0x3F ) ;
break;
}
result = result + base64ToAscii(sextet);
if( (i % 3) == 2 ) result = result + base64ToAscii(leftovers);
}
return result.toString();
}

function encipher(str)
{
var sum = 0;
var delta = 0x9E3779B9;
var n = 32;
var s = base64Decode(str);
var y = s.charCodeAt(3)+ (s.charCodeAt(2) << 8) + (s.charCodeAt(1) << 16) + (s.charCodeAt(0) << 24);
var z = s.charCodeAt(7)+ (s.charCodeAt(6) << 8) + (s.charCodeAt(5) << 16) + (s.charCodeAt(4) << 24);
var w;
if(str.length != 12) {
return "Missing character";
} else if((
(s.charCodeAt(0) + s.charCodeAt(1) + s.charCodeAt(2) +
s.charCodeAt(3) + s.charCodeAt(4) + s.charCodeAt(5) +
s.charCodeAt(6) + s.charCodeAt(7) + s.charCodeAt(8))
& 0xFF) != 0)
{
return "Checksum Error";
} else {
while (n-- > 0) {
sum += delta
y += (((z << 4) + keyA) ^ (z + sum) ^ (((z >> 5) & 0x07FFFFFF) + keyB))
z += (((y << 4) + keyC) ^ (y + sum) ^ (((y >> 5) & 0x07FFFFFF) + keyD))
}
w = (y>>24 & 0xFF) + (y>>16 & 0xFF) + (y>>8 & 0xFF) + (y & 0xFF) +
(z>>24 & 0xFF) + (z>>16 & 0xFF) + (z>>8 & 0xFF) + (z & 0xFF);
w &= 0xFF;
w = 0x100 - w;
s = (String.fromCharCode(y>>24 & 0xFF, y>>16 & 0xFF, y>>8 & 0xFF, y & 0xFF) +
String.fromCharCode(z>>24 & 0xFF, z>>16 & 0xFF, z>>8 & 0xFF, z & 0xFF) +
String.fromCharCode(w & 0xFF));
return base64Encode(s);
}
}

//-->
</SCRIPT>
<FORM name=myForm>
<INPUT type=text name=text1 size=16></INPUT>
<INPUT name=button1 onclick="this.form.text1.value=encipher(this.form.text1.value)" type=button value=Reply>
</FORM>
<!-- hhmts end -->
</body>
</html>

Popis výpočtu TEA v C++

Pro programování TEA algoritmu v C++ lze použít uvedený algoritmus, jehož použití funkcí pro TEA autorizaci spojení s našimi produkty ukazuje následující funkce:

void __fastcall TForm1::BtnTEAStartClick(TObject *Sender)
{
AnsiString PomStr;
unsigned char InBuf[64], OutBuf[65];
unsigned long y,z;
unsigned char CheckSum;
// Nastaveni klice
PomStr = "0x" + EKey1 -> Text;
TEAa = StrToInt(PomStr);
PomStr = "0x" + EKey2 -> Text;
TEAb = StrToInt(PomStr);
PomStr = "0x" + EKey3 -> Text;
TEAc = StrToInt(PomStr);
PomStr = "0x" + EKey4 -> Text;
TEAd = StrToInt(PomStr);


// Nacteni a dekodovani vstupniho retezce („soli“)
strcpy(InBuf, AutEdit -> Text.c_str());
base64Decode(InBuf, OutBuf, 12);
// Overeni kontrolniho souctu
CheckSum = OutBuf[0];
for (int i = 1; i < 9; i++)
CheckSum = CheckSum + OutBuf[i];
if (CheckSum)
{
AutEdit -> Text = "Chyba CRC vstupniho retezce";
return;
} // Zasifrovani „soli“


y=z=0;
preparekey(&y, &z, OutBuf+0);
updatekey(&y, &z, OutBuf+0);
// Vypocet kontrolniho souctu
CheckSum = 0;
for (int i = 0; i < 8; i++)
CheckSum = CheckSum + OutBuf[i];
OutBuf[8] = 256 - CheckSum;
OutBuf[9] = NULL;
// Zakodovani vystupniho retezce do Base64
base64Encode(OutBuf, InBuf, 9);
// V InBuf je vysledny autorizacni retezec, odesleme ho
ClientSocket1 -> Socket -> SendBuf(InBuf, 12);
}

V první části algoritmu, je převeden klíč z editačních boxů EKey1 až EKey4 do proměnných TEAa až TEAd. Tyto globální proměnné používají funkce TEA jako klíč. V editačním boxu AutEdit je „sůl“ vyslaná Serverem, kterou převede funkce base64Decode z kódu base64 na binární data do bufferu OutBuf. V následujícím cyklu je ověřen kontrolní součet. Pokud je kontrolní součet v pořádku, provede se vlastní zašifrování dat. Funkce preparekey provede výpočet proměnných y a z a funkce updatekey vlastní zašifrování dat. Poté je doplněn 9. byte - kontrolní součet. Voláním funkce base64Encode jsou data v bufferu OutBuf převedena na base64 a výsledek je uložen v bufferu InBuf. Data jsou odeslána Serveru a tím je ověření ukončeno.

 

Download

 
 

HW produkty podporující TEA autorizaci

  • PortBox
    Konvertor Ethernet na RS-232/485, podporuje Server i Client/Server režim, NVT, TEA autorizaci, "tunelování" RS-232 po TCP/IP i UDP/IP atd..  
  • PortStore
    Buffer 512/2048 kB RS-232 / Ethernet, ukládá data ze sériového portu do FLASH pamětí, při zaplnění kapacity upozorňuje ve dvou stupních emilem obsluhu.  
  • HW Virtual Serial Port
    Virtuální sériový port pro PortStore, PortBox a firmware konvertoru sériové linky na modulech Charon. HW VSP je určen pro Win 2000 a vyšší.  
  • Eth. I/O Controller
    Připojení binárních vstupů a výstupů přes Ethernet, spolu se sériovou linkou. Binární stavy lze vzdáleně pouze monitorovat (I/O Controller je v režimu Server), nebo krabička sama nahlásí změnu na vstupních pinech (režim Client/Server).  
  • Charon I module
    Vestavné moduly převodníků sériové linky na Ethernet, případně připojení měřicích přístrojů, SNMP rozhraní, teploměrů atd..