当前位置: 首页 > news >正文

模仿抖音用户ID加密ID的算法MB4E,提高自己平台ID安全性

先看抖音的格式 对ID加密的格式 MB4EENgLILJPeQKhJht-rjcc6y0ECMk_RGTceg6JBAA=

需求是 同一个ID 比如 413884936367560  每次获取得到的加密ID都是不同的,最终解密的ID都是413884936367560

注意这是一个加密后可解密原文的方式,不是单向加密

那么如下进行一个模仿。目前拆测 固定前缀MB4E和后缀BAA= 这俩要么和机房有关 要么就是和场景有关的一个标识性设置。

下面分别由Python和golang进行实现

记的安装 pip install pycryptodome

from Cryptodome.Cipher import AES
import base64
import os# 固定前缀和后缀  这俩要么和机房有关 要么就是和场景有关的一个标识性设置
PREFIX = "MB4EE"
SUFFIX = "BAA="# 密钥(假设为16字节)
KEY = b'1234567890123456'def pad(data):# PKCS7 填充padding_len = 16 - (len(data) % 16)return data + bytes([padding_len] * padding_len)def unpad(data):# 去除 PKCS7 填充return data[:-data[-1]]def encrypt_id(user_id):# 生成随机IV(16字节)iv = os.urandom(16)# 创建AES加密器cipher = AES.new(KEY, AES.MODE_CFB, iv)# 加密用户IDuser_id_bytes = user_id.to_bytes((user_id.bit_length() + 7) // 8, 'big')padded_user_id = pad(user_id_bytes)encrypted_id = cipher.encrypt(padded_user_id)# 将IV和加密结果编码为URL安全的Base64encoded_id = base64.urlsafe_b64encode(iv + encrypted_id).decode('utf-8')# 去除编码结果中的填充字符 '='encoded_id = encoded_id.rstrip('=')# 添加固定前缀和后缀sec_user_id = PREFIX + encoded_id + SUFFIXreturn sec_user_iddef decrypt_id(sec_user_id):# 去除固定前缀和后缀encoded_id = sec_user_id[len(PREFIX):-len(SUFFIX)]# 解码URL安全的Base64,并手动添加填充字符 '='padding_len = 4 - (len(encoded_id) % 4)encoded_id += '=' * padding_len# 解码Base64decoded_id = base64.urlsafe_b64decode(encoded_id)# 提取IV和加密结果iv = decoded_id[:16]encrypted_id = decoded_id[16:]# 创建AES解密器cipher = AES.new(KEY, AES.MODE_CFB, iv)# 解密用户IDpadded_user_id = cipher.decrypt(encrypted_id)user_id_bytes = unpad(padded_user_id)user_id = int.from_bytes(user_id_bytes, 'big')return user_id# 示例
user_id = 413884936367560
sec_user_id = encrypt_id(user_id)
print(f"Encrypted ID: {sec_user_id}")decrypted_id = decrypt_id(sec_user_id)
print(f"Decrypted ID: {decrypted_id}")

运行结果如下

go语言的实现

