美文网首页
PHP 内核源码 session_id 生成算法初入

PHP 内核源码 session_id 生成算法初入

作者: 过往云技 | 来源:发表于2019-01-12 02:21 被阅读0次

    PHP7 session_id 生成算法与 5.X 版本有很大区别

    /*
     * Note that we cannot use the BASE64 alphabet here, because
     * it contains "/" and "+": both are unacceptable for simple inclusion
     * into URLs.
     */
    
    static char hexconvtab[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,-";
    
    static void bin_to_readable(unsigned char *in, size_t inlen, char *out, size_t outlen, char nbits) /* {{{ */
    {
        unsigned char *p, *q;
        unsigned short w;
        int mask;
        int have;
    
        p = (unsigned char *)in;
        q = (unsigned char *)in + inlen;
    
        w = 0;
        have = 0;
        mask = (1 << nbits) - 1;
    
        while (outlen--) {
            if (have < nbits) {
                if (p < q) {
                    w |= *p++ << have;
                    have += 8;
                } else {
                    /* Should never happen. Input must be large enough. */
                    ZEND_ASSERT(0);
                    break;
                }
            }
    
            /* consume nbits */
            *out++ = hexconvtab[w & mask];
            w >>= nbits;
            have -= nbits;
        }
    
        *out = '\0';
    }
    /* }}} */
    
    #define PS_EXTRA_RAND_BYTES 60
    
    PHPAPI zend_string *php_session_create_id(PS_CREATE_SID_ARGS) /* {{{ */
    {
        unsigned char rbuf[PS_MAX_SID_LENGTH + PS_EXTRA_RAND_BYTES];
        zend_string *outid;
    
        /* It would be enough to read ceil(sid_length * sid_bits_per_character / 8) bytes here.
         * We read sid_length bytes instead for simplicity. */
        /* Read additional PS_EXTRA_RAND_BYTES just in case CSPRNG is not safe enough */
        if (php_random_bytes_throw(rbuf, PS(sid_length) + PS_EXTRA_RAND_BYTES) == FAILURE) {
            return NULL;
        }
    
        outid = zend_string_alloc(PS(sid_length), 0);
        bin_to_readable(
            rbuf, PS(sid_length),
            ZSTR_VAL(outid), ZSTR_LEN(outid),
            (char)PS(sid_bits_per_character));
    
        return outid;
    }
    /* }}} */
    

    php5.6 实现:MD5 / SHA1 / HASH

    PHPAPI char *php_session_create_id(PS_CREATE_SID_ARGS) /* {{{ */
    {
        PHP_MD5_CTX md5_context;
        PHP_SHA1_CTX sha1_context;
    #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH)
        void *hash_context = NULL;
    #endif
        unsigned char *digest;
        int digest_len;
        int j;
        char *buf, *outid;
        struct timeval tv;
        zval **array;
        zval **token;
        char *remote_addr = NULL;
    
        gettimeofday(&tv, NULL);
    
        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) == SUCCESS &&
            Z_TYPE_PP(token) == IS_STRING
        ) {
            remote_addr = Z_STRVAL_PP(token);
        }
    
        /* maximum 15+19+19+10 bytes */
        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);
    
        switch (PS(hash_func)) {
            case PS_HASH_FUNC_MD5:
                PHP_MD5Init(&md5_context);
                PHP_MD5Update(&md5_context, (unsigned char *) buf, strlen(buf));
                digest_len = 16;
                break;
            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_ops)) {
                    php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 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 */
            default:
                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid session hash function");
                efree(buf);
                return NULL;
        }
        efree(buf);
    
        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, MIN(toread, sizeof(rbuf))) == 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) && !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 <= 0) break;
    
                    switch (PS(hash_func)) {
                        case PS_HASH_FUNC_MD5:
                            PHP_MD5Update(&md5_context, rbuf, n);
                            break;
                        case PS_HASH_FUNC_SHA1:
                            PHP_SHA1Update(&sha1_context, rbuf, n);
                            break;
    #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH)
                        case PS_HASH_FUNC_OTHER:
                            PS(hash_ops)->hash_update(hash_context, rbuf, n);
                            break;
    #endif /* HAVE_HASH_EXT */
                    }
                    to_read -= n;
                }
                close(fd);
            }
    #endif
        }
    
        digest = emalloc(digest_len + 1);
        switch (PS(hash_func)) {
            case PS_HASH_FUNC_MD5:
                PHP_MD5Final(digest, &md5_context);
                break;
            case PS_HASH_FUNC_SHA1:
                PHP_SHA1Final(digest, &sha1_context);
                break;
    #if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH)
            case PS_HASH_FUNC_OTHER:
                PS(hash_ops)->hash_final(digest, hash_context);
                efree(hash_context);
                break;
    #endif /* HAVE_HASH_EXT */
        }
    
        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 range (should be 4, 5, or 6) - using 4 for now");
        }
    
        outid = emalloc((size_t)((digest_len + 2) * ((8.0f / PS(hash_bits_per_character)) + 0.5)));
        j = (int) (bin_to_readable((char *)digest, digest_len, outid, (char)PS(hash_bits_per_character)) - outid);
        efree(digest);
    
        if (newlen) {
            *newlen = j;
        }
    
        return outid;
    }
    /* }}} */
    

    相关文章

      网友评论

          本文标题:PHP 内核源码 session_id 生成算法初入

          本文链接:https://www.haomeiwen.com/subject/unkqdqtx.html