dufaxing To be a better man

PDCP加解密DEMO

2025-03-30


KYHHbj.png

博客地址

依赖库

此示例使用PyCryptodome库进行加密操作,要运行此代码,需要先安装PyCryptodome

pip install pycryptodome


PDCP加解密python demo

import os
import binascii
from Crypto.Cipher import AES
from Crypto.Util import Counter

class PDCPNEA2Cipher:
    def __init__(self, key, count, bearer, direction):
        """
        初始化PDCP NEA2加密器
        
        :param key: 16字节加密密钥(十六进制字符串或字节)
        :param count: 32位PDCP COUNT值
        :param bearer: 5位承载标识
        :param direction: 1位方向标识(0:上行, 1:下行)
        """
        # 处理密钥输入
        if isinstance(key, str):
            # 如果是十六进制字符串,转换为字节
            self.key = binascii.unhexlify(key)
        else:
            self.key = key
            
        if len(self.key) != 16:
            raise ValueError("密钥必须是16字节长度")
        
        self.count = count
        self.bearer = bearer
        self.direction = direction
        
    def _generate_iv(self):
        """生成初始化向量(IV)"""
        # 根据3GPP TS 33.401规范构建IV
        # IV = COUNT[32] | BEARER[5] | DIRECTION[1] | 0[26]
        iv = bytearray(16)
        
        # 设置COUNT (4字节,大端序)
        iv[0] = (self.count >> 24) & 0xFF
        iv[1] = (self.count >> 16) & 0xFF
        iv[2] = (self.count >> 8) & 0xFF
        iv[3] = self.count & 0xFF
        
        # 设置BEARER和DIRECTION
        # 第4字节: BEARER[5] + DIRECTION[1] + 0[2]
        iv[4] = ((self.bearer & 0x1F) << 3) | ((self.direction & 0x01) << 2)
        
        # 剩余字节保持为0
        return bytes(iv)
    
    def encrypt(self, plaintext, hex_input=False, hex_output=False):
        """
        加密数据
        
        :param plaintext: 明文数据(字节或十六进制字符串)
        :param hex_input: 输入是否为十六进制字符串
        :param hex_output: 是否输出十六进制字符串
        :return: 加密后的数据
        """
        # 处理输入数据
        if hex_input:
            # 如果是十六进制字符串,转换为字节
            data = binascii.unhexlify(plaintext)
        else:
            data = plaintext
        
        # 生成IV
        iv = self._generate_iv()
        
        # 创建CTR模式的计数器
        # NEA2使用完整的16字节IV作为初始计数器值
        ctr = Counter.new(128, initial_value=int.from_bytes(iv, byteorder='big'))
        
        # 创建AES-CTR密码器
        cipher = AES.new(self.key, AES.MODE_CTR, counter=ctr)
        
        # 加密数据
        ciphertext = cipher.encrypt(data)
        
        # 处理输出格式
        if hex_output:
            return binascii.hexlify(ciphertext).decode('utf-8')
        else:
            return ciphertext
    
    def decrypt(self, ciphertext, hex_input=False, hex_output=False):
        """
        解密数据
        
        :param ciphertext: 密文数据(字节或十六进制字符串)
        :param hex_input: 输入是否为十六进制字符串
        :param hex_output: 是否输出十六进制字符串
        :return: 解密后的数据
        """
        # 处理输入数据
        if hex_input:
            # 如果是十六进制字符串,转换为字节
            data = binascii.unhexlify(ciphertext)
        else:
            data = ciphertext
        
        # 解密过程与加密相同(CTR模式对称)
        # 生成IV
        iv = self._generate_iv()
        
        # 创建CTR模式的计数器
        ctr = Counter.new(128, initial_value=int.from_bytes(iv, byteorder='big'))
        
        # 创建AES-CTR密码器
        cipher = AES.new(self.key, AES.MODE_CTR, counter=ctr)
        
        # 解密数据
        plaintext = cipher.decrypt(data)
        
        # 处理输出格式
        if hex_output:
            return binascii.hexlify(plaintext).decode('utf-8')
        else:
            return plaintext

# 示例使用
if __name__ == "__main__":
    # 测试参数 - 使用十六进制格式
    key_hex = "00112233445566778899aabbccddeeff"  # 128位密钥(十六进制字符串)
    count = 0x12345678    # 32位COUNT值
    bearer = 1         # 承载标识 (最大31),BR_ID - 1(DRB2,bearer则为1)
    direction = 0         # 数据方向,0为上行,1为下行
    
    # 创建加密器实例
    cipher = PDCPNEA2Cipher(key_hex, count, bearer, direction)
    
    # 示例明文数据(十六进制字符串)
    plaintext_hex = "48656c6c6f2050444350204e45413220656e6372797074696f6e21"
    
    # 加密(输入和输出都使用十六进制)
    ciphertext_hex = cipher.encrypt(plaintext_hex, hex_input=True, hex_output=True)
    print(f"明文(hex): {plaintext_hex}")
    print(f"密文(hex): {ciphertext_hex}")
    
    # 解密(输入和输出都使用十六进制)
    decrypted_hex = cipher.decrypt(ciphertext_hex, hex_input=True, hex_output=True)
    print(f"解密后(hex): {decrypted_hex}")
    
    # 验证加解密是否正确
    assert plaintext_hex == decrypted_hex, "加解密测试失败!"
    print("加解密测试成功!")
    
    # 也可以将十六进制结果转换回可读文本
    decrypted_text = binascii.unhexlify(decrypted_hex).decode('utf-8')
    print(f"解密文本: {decrypted_text}")

说明

如果使用十六进制字符串作为密钥,必须确保是32个字符(16字节)



Similar Posts

上一篇 NR PDCP流程

Comments