package mainimport ("crypto/aes""crypto/cipher""crypto/rand""encoding/base64""encoding/binary""errors""fmt""io""strings"
)// 固定前缀和后缀
const (PREFIX = "MB4EE"SUFFIX = "BAA="
)// 密钥(假设为16字节)
var key = []byte("1234567890123456")// 填充数据
func pad(data []byte) []byte {padding := aes.BlockSize - len(data)%aes.BlockSizepadtext := make([]byte, padding)for i := range padtext {padtext[i] = byte(padding)}return append(data, padtext...)
}// 去除填充数据
func unpad(data []byte) ([]byte, error) {length := len(data)unpadding := int(data[length-1])if unpadding > length {return nil, errors.New("unpad error. This could happen when incorrect encryption key is used")}return data[:(length - unpadding)], nil
}// 加密用户ID
func encryptID(userID int64) (string, error) {// 生成随机IV(16字节)iv := make([]byte, aes.BlockSize)if _, err := io.ReadFull(rand.Reader, iv); err != nil {return "", err}// 创建AES加密器block, err := aes.NewCipher(key)if err != nil {return "", err}// 加密用户IDuserIDBytes := make([]byte, 8)binary.BigEndian.PutUint64(userIDBytes, uint64(userID))paddedUserID := pad(userIDBytes)ciphertext := make([]byte, len(paddedUserID))mode := cipher.NewCFBEncrypter(block, iv)mode.XORKeyStream(ciphertext, paddedUserID)// 将IV和加密结果编码为URL安全的Base64encodedID := base64.URLEncoding.EncodeToString(append(iv, ciphertext...))// 去除编码结果中的填充字符 '='encodedID = strings.TrimRight(encodedID, "=")// 添加固定前缀和后缀secUserID := PREFIX + encodedID + SUFFIXreturn secUserID, nil
}// 解密用户ID
func decryptID(secUserID string) (int64, error) {// 去除固定前缀和后缀encodedID := secUserID[len(PREFIX) : len(secUserID)-len(SUFFIX)]// 解码URL安全的Base64,并手动添加填充字符 '='paddingLen := 4 - len(encodedID)%4encodedID += strings.Repeat("=", paddingLen)// 解码Base64decodedID, err := base64.URLEncoding.DecodeString(encodedID)if err != nil {return 0, err}// 提取IV和加密结果iv := decodedID[:aes.BlockSize]ciphertext := decodedID[aes.BlockSize:]// 创建AES解密器block, err := aes.NewCipher(key)if err != nil {return 0, err}// 解密用户IDmode := cipher.NewCFBDecrypter(block, iv)mode.XORKeyStream(ciphertext, ciphertext)paddedUserID, err := unpad(ciphertext)if err != nil {return 0, err}// 转换为int64userID := int64(binary.BigEndian.Uint64(paddedUserID))return userID, nil
}func main() {userID := int64(66015130374)secUserID, err := encryptID(userID)if err != nil {fmt.Println("Encrypt error:", err)return}fmt.Println("Encrypted ID:", secUserID)decryptedID, err := decryptID(secUserID)if err != nil {fmt.Println("Decrypt error:", err)return}fmt.Println("Decrypted ID:", decryptedID)
}

运行结果如下

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Java】网络编程-地址管理-IP协议后序-NAT机制-以太网MAC机制
  • Qt_自定义信号
  • QT+OSG+OSG-earth如何在窗口显示一个地球
  • 【在Linux世界中追寻伟大的One Piece】五种IO模型和阻塞IO
  • play-with-docker使用指南
  • redis集群创建问题处理
  • 数据结构-3.3.栈的链式存储实现
  • PCL 计算点云距离
  • Python 入门教程(4)数据类型 | 4.6、列表
  • Oracle从入门到放弃
  • Halo 开发者指南——项目运行、构建
  • AI绘画:科技赋能艺术的崭新时代
  • CAPL_构建基于UDS的刷写学习—01 Hex文件的解析
  • 详细介绍 Redis 列表的应用场景
  • Java语言程序设计基础篇_编程练习题*18.29(某个目录下的文件数目)
  • [译] 怎样写一个基础的编译器
  • angular学习第一篇-----环境搭建
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • Next.js之基础概念(二)
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • Python_OOP
  • Redis字符串类型内部编码剖析
  • springboot_database项目介绍
  • 爱情 北京女病人
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 成为一名优秀的Developer的书单
  • 大主子表关联的性能优化方法
  • 多线程事务回滚
  • 番外篇1:在Windows环境下安装JDK
  • 给新手的新浪微博 SDK 集成教程【一】
  • 微信开源mars源码分析1—上层samples分析
  • 原生JS动态加载JS、CSS文件及代码脚本
  • ######## golang各章节终篇索引 ########
  • #define 用法
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (回溯) LeetCode 131. 分割回文串
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (转)Google的Objective-C编码规范
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • ./和../以及/和~之间的区别
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET Core Web APi类库如何内嵌运行?
  • .NET Core 和 .NET Framework 中的 MEF2
  • .Net 代码性能 - (1)
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • @DataRedisTest测试redis从未如此丝滑
  • [ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042
  • [BUUCTF 2018]Online Tool
  • [BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)
  • [C#7] 1.Tuples(元组)
  • [C++]——带你学习类和对象
  • [DEBUG] spring boot-如何处理链接中的空格等特殊字符