python 的sm2 密钥的格式转化pem 和str

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

"""
Author: tanglei
DateTime:2024-11-18 完成
微信:ciss_cedar
欢迎一起学习
"""

import base64

key_type = ('PUBLIC', 'PRIVATE')


def hex_to_pem(hex_key, key_type='PUBLIC'):
    """
    将十六进制字符串格式的密钥转换为 PEM 格式。

    :param hex_key: 十六进制编码的密钥字符串。
    :param key_type: 'PUBLIC' 或 'PRIVATE',表示公钥或私钥。
    :return: PEM 格式的密钥字符串。
    """
    # 将十六进制字符串解码为二进制数据
    bin_key = bytes.fromhex(hex_key)

    # 构造 PEM 格式的字符串
    pem_header = f'-----BEGIN {key_type.upper()} KEY-----\n'
    pem_footer = f'-----END {key_type.upper()} KEY-----\n'

    # 将二进制数据编码为 Base64,并确保每行不超过 64 个字符
    pem_body = ''.join([base64.b64encode(bin_key[i:i + 60]).decode('utf-8') for i in range(0, len(bin_key), 60)])
    pem_key = pem_header + pem_body.replace('\n', '\n    ') + '\n' + pem_footer  # 可选:添加缩进以符合某些工具的格式要求

    return pem_key


def pem_to_hex(pem_key):
    """
    将 PEM 格式的密钥字符串转换回十六进制字符串。

    :param pem_key: PEM 格式的密钥字符串。
    :return: 十六进制编码的密钥字符串。
    """
    pem_header_public = '-----BEGIN PUBLIC KEY-----'
    pem_header_private = '-----BEGIN PRIVATE KEY-----'
    pem_footer = '-----END '

    # 确定密钥类型并提取 Base64 编码的主体部分
    if pem_header_public in pem_key:
        pem_header = pem_header_public
    elif pem_header_private in pem_key:
        pem_header = pem_header_private
    else:
        raise ValueError("Invalid PEM key: Unrecognized header.")

    pem_body = pem_key[pem_key.index(pem_header) + len(pem_header):pem_key.index(pem_footer.replace(' ', '')) + len(
        ' KEY-----\n')].strip()

    # Base64 解码
    # print(f'pem_body={pem_body}')
    bin_key = base64.b64decode(pem_body)

    # 将二进制数据编码为十六进制字符串
    hex_key = bin_key.hex().upper()

    return hex_key


def main():
    # 示例用法
    public_key = 'B9C9A6E04E9C91F7BA880429273747D7EF5DDEB0BB2FF6317EB00BEF331A83081A6994B8993F3F5D6EADDDB81872266C87C018FB4162F5AF347B483E24620207'
    private_key = 'B9AB0B828FF68872F21A837FC303668428DEA11DCD1B24429D0C99E24EED83D5'

    public_key_pem = hex_to_pem(public_key, key_type[0])
    private_key_pem = hex_to_pem(private_key, key_type[1])

    print(f'public_key_pem=')
    print(f'{public_key_pem}')
    print(f'private_key_pem=')
    print(f'{private_key_pem}')

    public_key = pem_to_hex(public_key_pem)
    private_key = pem_to_hex(private_key_pem)

    print(public_key)
    print(private_key)


if __name__ == '__main__':
    main()

