<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Athlan • Piotr Pelczar • blog programisty &#187; md5</title>
	<atom:link href="http://athlan.pl/tag/md5/feed/" rel="self" type="application/rss+xml" />
	<link>http://athlan.pl</link>
	<description>Napisać kod zrozumiały dla komputera potrafi byle głupek. Dobrzy programiści tworzą kod zrozumiały dla człowieka...</description>
	<lastBuildDate>Sun, 12 Jun 2011 16:43:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Optymalizacja zapytań MySQL dla koniunkcji wielu danych</title>
		<link>http://athlan.pl/optymalizacja-zapytan-mysql/</link>
		<comments>http://athlan.pl/optymalizacja-zapytan-mysql/#comments</comments>
		<pubDate>Sat, 15 Jan 2011 15:54:17 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[Matematyka]]></category>
		<category><![CDATA[Optymalizacja]]></category>
		<category><![CDATA[php.pl]]></category>
		<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Przemyślenia]]></category>
		<category><![CDATA[Publikacje]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[InnoDB]]></category>
		<category><![CDATA[md5]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optymalizacja]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=670</guid>
		<description><![CDATA[Nie raz, nie dwa mieliśmy sytuację, która wymagała od nas koniunkcji warunków większej ilości danych lub dane te były tekstowe, ale niedługie. Niby nic, klucze załatwiają sprawę, ale sięgając do kodu gry bukmacherskiej, musiałem ją nieco zoptymalizować pod względem częstego wyciągania danych. Baza rozrosła się dość szybko, dlatego niezbędna była lekka modyfikacja jej struktury. Moim zadaniem było bardzo częste [...]]]></description>
			<content:encoded><![CDATA[<p>Nie raz, nie dwa mieliśmy sytuację, która wymagała od nas koniunkcji warunków większej ilości danych lub dane te były tekstowe, ale niedługie. Niby nic, klucze załatwiają sprawę, ale sięgając do kodu gry bukmacherskiej, musiałem ją nieco zoptymalizować pod względem częstego wyciągania danych. Baza rozrosła się dość szybko, dlatego niezbędna była lekka modyfikacja jej struktury.</p>
<p>Moim zadaniem było bardzo częste wyciągnięcie ID meczu, który musiał na raz (AND) być zgodny z żądaną datą, nazwą drużyny pierwszej oraz drugiej. Informacji do warunków dostarczał system. Oprócz daty, są to dane tekstowe, więc połączyłem je ze sobą <a href="http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_concat">CONCAT</a> i stworzyłem z nich sumę md5. Indeks, po którym baza szukała, był już krótszy od warunków, bo zawierał zawsze 32 znaki. Pierwszym warunkiem koniunkcji zawsze była suma md5 wymienionych wcześniej pól rekordu, nazwałem to <strong>suma kontrolna </strong><strong>rekordu</strong>, potem faktyczna wartość pól, aby w razie zdublowania sumy kontrolnej (czego się nie spodziewamy, bo zakres wariacji jest ogromny, ale dla idei) wybrać prawidłowy rekord. Do tej pory wystarczało&#8230;</p>
<p>Gdy baza rozrasta się, problemem staje się wyszukiwanie. O ile suma kontrolna to już krok w stronę optymalizacji, dla &gt;100k rekordów, baza danych potrzebowała co najmniej 0.05 sekundy na zwrócenie wyniku. Postanowiłem dodać <strong>odcisk palca sumy kontrolnej</strong>. Najlepszym rozwiązaniem okazało się <strong>dodanie jednego bajtu</strong>, który zrobił magię w bazie danych. Jedno pole TINYINT &#8211; 8 bitów, zakres 0-255 bez znaku. Założenia odcisku palca:</p>
<ul>
<li>jest wartością liczbową oraz zajmuje tylko jeden bajt, aby oszczędzić miejsca w rekordach oraz indeksach bazy danych,</li>
<li>nie musi być uniwersalny (unikalny), a jedynie grupować odciski palców w mniejsze, a liczniejsze zbiory.</li>
</ul>
<p>Rozwiązanie, które zastosowałem przy generowanu odcisku palca sumy kontrolnej, również nie jest skomplikowane:</p>
<ol>
<li><strong>Odcisk palca to suma kolejnych znaków sumy kontrolnej rekordu</strong>, gdzie 0 &#8211; 9 zachowują swoje wartości, a litery [a-f] przyjmują kolejno [10-15], dokładnie jak w przeliczaniu pojedynczych wyrazów systemu liczbowego o podstawie 16 (HEX) na dziesiętny.</li>
<li>Skoro jest to suma, to wartość minimalna jest dla samych zer, zatem <em>MIN</em> = 0.</li>
<li>Wartość maksymalną można stworzyć podając same maksymalne wartości F, zatem <em>MAX</em> = 480.</li>
<li>480 mieści się na 9 bitach (min. 2 bajty, zakres 0-65535 bez znaku, tracimy 65055 wartości), dzieląc liczbę przez 2 tracimy unikalność odcisku dwukrotnie, ale zmieścimy się na ośmiu bitach, czyli jednym bajcie &#8211; możemy użyć typu TINYINT (zakres 0-255 bez znaku, nasza to 0-240), zatem tracimy tylko 15 niewykorzystanych wartości.</li>
</ol>
<p><strong>Przeprowadzamy testy naszego rozwiązania.</strong></p>
<p>Stwórzmy przykładową tabelę danych <em>test_md5_index</em>, która będzie przechowywała wartości tekstowe w polach <em>data_content</em>, <em>data_content2</em>, <em>data_content3</em>. Tabela może zawierać pole dodatkowe, ale te trzy będziemy wykorzystywać w naszym wyszukiwaniu. Ważnym jest to, że warunkiem jest koniunkcja (AND), dlatego możemy stworzyć sumę (analogicznie do sumy logicznej) md5 jako odcisk palca tych pól, który zapiszemy w <em>data_sum</em> varchar(32). Dodatkowo stworzymy odcisk palca odcisku palca &#8211; jednobajtowe pole <em>data_sum_index</em> TINYINT.</p>
<p>Od razu zakładamy klucz podstawowy na <em>data_id</em> oraz klucz dla zapytania, który będzie go wykorzystywał, czyli szukanie wspólnie po <em>data_sum_index</em> oraz <em>data_sum</em>.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> test_md5_index <span style="color: #66cc66;">&#40;</span>
  data_id <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  data_sum_index tinyint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  data_sum <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">32</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  data_contents text <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  data_contents2 text <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  data_contents3 text <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span>data_id<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">KEY</span> data_index <span style="color: #66cc66;">&#40;</span>data_sum_index<span style="color: #66cc66;">,</span> data_sum<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>utf8 <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span>;</pre></div></div>

<p>Pora stworzyć funkcję, która przeliczy nam nowy, krótszy odcisk palca na podstawie poprzedniego:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">FUNCTION</span> TestIndexChecksum<span style="color: #66cc66;">&#40;</span>sSum <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">32</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">RETURNS</span> TINYINT
<span style="color: #993333; font-weight: bold;">BEGIN</span>
&nbsp;
  <span style="color: #993333; font-weight: bold;">DECLARE</span> sSumPart <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #993333; font-weight: bold;">DECLARE</span> iSumPart TINYINT;
  <span style="color: #993333; font-weight: bold;">DECLARE</span> iSum <span style="color: #993333; font-weight: bold;">SMALLINT</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #cc66cc;">0</span>;
  <span style="color: #993333; font-weight: bold;">DECLARE</span> i <span style="color: #993333; font-weight: bold;">INT</span>;
&nbsp;
  <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> sSum <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">REGEXP</span> <span style="color: #ff0000;">'^([a-z0-9]){32}$'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">THEN</span> <span style="color: #993333; font-weight: bold;">RETURN</span> <span style="color: #cc66cc;">0</span>; <span style="color: #993333; font-weight: bold;">END</span> <span style="color: #993333; font-weight: bold;">IF</span>;
&nbsp;
  <span style="color: #993333; font-weight: bold;">SET</span> i <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
&nbsp;
  WHILE i &amp;lt;<span style="color: #66cc66;">=</span> <span style="color: #993333; font-weight: bold;">LENGTH</span><span style="color: #66cc66;">&#40;</span>sSum<span style="color: #66cc66;">&#41;</span> DO
    <span style="color: #993333; font-weight: bold;">SET</span> sSumPart <span style="color: #66cc66;">=</span> SUBSTR<span style="color: #66cc66;">&#40;</span>sSum<span style="color: #66cc66;">,</span> i<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #993333; font-weight: bold;">SET</span> iSumPart <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">CASE</span> <span style="color: #993333; font-weight: bold;">WHEN</span> sSumPart <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'a'</span> <span style="color: #993333; font-weight: bold;">THEN</span> <span style="color: #cc66cc;">10</span> <span style="color: #993333; font-weight: bold;">WHEN</span> sSumPart <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'b'</span> <span style="color: #993333; font-weight: bold;">THEN</span> <span style="color: #cc66cc;">11</span> <span style="color: #993333; font-weight: bold;">WHEN</span> sSumPart <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'c'</span> <span style="color: #993333; font-weight: bold;">THEN</span> <span style="color: #cc66cc;">12</span> <span style="color: #993333; font-weight: bold;">WHEN</span> sSumPart <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'d'</span> <span style="color: #993333; font-weight: bold;">THEN</span> <span style="color: #cc66cc;">13</span> <span style="color: #993333; font-weight: bold;">WHEN</span> sSumPart <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'e'</span> <span style="color: #993333; font-weight: bold;">THEN</span> <span style="color: #cc66cc;">14</span> <span style="color: #993333; font-weight: bold;">WHEN</span> sSumPart <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'f'</span> <span style="color: #993333; font-weight: bold;">THEN</span> <span style="color: #cc66cc;">15</span> <span style="color: #993333; font-weight: bold;">ELSE</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">END</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #993333; font-weight: bold;">IF</span> iSumPart <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span> <span style="color: #993333; font-weight: bold;">THEN</span>
      <span style="color: #993333; font-weight: bold;">SET</span> iSumPart <span style="color: #66cc66;">=</span> sSumPart;
    <span style="color: #993333; font-weight: bold;">END</span> <span style="color: #993333; font-weight: bold;">IF</span>;
&nbsp;
    <span style="color: #993333; font-weight: bold;">SET</span> iSum <span style="color: #66cc66;">=</span> iSum <span style="color: #66cc66;">+</span> iSumPart;
    <span style="color: #993333; font-weight: bold;">SET</span> i <span style="color: #66cc66;">=</span> i <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span>;
  <span style="color: #993333; font-weight: bold;">END</span> WHILE;
&nbsp;
  <span style="color: #993333; font-weight: bold;">RETURN</span> iSum <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">2</span>;
<span style="color: #993333; font-weight: bold;">END</span>;</pre></div></div>

<p>Aby przeprowadzać testy, stwórzmy sobie procedurę, która wstawi nam N losowo, jakkolwiek wypełnionych rekordów do bazy danych:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">PROCEDURE</span> TestIndexesPrepareTest<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">IN</span> i <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">BEGIN</span>
  <span style="color: #993333; font-weight: bold;">TRUNCATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> test_md5_index;
&nbsp;
  WHILE i &amp;gt; <span style="color: #cc66cc;">0</span> DO
&nbsp;
    <span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> test_md5_index <span style="color: #993333; font-weight: bold;">SET</span>
      data_contents  <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">REPLACE</span><span style="color: #66cc66;">&#40;</span>CONCAT<span style="color: #66cc66;">&#40;</span>RAND<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">32</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;.&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
      data_contents2 <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">REPLACE</span><span style="color: #66cc66;">&#40;</span>CONCAT<span style="color: #66cc66;">&#40;</span>RAND<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">32</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;.&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
      data_contents3 <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">REPLACE</span><span style="color: #66cc66;">&#40;</span>CONCAT<span style="color: #66cc66;">&#40;</span>RAND<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">32</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;.&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
      data_sum <span style="color: #66cc66;">=</span> CONCAT<span style="color: #66cc66;">&#40;</span>data_contents<span style="color: #66cc66;">,</span> data_contents2<span style="color: #66cc66;">,</span> data_contents3<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
      data_sum_index <span style="color: #66cc66;">=</span> TestIndexChecksum<span style="color: #66cc66;">&#40;</span>data_sum<span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #993333; font-weight: bold;">SET</span> i <span style="color: #66cc66;">=</span> i <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span>;
  <span style="color: #993333; font-weight: bold;">END</span> WHILE;
<span style="color: #993333; font-weight: bold;">END</span>;</pre></div></div>

<p>Po wykonaniu <code>CALL TestIndexesPrepareTest(100000)</code> mamy przygotowane małe środowisko testowe.</p>
<p>Przygotujmy kilka zapytań do bazy danych, wybieramy losowy rekord, na którym będziemy testowali wyniki. Wykonujemy zapytanie z ręcznie wpisaną wartością warunku wybranego rekordu, sprawdźmy, jak szybko zostanie odnaleziony:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> test_md5_index <span style="color: #993333; font-weight: bold;">WHERE</span> data_sum <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;24045771412594250684228176888212&quot;</span>;</pre></div></div>

<p><em>Average: ~0.0506 sec</em></p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> test_md5_index <span style="color: #993333; font-weight: bold;">WHERE</span> data_sum_index <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">68</span> <span style="color: #993333; font-weight: bold;">AND</span> data_sum <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;24045771412594250684228176888212&quot;</span>;</pre></div></div>

<p><em>Average: ~0.0004 sec </em>(<strong>UWAGA!</strong> Specjalnie w warunku nie użyłem zwróconej warości funkcji, tylko dałem ją na sztywno, ręcznie wpisaną &#8211; funkcja by była wykonywana dla każdego porównania rekordu z osobna!).</p>
<p>Nasze zapytanie działa znacznie szybciej (~120 razy dla 100k rekordów) kosztem niewielkiej pamięci &#8211; po 1 bajcie do rekordu oraz po 1 bajcie do jego indeksu.</p>
<p>Zapewne istnieją szybkie silniki indeksowania danych, natomiast, gdy jesteśmy skazani np. na InnoDB z założeń technicznych &#8211; nie oznacza, że się nie da.</p>
<p>Mam nadzieję, że komuś się przyda.</p>
]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/optymalizacja-zapytan-mysql/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Hashowanie haseł z solą</title>
		<link>http://athlan.pl/hashowanie-hasel-z-sola/</link>
		<comments>http://athlan.pl/hashowanie-hasel-z-sola/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 18:50:26 +0000</pubDate>
		<dc:creator>Athlan</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Planeta]]></category>
		<category><![CDATA[Publikacje]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[md5]]></category>
		<category><![CDATA[sha1]]></category>

		<guid isPermaLink="false">http://athlan.pl/?p=150</guid>
		<description><![CDATA[Przeglądając forum.php.pl często widziałem, jak użytkownicy przechowują hasła w swoich bazach danych. Najczęściej używają funkcji hashujących md5, sha1 i sha2. Wszystko wygląda bardzo dobrze, hasła są przechowywanie bezpiecznie. No właśnie&#8230; na ile bezpiecznie. Nie będę tutaj rozwodził się nad zabezpieczeniem baz danych, w których owa baza haseł się znajduje, ale nad samym zahashowanym ciągu. Wszyscy [...]]]></description>
			<content:encoded><![CDATA[<p>Przeglądając forum.php.pl często widziałem, jak użytkownicy przechowują hasła w swoich bazach danych. Najczęściej używają funkcji hashujących <code>md5</code>, <code>sha1</code> i <code>sha2</code>. Wszystko wygląda bardzo dobrze, hasła są przechowywanie bezpiecznie. No właśnie&#8230; na ile bezpiecznie.</p>
<p>Nie będę tutaj rozwodził się nad zabezpieczeniem baz danych, w których owa baza haseł się znajduje, ale nad samym zahashowanym ciągu. Wszyscy doskonale wiemy, że istnieją bazy md5 (sha1, sha2 również).</p>
<p><em>Przezorny zawsze ubezpieczony.</em> Wiadomo, że nigdy nic nie wiadomo.</p>
<p>Pokażę, jak dodatkowo zabezpieczyć nasze hasła. Będą przechowywane w tej samej bazie danych, używając tych samych metod hashowania, a jednak szansa na &#8220;złamanie&#8221; hasła (wyszukania w bazie) będzie niemożliwa. Posłużymy się ciągiem znaków zwanym przez programistów <em>solą </em>(<em>salt</em>). Przykład implementacji możemy znaleźć w forum IPB, natomiast phpBB pozbawione jest tego <span style="text-decoration: line-through;">fjuczuru</span> ficzera. Cała sprawa sprowadza się do wygenerowania dowolnego kawałka ciągu znaków i doklejenia go do hasła. Sól potrzebna nam będzie również przy porównaniu hasła, więc trzeba ją zapisać w bazie danych obok hasła.</p>
<p>Poniżej zamieszczam przykładową klasę, która obsługuje solenie haseł. Doklejanie soli może być napisane w dowolny sposób, zależy to od Waszej wyobraźni. Ja dodatkowo dodałem element &#8220;losowy&#8221; w postaci doklejenia do soli wyniku działania funkcji microtime().</p>
<ul>
<li><a href="http://athlan.pl/code/PassSalt">Klasa, która soli hasła.</a></li>
<li><a href="http://athlan.pl/code/PassSaltExample">Przykład</a> &#8211; zapisywanie hasła do bazy danych oraz sprawdzanie go przy logowaniu.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://athlan.pl/hashowanie-hasel-z-sola/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
