Parsing PHP's default session_id generation algorithm

Source: Internet
Author: User
Tags session id sha1
As a web programmer, we are certainly not unfamiliar with the session, session ID is our respective on the server, a unique flag, this ID string can be generated automatically by PHP, or we can give. You may be like me, very concerned about the automatic generation of PHP ID string is how, the probability of conflict, and can not easily be calculated by others, so the following.

We download a copy of the php5.3.6 source code, enter the/ext/session directory, generate session ID function is located in the Session.c file 345 lines, the following details about this function. For the sake of understanding, I adjusted the order of some code.

Phpapi Char *php_session_create_id (Ps_create_sid_args)//* {{{{*/{//these rows define the data required for the hash function, directly over the ~php_md5_ctx Md5_context; Php_sha1_ctx sha1_context; #if defined (have_hash_ext) &&!defined (compile_dl_hash) void *hash_context;# endifunsigned Char *digest;int digest_len;int j;char *buf, *outid;zval **array;zval **token;//used to record $_server[' REMOTE_ The value of ADDR '] char *remote_addr = null;//a timeval structure used to record the current timestamp and the number of milliseconds struct Timeval tv;gettimeofday (&AMP;TV, NULL);//if possible, REMOTE_ADDR is assigned a value, in PHP pseudo-code is://if (isset ($_server[' remote_addr '))//{remote_addr = $_server[' remote_addr '];}         Note: In CLI mode there is no ~if (Zend_hash_find (&eg (symbol_table), "_server", sizeof ("_server"),         (void *) &array) = = SUCCESS && z_type_pp (array) = = Is_array && zend_hash_find ( Z_ARRVAL_PP (Array), "REMOTE_ADDR", sizeof ("REMOTE_ADDR"), (void * *) &token) = = Succes S) {remote_addr = z_strval_pp (token);} /* Maximum 15+19+19+10 bytes *Generate the required session ID, and, of course, subsequent processing ~//format is:%.15s%ld%ld%0.8f, the meaning of each paragraph is as follows://%.15s REMOTE_ADDR? REMOTE_ADDR: "" This line is easy to understand//%ld tv.tv_sec current timestamp//%ld (long int) tv.tv_usec current number of milliseconds//%0.8f PHP_COMBINED_LC G (Tsrmls_c) * 101 Random numbers spprintf (&buf, 0, "%.15s%ld%ld%0.8f", remote_addr? REMOTE_ADDR: "", tv.tv _sec, (long int) tv.tv_usec, PHP_COMBINED_LCG (tsrmls_c) * 10);//below the value of the BUF string to hash//Detect hash function in session configuration/*300 line: enum {ps_hash_func_md5, PS_HASH_FUNC_SHA1, Ps_hash_func_other};812 line: php_ini_entry ("se  Ssion.hash_function "," 0 ", Php_ini_all,onupdatehashfunc) 738 lines: Static PHP_INI_MH (Onupdatehashfunc) {... val    = Strtol (New_value, &endptr, 10);         if (endptr && (*endptr = = ')}) {/* Numeric value */PS (Hash_func) = val? 1:0;     return SUCCESS; }     ......     ...... The default value of PS (Hash_func) is 0, which is ps_hash_func_md5. */switch (PS (Hash_func)) {///if MD5, hash our BUF string with the MD5 algorithmProcessing.         Case Ps_hash_func_md5:php_md5init (&md5_context);         Php_md5update (&md5_context, (unsigned char *) buf, strlen (BUF));         Digest_len = 16;     Break     If it is SHA1, the SHA1 algorithm is used to hash our buf string.         Case Ps_hash_func_sha1:php_sha1init (&sha1_context);         Php_sha1update (&sha1_context, (unsigned char *) buf, strlen (BUF));         Digest_len = 20; Break, #if defined (have_hash_ext) &&!defined (Compile_dl_hash) Case Ps_hash_func_other:if (!ps (hash_op s) {php_error_docref (NULL tsrmls_cc, E_error, "Inva             Lid session hash function ");             Efree (BUF);         return NULL;         } Hash_context = Emalloc (PS (hash_ops)->context_size);         PS (Hash_ops)->hash_init (Hash_context);         PS (Hash_ops)->hash_update (Hash_context, (unsigned char *) buf, strlen (BUF)); Digest_len = PS (hash_ops)->digest_sizE Break, #endif/* have_hash_ext *//If there is no hash function, then an error, or e_error level, awkward ~ default:php_error_docref (NULL tsrmls_cc,         E_error, "Invalid session hash function");         Efree (BUF); return NULL;} Release buf~//embarrassing, that content, content has gone to our hash_context, such as Md5_context, Sha1_context ... Efree (BUF);/*session.entropy_file gives a path to an external resource (file) that will be used as an additional entropy resource in the session ID creation process. For example, in many Unix systems you can use/dev/random or/dev/urandom. SESSION.ENTROPY_LENGTH Specifies the number of bytes read from the above file. The default is 0 (disabled).     If entropy_length this configuration is greater than 0, then: */if (PS (entropy_length) > 0) {#ifdef php_win32 unsigned char rbuf[2048];     size_t toread = PS (entropy_length);             if (Php_win32_get_random_bytes (Rbuf, (size_t) toread) = = SUCCESS) {switch (PS (hash_func)) {                 Case Ps_hash_func_md5:php_md5update (&md5_context, Rbuf, toread);             Break                 Case Ps_hash_func_sha1:php_sha1update (&sha1_context, Rbuf, toread); break;# if defined (have_hash_ext) &Amp;&!defined (Compile_dl_hash) Case Ps_hash_func_other:ps (hash_ops)->hash_update (hash_                 Context, RBUF, toread);     break;# endif/* Have_hash_ext *}} #else int fd;     FD = Vcwd_open (PS (entropy_file), o_rdonly);         if (FD >= 0) {unsigned char rbuf[2048];         int n;         int to_read = PS (entropy_length);             while (To_read > 0) {n = read (FD, RBUF, MIN (to_read, sizeof (RBUF)));                     if (n hash_update (Hash_context, RBUF, N);         break; #endif/* Have_hash_ext */} To_read-= n;     } close (FD);         }//the logical #endif}//at the end of Entropy_length>0 is still part of the hash calculation, it seems our hash_final (Digest, Hash_context);         Efree (Hash_context); break; #endif/* Have_hash_ext */}/*session.hash_bits_per_character allows the user to define how many bits per character will be stored when converting binary hash data into a readable format. The possible values are ' 4 ' (0-9,a-f), ' 5 ' (0-9,a-v), and ' 6 ' (0-9,a-z,a-z, "-", ",").         */if (PS (Hash_bits_per_character) < 4||     PS (Hash_bits_per_character) > 6) {PS (hash_bits_per_character) = 4; Php_error_docref (NULL tsrmls_cc, e_warning, "The INI setting Hash_bits_per_character is out of RA Nge (should is 4, 5, or 6)-using 4 for Now ");} Our hashed binary data digest is represented in a readable form by a string and placed in the Outid string outid = Emalloc ((size_t) ((Digest_len + 2) * (8.0f/ps (hash_bits_per_ character))), j = (int) (Bin_to_readable ((char *) digest, Digest_len, Outid, (char) PS (hash_bits_per_character))-O Utid); Efree (Digest); if (Newlen) {*newlen = j;} return to Outidreturn Outid;}
  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.