import base64
import socket
import struct
def decode_cookie(cookie):
"""decode a u cookie into an uid
:param cookie: a cookie value that will be decoded into a uid
:return: string representing the uid
This algorithm is for version 2 of http://wiki.nginx.org/HttpUseridModule.
This nginx module follows the apache mod_uid module algorithm, which is
documented here: http://www.lexa.ru/programs/mod-uid-eng.html.
"""
# get the raw binary value
binary_cookie = base64.b64decode(cookie)
# unpack into 4 parts, each a network byte orderd 32 bit unsigned int
unsigned_ints = struct.unpack('!4I', binary_cookie)
# convert from network (big-endian) to host byte (probably little-endian) order
host_byte_order_ints = [socket.ntohl(i) for i in unsigned_ints]
# convert to upper case hex value
uid = 'u=' + ''.join(['{0:08X}'.format(h) for h in host_byte_order_ints])
return uid
def encode_uid(uid):
"""encode an uid into a u cookie
:param uid: an uid that will be encoded into a cookie.
:return: string representing the u cookie
The algorithm is for version 2 of http://wiki.nginx.org/HttpUseridModule.
This nginx module follows the apache mod_uid module algorithm, which is
documented here: http://www.lexa.ru/programs/mod-uid-eng.html.
"""
# get the hex value of the uid
hex_value = uid.split('=')[1]
# convert 128 bit string into 4 32 bit integers
host_byte_order_ints = [int(hex_value[i:i+8], 16) for i in range(0, 32, 8)]
# convert from host byte (probably little-endian) to network byte (big-endian) order
unsigned_ints = [socket.htonl(i) for i in host_byte_order_ints]
# convert to raw binary value
binary_cookie = struct.pack('!4I', *unsigned_ints)
# get the base64 version of the cookie
cookie = base64.b64encode(binary_cookie)
return cookie
Parsing Nginx's http_userid_module cookie in Python
-
27-06-2022 - |
Frage
I've set nginx userid module to produce uid cookies on requests to the server for anonymous tracking, While everything goes as expected with setting the cookies, I can't figure out how these cookies should be parsed (in Python) for further analysis.
According the nginx's docs (http://nginx.org/en/docs/http/ngx_http_userid_module.html#userid_service) the http_userid_module is fully compliant with apache's mod_uid and according to apache's mod_uid docs (http://www.lexa.ru/programs/mod-uid-eng.html) the cookie value actually contains valuable data such as the timestamp the cookie was issued at.
the base64 decoding part is easy :) Was wondering if anyone here can help with the rest of the actions needed in order to parse the data in these cookies?
Lösung
Andere Tipps
Backport of @d3w4rd's answer in PHP just in case someone is looking for it.
class NginxUniqid
{
public static function decodeCookie($cookie)
{
return strtoupper(join('', array_map(function ($e) {
return str_pad(
base_convert($e, 10, 16),
8, '0', STR_PAD_LEFT
);
}, unpack('I4', base64_decode($cookie)))));
}
public static function encodeUid($hex)
{
return base64_encode(pack(
'I4',
base_convert(substr($hex, 0, 8), 16, 10),
base_convert(substr($hex, 8, 8), 16, 10),
base_convert(substr($hex, 16, 8), 16, 10),
base_convert(substr($hex, 24, 8), 16, 10)
));
}
}