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

模仿抖音用户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)

    # 加密用户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)
}

运行结果如下


http://www.kler.cn/news/315427.html

相关文章:

  • C# Winform调用控制台程序(通过Process类)
  • Java设计模式(单例模式)——单例模式存在的问题(完整详解,附有代码+案例)
  • svn 1.14.5
  • numpy的花式引用
  • 3款免费的GPT类工具
  • Git 原理(提交对象)(结合图与案例)
  • 前后端分离项目中如何保证 API 安全
  • leetcode第十题:正则表达式匹配
  • (k8s)kubernetes 部署Promehteus学习之路
  • C语言:冒泡排序的注意事项及具体实现
  • Linux 基础IO 1
  • set的相关函数(3)
  • Node.js的学习2——内置模块(一)
  • 电气设备施工现场风险状态判断ai模型训练数据集
  • 【沪圈游戏公司作品井喷,游戏产业复兴近在眼前】
  • 整数二分算法和浮点数二分算法
  • 【数据结构与算法 | 灵神题单 | 二叉搜索树篇】力扣653
  • 基于SpringBoot的在线点餐系统【附源码】
  • 【C++笔记】C++编译器拷贝优化和内存管理
  • 【Obsidian】当笔记接入AI,Copilot插件推荐
  • SpringCloud alibaba
  • 算法-环形链表(141)
  • 【Elasticsearch】-图片向量化存储
  • ffplay ubuntu24出现:Could not initialize SDL - dsp: No such audio device
  • Redis存储原理
  • ElementUI 用span-method实现循环el-table组件的合并行功能
  • Spring Boot文件上传/下载问题
  • 计算机网络(运输层)
  • Selenium:开源自动化测试框架的Java实战解析
  • SpringCloud Feign 以及 一个标准的微服务的制作