pycryptodome AES-GCM加密生成临时ticket python脚本

#!/usr/bin/env python  
# -*- coding:utf-8 -*-  
import base64
import binascii
import hashlib
import struct
import random
import time

from Crypto.Cipher import AES

SALTS = ["00000000000000000000000000000000",
         "11111111111111111111111111111111",
         "22222222222222222222222222222222",
         "33333333333333333333333333333333",
         "44444444444444444444444444444444",
         "55555555555555555555555555555555",
         "66666666666666666666666666666666",
         "77777777777777777777777777777777",
         "88888888888888888888888888888888",
         "99999999999999999999999999999999"]

ENV = {
    'dev': 1,
    'test': 2,
    'stg': 3,
    'prod': 4,
}


# 注意业务字段event_id,为长度为32位的16进制字符串
def generate_ticket(env: str, account_id: int, event_id: str):
    env_int = ENV[env]
    create_time = int(time.time())
    expire_time = create_time + 2 * 60 * 60  # ticket有效期2小时
    first_char = ord(event_id[0])
    salt = SALTS[abs(first_char % len(SALTS))]
    event_type = 1  # 事件类型(业务字段)

	# account_id + event_id + salt 用于生成AES key和iv(GCM使用nonce)
    message = str(account_id) + event_id + salt
    hash_str = hashlib.sha256(message.encode('utf-8')).digest()
    length = int(len(hash_str) / 2)
    # 前16字节作为key
    aes_key = hash_str[:length]
    # 后16字节作为iv(GCM为nonce)
    aes_iv = hash_str[length:]
    cipher = AES.new(aes_key, AES.MODE_GCM, aes_iv)

    digest = str(account_id) + event_id + str(create_time) + str(expire_time) + str(env_int) + str(event_type) + salt
    digest_sha = hashlib.sha256(digest.encode('utf-8')).digest()

	# 待加密字符串由以下参数拼接而成,各字段占用的比特数依次为“i16siibb2s4s”
    # binascii.unhexlify(event_id) 等价于 int(event_id, 16).to_bytes(length=16, byteorder='big')
    sensitive_data = struct.pack(">i16siibb2s4s", account_id, binascii.unhexlify(event_id), create_time, expire_time, env_int, event_type, random.randbytes(2), digest_sha[-4:])
    params, tag = cipher.encrypt_and_digest(sensitive_data)
    base64_data = params + tag
    return base64.b64encode(base64_data).decode('utf-8')


if __name__ == '__main__':
    print('Token_' + generate_ticket('dev', 88888888, 'ffffffffffffffffffffffffffffffff'))


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值