先看抖音的格式 对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)
# 加密用户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语言的实现
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)
}
运行结果如下