Portál AbcLinuxu, 12. května 2025 15:30

Dotaz: Nefunguje ověřování hesel pomocí fce crypt pro ext_des v php

25.8.2010 14:03 ssorrenn
Nefunguje ověřování hesel pomocí fce crypt pro ext_des v php
Přečteno: 406×
Odpovědět | Admin
Pomocí příkladu ze stránek php ověřuji řetězce generované fcí crypt tak, že takto generovaný řetězec přidám jako salt fci crypt. Funguje to pro všechny algoritmy kromě EXT_DES. Při použití tohoto algoritmu jsou potom řetězce různé např.:
vstupní: _U9..vnIfeJymPPkVwPU
výstupní: _UbD.ypiMD0vw
V čem je problém?

Řešení dotazu:


Nástroje: Začni sledovat (1) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

25.8.2010 17:05 Messa | skóre: 39 | blog: Messa
Rozbalit Rozbalit vše Re: Nefunguje ověřování hesel pomocí fce crypt pro ext_des v php
Odpovědět | | Sbalit | Link | Blokovat | Admin
Co znamená "že takto generovaný řetězec přidám jako salt fci crypt"? Pokud je pokaždé jiný salt, pak není až tak divné, že je pokaždé jiný výstup...
25.8.2010 17:14 ssorrenn
Rozbalit Rozbalit vše Re: Nefunguje ověřování hesel pomocí fce crypt pro ext_des v php
Viz. php.net example:
<?php
$password = crypt('mypassword'); // let the salt be automatically generated

/* You should pass the entire results of crypt() as the salt for comparing a
   password, to avoid problems when different hashing algorithms are used. (As
   it says above, standard DES-based password hashing uses a 2-character salt,
   but MD5-based hashing uses 12.) */
if (crypt($user_input, $password) == $password) {
   echo "Password verified!";
}
?>
Pokud funkcí crypt vygeneruju jakýkoliv hash kromě extended-des tak se to dá takto ověřit. Pro extended-des to nefunguje:

$password = crypt('retezec', '_U9..dCaX');
(crypt('retezec', $password) == $password) : toto je vždy FALSE
25.8.2010 18:02 Messa | skóre: 39 | blog: Messa
Rozbalit Rozbalit vše Re: Nefunguje ověřování hesel pomocí fce crypt pro ext_des v php
Jo tak, ono se to takto opravdu má používat :) Vlastně bych to měl i znát, je to jen obal nad standardním systémovým voláním crypt, kterým se kryptují i uživatelská hesla.

Jakou máš verzi glibc? Na mém systému (Debian testing) je ve skutečnosti eglibc, který vypadá, že ext DES neumí, ale tváří se, nebo si PHP myslí, že umí. V Debianu stable mi PHP samo dává vědět, že ext DES k dispozici není (CRYPT_EXT_DES je 0).
25.8.2010 19:14 ssorrenn
Rozbalit Rozbalit vše Re: Nefunguje ověřování hesel pomocí fce crypt pro ext_des v php
eglibc 2.11 v ubuntu 10.04. Detekcí toho, zda daný algoritmus php zvládá jsem se ani netrápil, protože od php 5.3.0 má zvládat všechny i ty které přímo nepodporuje systém. Nicméně extended-des to asi umí, protože podle php.net je daný řetězec podobný tomu co tam mají jako příklad.
25.8.2010 20:56 ssorrenn
Rozbalit Rozbalit vše Re: Nefunguje ověřování hesel pomocí fce crypt pro ext_des v php
No pokud provedu ověření s hashem tak, že pomocí substr($hash,0,9) vyseparuji salt tak to funguje. Jenže proč u ostatních algoritmů mohu předhodit celý hash a u tohoto algoritmu jen salt?
26.8.2010 01:10 Messa | skóre: 39 | blog: Messa
Rozbalit Rozbalit vše Re: Nefunguje ověřování hesel pomocí fce crypt pro ext_des v php
Tak, vyhrabal jsem obraz Ubuntu, patchnul zdrojáky PHP debian/patches/php_crypt_revamped.patch a copak nevidím v ext/standard/crypt.c:
		if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$') {
			/* CRYPT_MD5 */
#if PHP_MD5_CRYPT
# warning Using system MD5 crypt function, which is OK on Debian system
# if PHP_USE_SYSTEM_CRYPT_R
			crypt_res = crypt_r(str, salt, &buffer);
# else
			crypt_res = crypt(str, salt);
# endif
#elif PHP_USE_PHP_CRYPT_R
# error Using PHP MD5 crypt function, should not happen on Debian system
			crypt_res = php_md5_crypt_r(str, salt, output);
