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

devtools/2024/9/22 19:19:23/

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

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

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

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

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

记的安装 pip install pycryptodome

python">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)
}

运行结果如下


http://www.ppmy.cn/devtools/115611.html

相关文章

软件卸载工具(windows系统)-geek

有时候软件卸载会很麻烦,使用geek会比较方便。但是针对一些特别大的软件,geek也好像会稍微费点劲(比如MATLAB2022A),不过针对一般常规软件的卸载,geek就可以有效地完全卸载了,使用方法也很简单,…

NoSql数据库Redis知识点

数据库的分类 关系型数据库 ,是建立在关系模型基础上的数据库,其借助于集合代数等数学概念和方法来处理数据库 中的数据主流的 MySQL 、 Oracle 、 MS SQL Server 和 DB2 都属于这类传统数据库。 NoSQL 数据库 ,全称为 Not Only SQL &a…

10年408考研真题-数据结构

23.[2010统考真题]若元素 a,b,c,d,e,f 依次进栈,允许进栈、退栈操作交替进行,但不允许连续3次进行退栈操作,不可能得到的出栈序列是(D)。 A.dcebfa B.cbdaef C.bcaefd D.afedcb 解析: 直接看D选项&#xff0…

数据结构 第三章 栈和队列 练习题3.2.5 表达式求值 C语言代码

本代码没有处理某个数字为负数的情况,感兴趣的小伙伴可以分享自己的思路和代码 #include <stdio.h> #include <stdlib.h> #include <ctype.h>#define MAX_SIZE 100int numStk[MAX_SIZE], num_hh 0; char opStk[MAX_SIZE], op_hh 0;// (1)Stack creation a…

笔记:DrawingContext和GDI+对比简介

一、目的&#xff1a;分享一个wpf中级控件&#xff0c;鼠标放上展开其他控件的效果 DrawingContext 和 GDI 的 Graphics 类都是用于绘图的技术&#xff0c;但它们属于不同的图形库和框架&#xff0c;适用于不同的场景。让我们详细比较一下这两者。 二、对比 DrawingContext Dra…

Linux线程同步与互斥

&#x1f30e;Linux线程同步与互斥 文章目录&#xff1a; Linux线程同步与互斥 Linux线程互斥 线程锁       互斥量Mutex         初始化互斥量的两种方式         申请锁方式         解除与销毁锁 问题解决及线程饥饿       互斥锁的底…

ppt组织结构图怎么增加分支?

在使用ppt里边的SmartArt来制作组织结构图的时候&#xff0c;我们发现里边的图形不够用&#xff0c;需要增加分支&#xff0c;这也就是大家近期问的ppt组织结构图怎么增加分支。今天设计学徒自学网小编就把具体的操作步骤分享给大家了&#xff0c;希望能帮助你们&#xff01; …

java编程行业特点

Java编程行业是一个庞大且充满活力的领域&#xff0c;它涵盖了从桌面应用到企业级应用、从Web开发到移动应用、从大数据处理到云计算服务的广泛范围。Java作为一种跨平台、面向对象的编程语言&#xff0c;自1995年发布以来&#xff0c;一直受到全球开发者的青睐&#xff0c;并在…