您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>好的,我现在要解决用户的问题:如何在Python中使用requests库调用SM2加密的API接口,并对返回参数进行解密。用户还希望有示例代码。首先,我需要回忆一下相关的知识,并结合用户提供的引用内容来组织答案。 首先,用户提到的引用[2]是关于Python与Java Hutool库SM2加解密互通的。这说明用户可能遇到了跨语言加解密的问题,特别是Java那边使用Hutool生成的密钥对,而Python需要兼容。根据引用中的内容,Hutool生成的SM2密钥对中,私钥可能比公钥长,这可能涉及到密钥格式的问题,比如是否包含ASN.1编码或其他元数据。 接下来,用户的需求是使用Python的requests库发送POST请求,并且请求数据需要SM2加密,同时响应也需要解密。所以步骤应该是:生成SM2密钥对,加密请求数据,发送请求,接收响应,解密响应数据。 首先,Python中处理SM2加密的库有哪些?常见的可能是gmssl库或者使用cryptography库结合其他模块。根据引用中的示例,用户可能需要使用gmssl或者类似的库。需要检查gmssl是否支持处理Hutool生成的密钥格式。例如,Hutool生成的公钥可能包含04前缀,后面跟着xy坐标,而gmssl可能需要正确的公钥格式。 另外,密钥换可能是一个关键点。比如,Java生成的私钥可能包含ASN.1结构,而Python库可能需要原始的私钥字节。用户引用[2]中提到,通过分析密钥结构,将私钥换为Python可用的格式。这可能涉及到解码PEM文件,提取实际的私钥部分。 然后,关于requests库的使用,需要构造POST请求,将加密后的数据作为请求体发送。加密的数据可能需要是Base64编码的字符串,因为二进制数据不适合直接传输。 在解密返回参数时,同样需要使用SM2私钥解密响应内容。需要确保响应数据是正确编码的,比如Base64,然后在Python中解码后再进行解密。 现在,可能的步骤是: 1. 安装必要的库,如requests、gmssl。 2. 生成或导入SM2密钥对,处理可能的格式问题。 3. 使用公钥加密请求数据,换为Base64。 4. 发送POST请求。 5. 接收响应后,使用私钥解密Base64解码后的数据。 需要处理的问题可能包括密钥格式换、加密解密的正确调用、数据编码等。特别是Hutool生成的密钥可能需要处理,比如去掉多余的部分,提取出实际的密钥值。 在示例代码中,需要展示如何加载密钥,加密数据,发送请求,解密响应。可能还需要注意点,比如使用正确的椭圆曲线参数(如sm2p256v1),处理可能的异常情况,如解码错误、解密失败等。 另外,用户引用[1]提到了AES加解密的互操作,虽然现在的问题是关于SM2的,但可能可以参考类似的思路,比如处理不同语言间的数据格式编码问题。 总结下来,回答的结构应该是: - 环境准备(安装库) - 密钥处理(生成或加载) - 加密请求数据 - 发送POST请求 - 解密响应数据 - 示例代码 - 注意事项 需要注意引用中的内容,比如用户提到的Hutool生成的密钥格式问题,所以在处理密钥时要考虑如何换,可能需要从PEM文件中提取实际密钥,或者处理ASN.1结构。 可能的问题点:gmssl库的SM2实现是否与Hutool兼容?例如,曲线的参数、签名算法、加密模式等是否一致。可能需要确认双方使用的椭圆曲线参数是否相同,比如都是使用标准的sm2p256v1曲线。 另外,加密后的数据格式可能不同,比如SM2加密后的数据是否包含ASN.1编码,或者是否为C1C3C2拼接格式。Hutool可能使用特定的格式Python这边需要对应处理,否则无法正确解密。例如,Hutool生成的密文可能需要按照特定顺序拼接各部分,而gmssl可能需要同样的顺序才能解密。 综上,示例代码需要包含密钥的加载、加密、解密的具体实现,并处理这些格式问题。可能需要将公钥私钥处理成gmssl所需的格式,比如去掉多余的元数据,只保留坐标值,并在加密时使用正确的编码方式。</think>### Python调用SM2加密API接口及解密返回参数教程 #### 一、环境准备 1. 安装依赖库: ```bash pip install requests gmssl==3.2.2 ``` 2. 密钥生成建议: - 若需与Java Hutool库互通,需确保密钥格式兼容[^2] - 标准SM2公钥格式为`04||x||y`(65字节),私钥为32字节 #### 二、完整代码示例 ```python from gmssl import sm2, func import requests import base64 # 密钥配置(示例密钥需替换为实际值) private_key = "3690655E33D5E5D5FE9F0F0F2F8F8B0B5F0E0E2F8F0E5E5E0E5E5E0E5E5E0" public_key = "04B9C0D0E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B6C7D8E9F0A1B2C3D4E5F6A7B8C9D0E1F2A3" # 加密请求数据 def sm2_encrypt(data): sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key="") enc_data = sm2_crypt.encrypt(data.encode()) return base64.b64encode(enc_data).decode() # 解密响应数据 def sm2_decrypt(encrypted_data): sm2_crypt = sm2.CryptSM2(public_key="", private_key=private_key) dec_data = sm2_crypt.decrypt(base64.b64decode(encrypted_data)) return dec_data.decode() # 发送加密请求 url = "https://api.example.com/sm2_endpoint" request_data = {"param1": "value1"} # 加密请求体 encrypted_body = sm2_encrypt(str(request_data)) headers = {"Content-Type": "application/base64"} # 发送POST请求 response = requests.post( url, data=encrypted_body, headers=headers ) # 解密响应 if response.status_code == 200: decrypted_response = sm2_decrypt(response.content) print("解密结果:", decrypted_response) else: print("请求失败:", response.text) ``` #### 三、关键步骤说明 1. **密钥处理**: - 若使用Java Hutool生成的密钥,需提取实际密钥值: ```python # Hutool生成的PEM格式密钥处理方法 def extract_private_key(pem_str): return pem_str[32:-32] # 根据实际格式调整切片位置 ``` 2. **加密规范**: - 采用`C1C3C2`密文结构(与Java兼容) - 使用国密推荐曲线`sm2p256v1` 3. **异常处理**: ```python try: decrypted = sm2_decrypt(response.content) except Exception as e: print(f"解密失败:{str(e)}") # 检查密钥是否匹配、密文是否被篡改 ``` #### 四、注意事项 1. **编码一致性**: - 请求/响应数据需统一使用Base64编码 - 加密前数据建议进行UTF-8编码换 2. **性能优化**: ```python # 复用SM2对象提升性能 sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key) ``` 3. **安全建议**: - 私钥存储使用HSM或KMS系统 - 启用SM3哈希算法进行完整性校验 #### 五、互通性验证 1. Java端应使用相同椭圆曲线参数 2. 加解密测试向量: ```python test_data = "Hello SM2" encrypted = sm2_encrypt(test_data) decrypted = sm2_decrypt(encrypted) assert test_data == decrypted ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值