#endif
		} else if (salt[0]=='$' && salt[1]=='6' && salt[2]=='$') {
			/* CRYPT_SHA512 */
#if PHP_SHA512_CRYPT
# warning Using system SHA512 crypt function, which is OK on Debian system
# if PHP_USE_SYSTEM_CRYPT_R
			crypt_res = crypt_r(str, salt, &buffer);
# else
			crypt_res = crypt(str, salt);
# endif
#elif PHP_USE_PHP_CRYPT_R
# error Using PHP SHA512 crypt function, should not happen on Debian system
			crypt_res = php_sha512_crypt_r(str, salt, output, sizeof(output));
#endif
		} else if (salt[0]=='$' && salt[1]=='5' && salt[2]=='$') {
			/* CRYPT_SHA256 */
#if PHP_SHA256_CRYPT
# warning Using system SHA256 crypt function, which is OK on Debian system
# if PHP_USE_SYSTEM_CRYPT_R
			crypt_res = crypt_r(str, salt, &buffer);
# else
			crypt_res = crypt(str, salt);
# endif
#elif PHP_USE_PHP_CRYPT_R
# error Using PHP SHA256 crypt function, should not happen on Debian system
			crypt_res = php_sha256_crypt_r(str, salt, output, sizeof(output));
#endif
		} else if (
				salt[0] == '$' &&
				salt[1] == '2' &&
				salt[2] == 'a' &&
				salt[3] == '$' &&
				salt[6] == '$' &&
				((salt[4] == '0' &&
				  salt[5] >= '4' && salt[5] <= '9') ||
				 (salt[4] >= '1' && salt[4] <= '2' &&
				  salt[5] >= '0' && salt[5] <= '9') ||
				 (salt[4] == '3' &&
				  salt[5] >= '0' && salt[5] <= '1'))) {
			/* CRYPT_BLOWFISH */
#if PHP_BLOWFISH_CRYPT
# error Using system BlowFish crypt function, should not happen on Debian system
# if PHP_USE_SYSTEM_CRYPT_R
			crypt_res = crypt_r(str, salt, &buffer);
# else
			crypt_res = crypt(str, salt);
# endif
#elif PHP_USE_PHP_CRYPT_R
# warning Using PHP BlowFish crypt function, which is OK on Debian system
			crypt_res = php_crypt_blowfish_rn(str, salt, output, sizeof(output));
#endif
		} else if (salt[0]=='_' && 
				   salt_len == 9) {
			/* CRYPT_EXT_DES */
#if PHP_EXT_DES_CRYPT
# error Using system extended DES crypt function, should not happen on Debian system
# if PHP_USE_SYSTEM_CRYPT_R
			crypt_res = crypt_r(str, salt, &buffer);
# else
			crypt_res = crypt(str, salt);
# endif
#elif PHP_USE_PHP_CRYPT_R
# warning Using PHP extended DES crypt function, which is OK on Debian system
			_crypt_extended_init_r();
			crypt_res = _crypt_extended_r(str, salt, &extended_buffer);
#endif
		} else {
			/* CRYPT_STD_DES */
#if PHP_STD_DES_CRYPT
# warning Using system standard DES crypt function, which is OK on Debian system
# if PHP_USE_SYSTEM_CRYPT_R
			crypt_res = crypt_r(str, salt, &buffer);
# else
			crypt_res = crypt(str, salt);
# endif
#elif PHP_USE_PHP_CRYPT_R
# error Using PHP standard DES crypt function, should not happen on Debian system
			_crypt_extended_init_r();
			crypt_res = _crypt_extended_r(str, salt, &extended_buffer);
#endif
		}
Jak je na první pohled jasné, zatímco u standardního DES a u saltů s dolary to funguje, i když je samotný hash součástí saltu, tak zrovna u extended DES se testuje, zda je délka hashe přesně 9. Pokud je 9, zavolá se funkce _crypt_extended_r, která extended DES umí. No a pokud není délka 9, použije se postup pro standardní DES - což je právě volání systémového crypt, který extended DES neumí. (To, že se to volá přesně takto, jsem si ověřil debuggerem.)

V upstream zdrojovych kodech PHP je tato část jinak - tam by ext des nejspíš buď fungovalo, nebo nefungovalo vůbec :).

Jako oprava by stačilo odstranění salt_len == 9 - v saltu standardního DESu by podtržítko být nemělo, takže standardní DES se od extended pozná i tak.

Není mi moc jasné, kde přesně se ty patche berou, tak nevím, komu můžeš poděkovat - zda maintainerům Debianu, nebo PHP.
26.8.2010 02:31 ssorrenn
Rozbalit Rozbalit vše Re: Nefunguje ověřování hesel pomocí fce crypt pro ext_des v php
Děkuju moc. Z toho plyne zásadní věc: při každém provádění php skriptů na začátku kontrolovat funkčnost jednotlivých algoritmů. Těch 0.1 sekundy navíc už přežiju.

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.