keystone fernet token(gAAAAA开头的token)反向解析

版权声明:原创文章,转载注明出处! https://blog.csdn.net/u010317005/article/details/81218681

keystone的token分成很多种,其中一种是fernet token,是无需存库的,直接将信息加密成一串字符串,形如

gAAAAABbWVmgqmOqekHLGAP5-JjSIE_-cGzKZYeADNMmEu0d6nGvZ2rBMgN7EvAGHSkrcOo3JourXwz9TG6zIrsxWBxK4iK6B2I6zBL7a-s9bHAb0qqUSwGqXRoIiZdCHfN58HgqQZQcxPznAJhVOVBwFE0-qrG3oOXa5DR3p_Xii1_r7YQeti1QzojY1LhIICkLwMAWPaV-

下述是根据阅读源码编写的一个反向解析token的脚本,目前只支持解析ProjectScoped fernet token,其他类型的fernet token可自行研究

import os
import six
from cryptography import fernet
import msgpack
import uuid
import time
import base64
import sys

token= sys.argv[1] if len(sys.argv) > 1 else None
if not token:
    print("please input a token")
    exit()

def load_keys():
    # build a dictionary of key_number:encryption_key pairs
    keys = dict()
    for filename in os.listdir("/etc/keystone/fernet-keys/"):
        path = os.path.join("/etc/keystone/fernet-keys/", str(filename))
        if os.path.isfile(path):
            with open(path, 'r') as key_file:
                try:
                    key_id = int(filename)
                except ValueError:
                    pass
                else:
                    keys[key_id] = key_file.read()

    return [keys[x] for x in sorted(keys.keys(), reverse=True)]

def convert_uuid_bytes_to_hex(uuid_byte_string):
    uuid_obj = uuid.UUID(bytes=uuid_byte_string)
    return uuid_obj.hex

def base64_encode(s):
    """Encode a URL-safe string."""
    return base64.urlsafe_b64encode(s).rstrip('=')


def disassemble(payload):
    (is_stored_as_bytes, user_id) = payload[0]
    if is_stored_as_bytes:
        user_id = "user_id = " + convert_uuid_bytes_to_hex(user_id)
    methods = "method = " + str((payload[1]))
    (is_stored_as_bytes, project_id) = payload[2]
    if is_stored_as_bytes:
        project_id = "project_id = " + convert_uuid_bytes_to_hex(project_id)
    expires_at_str = "expired_at = " + time.strftime("%Y-%m-%d %H:%M:%S",time.localtime((payload[3])))
    audit_ids =  list(map(base64_encode,payload[4]))
    return (user_id, project_id, expires_at_str,audit_ids)


def decoder(token):
    token = six.binary_type(token)
    mod_returned = len(token) % 4
    if mod_returned:
        missing_padding = 4 - mod_returned
        token += b'=' * missing_padding
    keys = load_keys()
    fernet_instances = [fernet.Fernet(key) for key in keys]
    serialized_payload =  fernet.MultiFernet(fernet_instances).decrypt(token)
    # payload format: (version,user_id,method,vertion_data,audit_ids)
    payload = msgpack.unpackb(serialized_payload)
    print("raw token info:\n%s" % payload)
    # version 2 is ProjectScopedPayload ,see keystone/token/providers/fernet/token_formatters.py
    if payload[0] == 2:
        return disassemble(payload[1:])
    else:
        return None

res = decoder(token)
if not res:
    print("could only resolve ProjectScopedPayload!")
    exit()
print("=================================================\nunpack token:")
for i in res:
    print(i)

解析示例:

猜你喜欢

转载自blog.csdn.net/u010317005/article/details/81218681