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

先看抖音的格式 对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)

    # 加密用户ID
    user_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安全的Base64
    encoded_id = base64.urlsafe_b64encode(iv + encrypted_id).decode('utf-8')

    # 去除编码结果中的填充字符 '='
    encoded_id = encoded_id.rstrip('=')

    # 添加固定前缀和后缀
    sec_user_id = PREFIX + encoded_id + SUFFIX

    return sec_user_id


def 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

    # 解码Base64
    decoded_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)

    # 解密用户ID
    padded_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语言的实现

Go 复制代码
package main

import (
	"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.BlockSize
	padtext := 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
	}

	// 加密用户ID
	userIDBytes := 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安全的Base64
	encodedID := base64.URLEncoding.EncodeToString(append(iv, ciphertext...))

	// 去除编码结果中的填充字符 '='
	encodedID = strings.TrimRight(encodedID, "=")

	// 添加固定前缀和后缀
	secUserID := PREFIX + encodedID + SUFFIX

	return secUserID, nil
}

// 解密用户ID
func decryptID(secUserID string) (int64, error) {
	// 去除固定前缀和后缀
	encodedID := secUserID[len(PREFIX) : len(secUserID)-len(SUFFIX)]

	// 解码URL安全的Base64,并手动添加填充字符 '='
	paddingLen := 4 - len(encodedID)%4
	encodedID += strings.Repeat("=", paddingLen)

	// 解码Base64
	decodedID, 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
	}

	// 解密用户ID
	mode := cipher.NewCFBDecrypter(block, iv)
	mode.XORKeyStream(ciphertext, ciphertext)
	paddedUserID, err := unpad(ciphertext)
	if err != nil {
		return 0, err
	}

	// 转换为int64
	userID := 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)
}

运行结果如下

相关推荐
路多辛2 分钟前
Golang database/sql 包深度解析(二):连接池实现原理
数据库·sql·golang
夏小花花3 分钟前
vue3 ref和reactive的区别和使用场景
前端·javascript·vue.js·typescript
outsider_友人A5 分钟前
前端也想写后端(3)中间件Middleware、管道Pipes、拦截器Interceptors
前端·node.js·nestjs
静Yu6 分钟前
Webpack 你到底在干什么!?
前端
掘金安东尼7 分钟前
前端周刊第427期(2025年8月4日–8月10日)
前端·javascript·面试
阿华的代码王国7 分钟前
【Android】适配器与外部事件的交互
android·xml·java·前端·后端·交互
写bug写bug8 分钟前
分布式锁的使用场景和常见实现(下)
分布式·后端·面试
kgduu9 分钟前
go资料汇总
golang
Postkarte不想说话9 分钟前
Debian13编译安装FreeSWITCH
后端
mit6.82410 分钟前
[AI React Web] 包与依赖管理 | `axios`库 | `framer-motion`库
前端·人工智能·react.js