Python国密算法实战:SM2与SM3完整实现指南

Python国密算法实战:gmalg库SM2/SM3/SM4完整教程与避坑指南 密码学是保障数据安全的基石,其核心原理在于通过加密算法将明文信息转换为无法直接识别的密文,确保数据的机密性、完整性与不可否认性。在众多加密技术中,对称加密与非对称加密构成了现代密码学体系的两大支柱,而哈希算法则广泛用于数据完整性校验。随着信息安全自主可控需求的提升,符合国家商用密码标准的国密算法(SM系列)在金融、政务、物联网等关键领域成为合规刚需。国密算法包括用于非对称加密与签名的SM2、用于哈希计算的SM3以及用于对称加密的SM4,它们共同构成了我国自主可控的密码技术体系。本文聚焦于Python生态中的 阅读详情

1. 项目概述:为什么要在Python里搞国密算法?

最近几年,但凡涉及到数据安全、金融支付、政务系统这些对安全性要求极高的领域,“国密算法”这个词出现的频率是越来越高了。我最早接触国密是在一个对接某大型银行支付接口的项目里,对方明确要求所有敏感数据的签名和验签必须使用SM2和SM3,当时市面上成熟的、好用的Python库还真不多,踩了不少坑。所以,今天就想系统地聊聊,怎么用Python3来完整地实现国密SM2(非对称加密/签名)和SM3(哈希摘要)这套组合拳。

简单来说,你可以把SM3理解为我们更熟悉的SHA-256的“国产升级版”,它是一个密码杂凑函数,负责把任意长度的数据“浓缩”成一个固定长度(256位)且不可逆的“指纹”。而SM2则是基于椭圆曲线密码学(ECC)的非对称加密算法,相当于RSA的国产替代,但它比RSA更安全(在相同安全强度下,所需的密钥长度更短)、效率也更高。这俩组合起来,一个负责“验明正身”(哈希和签名),一个负责“守口如瓶”(加密解密),是构建自主可控安全体系的基石。

对于开发者而言,掌握Python下的国密算法实现,不再是“锦上添花”,而是逐渐变成了一个“硬需求”。无论是开发需要符合国家密码管理要求的应用,还是与越来越多的采用国密标准的机构做对接,这都是一项必备技能。接下来,我就从环境准备、核心原理、代码实操到避坑指南,带你完整走一遍。

2. 核心工具选型与环境搭建

工欲善其事,必先利其器。在Python的世界里,实现国密算法主要有两种路径:一是使用纯Python实现的库,优点是跨平台、依赖少;二是绑定成熟的C语言国密库(如GmSSL),性能更高。对于大多数应用场景,我推荐后者,因为它经过了更严格的实践检验。

2.1 主流库对比与选择

市面上常见的Python国密库主要有以下几个:

  1. gmssl : 这是目前最主流、最活跃的选择。它是著名开源国密密码库GmSSL的Python绑定。功能完整,支持SM2、SM3、SM4、SM9等国密算法,且持续更新。缺点是安装稍微复杂,需要先解决C编译环境和依赖。
  2. python-gmssl (或 sm2crypto ) : 一些早期的纯Python实现或对其他C库的封装。它们的优点是安装简单( pip install 即可),但可能存在功能不全、性能较差、或维护停滞的风险。
  3. cryptography + 自定义适配 : 强大的通用密码学库 cryptography 本身不直接支持国密,但你可以利用其底层接口和椭圆曲线基础功能进行“组装”,但这要求你对密码学原理有很深的理解,不推荐新手。

我的选择与理由 : 经过多个生产项目的验证,我坚定地选择 gmssl 。原因很简单: 官方背景、生态完整、性能可靠 。它直接对接的是由国家密码管理局认证的算法实现核心,在合规性和正确性上最有保障。虽然安装步骤多一步,但一劳永逸。下面我们就以它为例进行环境搭建。

2.2 gmssl 库的安装详解

安装 gmssl 的Python包,实际上需要先在其系统环境中安装GmSSL的C语言库。这里以最常见的Linux(Ubuntu/CentOS)和macOS为例,Windows系统建议使用WSL2以获得最佳体验。

对于 Ubuntu/Debian 系统:

# 1. 更新系统并安装编译工具和依赖
sudo apt-get update
sudo apt-get install -y build-essential cmake git

# 2. 克隆 GmSSL 源码并编译安装
git clone https://github.com/guanzhi/GmSSL.git
cd GmSSL
mkdir build
cd build
cmake ..
make
sudo make install

# 3. 执行动态链接库配置(关键步骤!)
echo "/usr/local/lib64" | sudo tee /etc/ld.so.conf.d/gmssl.conf
sudo ldconfig

# 4. 安装Python绑定
pip install gmssl-python

对于 CentOS/RHEL 系统:

# 1. 安装开发工具组和依赖
sudo yum groupinstall -y "Development Tools"
sudo yum install -y cmake git

# 2. 后续步骤与Ubuntu相同,克隆、编译、安装GmSSL
git clone https://github.com/guanzhi/GmSSL.git
cd GmSSL
mkdir build
cd build
cmake ..
make
sudo make install

# 3. 配置库路径(CentOS的库路径可能不同,注意检查)
sudo ldconfig /usr/local/lib64 # 或 /usr/local/lib

# 4. 安装Python绑定
pip install gmssl-python

对于 macOS 系统(使用Homebrew):

# 1. 使用Homebrew安装GmSSL(这是最简便的方式)
brew install gmssl

# 2. 安装Python绑定
pip install gmssl-python

安装核心注意事项 :

  1. ldconfig 是关键 : 在Linux上编译安装C库后,必须运行 sudo ldconfig ,否则Python在运行时找不到 libgmssl.so 动态库,会报 ImportError 。
  2. 版本匹配 : 确保 gmssl-python 的版本与你安装的GmSSL C库版本大致兼容。通常使用最新版即可。
  3. 验证安装 : 安装完成后,打开Python解释器,执行 import gmssl ,如果不报错,说明安装成功。可以进一步执行 print(gmssl.__version__) 查看版本。

如果一切顺利,你的武器库就准备好了。接下来,我们深入算法核心。

3. SM3哈希算法:国产的消息摘要标杆

SM3算法生成一个256位(32字节)的哈希值,其设计安全性与SHA-256相当。但理解算法原理和学会调用接口同样重要。

3.1 SM3算法原理浅析与调用

SM3的过程可以概括为 填充-分组-迭代压缩 。对于输入消息,先进行填充使其长度满足512位的倍数,然后切分成多个512位的分组,每个分组再与当前的状态值(一个256位的中间值)进行复杂的压缩函数计算,最终输出最后一个状态值作为哈希结果。

作为开发者,我们不必手动实现这个过程。使用 gmssl 库非常简单:

from gmssl import sm3

def demo_sm3_basic():
    """SM3基础使用示例"""
    data = b"Hello, SM3! This is a test message."  # 注意:输入需要是字节串(bytes)
    
    # 方法1: 使用 sm3.sm3_hash 函数
    hash_hex = sm3.sm3_hash(data)
    print(f"SM3哈希值(方法1): {hash_hex}")
    # 输出类似:6605b7c8d5b3a7e3c6a9f8d4e2b1c0a9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4
    
    # 方法2: 使用 SM3 对象,适用于流式数据或多次更新
    sm3_obj = sm3.SM3()
    sm3_obj.update(b"Hello, ")
    sm3_obj.update(b"SM3! ")
    sm3_obj.update(b"This is a test message.")
    hash_hex2 = sm3_obj.hexdigest()
    print(f"SM3哈希值(方法2): {hash_hex2}")
    
    # 验证两种方法结果一致
    assert hash_hex == hash_hex2, "两种计算方法结果应一致"
    
    # 获取字节类型的哈希值
    hash_bytes = sm3_obj.digest()
    print(f"哈希字节长度: {len(hash_bytes)}")  # 输出: 32

if __name__ == "__main__":
    demo_sm3_basic()

3.2 SM3在实际场景中的应用与技巧

SM3不仅仅用于生成文件或字符串的“指纹”,它在更多安全协议中扮演核心角色。

场景一:文件完整性校验 这是最经典的应用。比如你从官网下载了一个软件安装包,同时官网提供了该文件的SM3哈希值。你可以计算下载文件的SM3值进行比对,确保文件在传输过程中未被篡改。

import hashlib # 对比用
from gmssl import sm3

def get_file_sm3(file_path):
    """计算大文件的SM3哈希值,避免一次性加载到内存"""
    hash_obj = sm3.SM3()
    with open(file_path, 'rb') as f:
        # 分块读取,适用于大文件
        for chunk in iter(lambda: f.read(4096), b''):
            hash_obj.update(chunk)
    return hash_obj.hexdigest()

# 计算并对比
file_hash = get_file_sm3("my_package.tar.gz")
official_hash = "a1b2c3d4e5f6..." # 从官网获取
if file_hash == official_hash:
    print("文件完整,未被篡改")
else:
    print("警告!文件哈希值不匹配!")

场景二:密码存储(加盐哈希) 绝对不要明文存储用户密码!使用SM3进行加盐哈希是基本操作。

import os
from gmssl import sm3

def hash_password(password: str, salt: bytes = None) -> tuple:
    """对密码进行加盐哈希
    返回: (存储的哈希值hex, 使用的盐hex)
    """
    if salt is None:
        salt = os.urandom(16)  # 生成16字节的随机盐
    # 将密码和盐组合后哈希
    data = password.encode('utf-8') + salt
    hashed = sm3.sm3_hash(data)
    return hashed, salt.hex()

def verify_password(password: str, stored_hash: str, salt_hex: str) -> bool:
    """验证密码"""
    salt = bytes.fromhex(salt_hex)
    data = password.encode('utf-8') + salt
    computed_hash = sm3.sm3_hash(data)
    # 使用恒定时间比较,避免时序攻击
    return computed_hash == stored_hash

# 使用示例
stored_hash, salt = hash_password("MySuperSecretPassword123")
print(f"存储的哈希: {stored_hash}")
print(f"使用的盐: {salt}")

is_correct = verify_password("MySuperSecretPassword123", stored_hash, salt)
print(f"密码验证结果: {is_correct}")  # 应为 True
is_correct = verify_password("WrongPassword", stored_hash, salt)
print(f"密码验证结果: {is_correct}")  # 应为 False

SM3实操心得 :

  1. 输入类型 : sm3_hash 函数和 update 方法只接受 bytes 类型。对字符串操作前务必使用 .encode('utf-8') 转换。
  2. 盐值(Salt)的重要性 : 在密码存储场景, 必须使用随机盐 。相同的密码,不同的盐会产生截然不同的哈希值,这能有效防御彩虹表攻击。盐不需要保密,可以与哈希值一起存储。
  3. 恒定时间比较 : 在验证哈希值(如密码)时,简单的 == 操作在Python中可能受到时序攻击的影响。对于极高安全要求的场景,应考虑使用 hmac.compare_digest (Python标准库)来比较两个字节串。在上面的例子中,由于我们比较的是十六进制字符串,风险相对较低,但最佳实践是先将十六进制字符串转回字节串再用 compare_digest 。

4. SM2非对称加密算法:椭圆曲线上的安全卫士

SM2是基于椭圆曲线密码学(ECC)的算法。相比于我们更熟悉的RSA,ECC在达到相同安全级别时,所需的密钥长度要短得多(例如,256位的ECC密钥安全性约等于3072位的RSA密钥),这意味着更快的计算速度和更小的数据包。

4.1 SM2密钥对生成与管理

SM2的密钥对包括一个私钥(自己保密)和一个公钥(可以公开)。 gmssl 库使得生成和管理它们变得非常容易。

from gmssl import sm2

def demo_sm2_keygen():
    """生成SM2密钥对"""
    # 默认使用国密标准推荐的 sm2p256v1 曲线
    sm2_crypt = sm2.CryptSM2()
    # 生成密钥对
    private_key = sm2_crypt.generate_private_key()
    public_key = sm2_crypt.generate_public_key(private_key)
    
    print(f"私钥 (32字节, 16进制): {private_key.hex()}")
    print(f"公钥 (64字节, 未压缩格式): {public_key.hex()}")
    # 注意: 公钥通常是04||X||Y的格式,共65字节?这里生成的是64字节,可能省略了04前缀。
    # gmssl 内部可能使用压缩或特定格式,需查阅其文档。通常其接口期望的即是此64字节格式。
    
    return private_key, public_key

# 生成密钥对
priv_key, pub_key = demo_sm2_keygen()

在实际项目中,我们通常需要将密钥持久化存储,例如保存为PEM格式的文件。

from gmssl import sm2
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec
import binascii

def save_sm2_keypair(private_key_bytes: bytes, public_key_bytes: bytes, private_key_path: str, public_key_path: str):
    """将SM2密钥对保存为PEM格式文件(一种通用格式)"""
    # 注意:gmssl生成的原始字节需要转换成cryptography库能识别的对象以便导出PEM
    # 这里演示一种方法:先构造EC私钥对象
    # SM2使用的曲线参数与 prime256v1 (NIST P-256) 相同
    curve = ec.SECP256R1()
    
    # 构建私钥对象
    private_key = ec.derive_private_key(int.from_bytes(private_key_bytes, 'big'), curve)
    # 构建公钥对象 (公钥是04||X||Y,65字节)
    # gmssl生成的64字节公钥,需要加上04前缀
    public_key_full = b'\x04' + public_key_bytes
    public_key = ec.EllipticCurvePublicKey.from_encoded_point(curve, public_key_full)
    
    # 将私钥保存为PEM,并用密码加密
    pem_private = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.BestAvailableEncryption(b'mypassword') # 设置密码
    )
    with open(private_key_path, 'wb') as f:
        f.write(pem_private)
    
    # 将公钥保存为PEM
    pem_public = public_key.public_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PublicFormat.SubjectPublicKeyInfo
    )
    with open(public_key_path, 'wb') as f:
        f.write(pem_public)
    
    print(f"私钥已保存至: {private_key_path} (已加密)")
    print(f"公钥已保存至: {public_key_path}")

def load_sm2_private_key(private_key_path: str, password: bytes) -> bytes:
    """从PEM文件加载私钥,返回原始字节"""
    with open(private_key_path, 'rb') as f:
        private_key = serialization.load_pem_private_key(
            f.read(),
            password=password
        )
    # 将私钥对象转换回整数,然后转为32字节
    private_int = private_key.private_numbers().private_value
    return private_int.to_bytes(32, 'big')

# 使用示例(接续之前的密钥生成)
save_sm2_keypair(priv_key, pub_key, 'sm2_private.pem', 'sm2_public.pem')
loaded_priv = load_sm2_private_key('sm2_private.pem', b'mypassword')
print(f"加载的私钥是否与原始一致: {loaded_priv == priv_key}")

密钥管理核心注意事项 :

  1. 私钥安全 : 私钥是安全的核心, 必须加密存储 (如上面示例中的密码保护),并且严格控制访问权限。绝对不要将私钥硬编码在源代码或提交到版本控制系统。
  2. 公钥格式 : 不同的库和系统对公钥的格式要求可能不同(如是否包含 0x04 前缀、是否压缩)。在与第三方系统对接时,务必确认对方要求的公钥格式,并进行必要的转换。 gmssl 库在加解密和签名时,通常期望的是64字节的裸公钥(X||Y)。
  3. 曲线参数 : SM2使用的是特定的椭圆曲线参数(sm2p256v1),它与国际标准的 prime256v1 (NIST P-256)曲线参数相同,但哈希函数和部分计算流程不同。这意味着从数学上,密钥本身可以互换,但 不能 直接用其他ECC库(如OpenSSL的默认ECC)来进行SM2运算,因为算法标识和流程不同。

4.2 数据加密与解密实战

SM2用于加密时,发送方使用接收方的公钥加密数据,只有拥有对应私钥的接收方才能解密。

from gmssl import sm2
import os

def demo_sm2_encrypt_decrypt():
    """SM2加密解密完整流程"""
    # 1. 接收方生成密钥对 (模拟接收方)
    sm2_recv = sm2.CryptSM2()
    recv_private_key = sm2_recv.generate_private_key()
    recv_public_key = sm2_recv.generate_public_key(recv_private_key)
    print(f"接收方公钥 (前16位...): {recv_public_key.hex()[:32]}...")
    
    # 2. 发送方准备加密 (模拟发送方)
    plaintext = b"This is a very secret message that needs to be encrypted using SM2."
    print(f"原始明文: {plaintext[:50]}... (长度: {len(plaintext)})")
    
    # 注意:SM2加密本身不直接支持过长的数据。通常做法是:
    # a) 生成一个随机的对称密钥(如SM4密钥)
    # b) 用SM2加密这个对称密钥
    # c) 用对称密钥加密实际数据
    # 这里演示gmssl库的SM2加密接口(它内部可能处理了数据长度问题或仅适用于短数据)
    sm2_sender = sm2.CryptSM2()
    # 使用接收方的公钥进行加密
    ciphertext = sm2_sender.encrypt(plaintext, recv_public_key)
    print(f"加密后的密文 (长度: {len(ciphertext)}): {ciphertext.hex()[:100]}...")
    
    # 3. 接收方进行解密
    sm2_recv_decryptor = sm2.CryptSM2()
    # 设置接收方自己的私钥
    sm2_recv_decryptor.set_private_key(recv_private_key)
    decrypted_data = sm2_recv_decryptor.decrypt(ciphertext)
    
    print(f"解密后的明文: {decrypted_data[:50]}... (长度: {len(decrypted_data)})")
    print(f"解密是否成功: {decrypted_data == plaintext}")

if __name__ == "__main__":
    demo_sm2_encrypt_decrypt()

关于加密数据长度的限制 : 纯粹的SM2加密算法(即公钥加密)由于性能原因,通常只用于加密一个 会话密钥 (比如一个32字节的随机数),而不是直接加密大量数据。这个会话密钥随后被用于对称加密算法(如国密的SM4)来加密实际的消息。这种模式称为 混合加密系统 ,结合了非对称加密的安全性和对称加密的效率。 gmssl 的 encrypt 方法可能内部已经处理了较长的数据,但为了最佳实践和与其他系统的兼容性,你应该查阅其官方文档,确认其支持的数据长度上限。对于超长数据,手动实现混合加密是更稳妥的方案。

4.3 数字签名与验签流程解析

数字签名用于验证数据的完整性和来源的真实性。发送方用私钥对数据的哈希值(如SM3哈希)进行签名,接收方用发送方的公钥验证签名。

from gmssl import sm2, sm3

def demo_sm2_sign_verify():
    """SM2签名与验签完整流程"""
    # 1. 签名方(例如,服务端或客户端)生成密钥对
    signer = sm2.CryptSM2()
    signer_private_key = signer.generate_private_key()
    signer_public_key = signer.generate_public_key(signer_private_key)
    
    # 2. 待签名的数据
    message = b"Important contract: Pay $1000 to account 123456 by 2023-12-31."
    print(f"原始消息: {message}")
    
    # 3. 计算消息的SM3哈希值 (签名是对哈希值进行运算,而非直接对消息)
    msg_hash = sm3.sm3_hash(message)
    msg_hash_bytes = bytes.fromhex(msg_hash)  # 将十六进制哈希转为字节
    print(f"消息SM3哈希: {msg_hash}")
    
    # 4. 使用私钥对哈希值进行签名
    # 注意:gmssl的sign方法通常接受原始消息或哈希值,需根据库版本确认。
    # 这里假设sign方法接受原始消息,并内部计算SM3哈希。
    # 更通用的做法是传递哈希值,但需确认库支持。
    # 查看gmssl文档,其sign方法通常需要原始数据和用户ID。
    user_id = b"1234567812345678"  # 默认用户ID,可为空或特定值
    signature = signer.sign(message, user_id)  # 使用默认或指定用户ID
    print(f"生成的签名 (长度: {len(signature)}): {signature.hex()}")
    
    # 5. 验证方(例如,接收方)进行验签
    verifier = sm2.CryptSM2()
    # 设置签名方的公钥
    verifier.set_public_key(signer_public_key)
    
    # 使用公钥、原始消息、用户ID和签名进行验证
    is_valid = verifier.verify(signature, message, user_id)
    
    print(f"签名验证结果: {is_valid}")
    
    # 6. 测试篡改消息后验签失败
    tampered_message = b"Important contract: Pay $10000 to account 123456 by 2023-12-31." # 修改了金额
    is_valid_tampered = verifier.verify(signature, tampered_message, user_id)
    print(f"篡改消息后验签结果: {is_valid_tampered} (应为False)")

if __name__ == "__main__":
    demo_sm2_sign_verify()

签名验签实操心得 :

  1. 用户ID(User ID) : SM2签名标准中包含了用户ID(一个字节串)作为签名计算的一部分,通常用于标识签名实体。默认值可以是空字符串 b'' 或国标推荐的 b'1234567812345678' (16字节)。 发送方和接收方必须使用相同的用户ID ,否则验签会失败。这是SM2与ECDSA等算法的一个区别点。
  2. 签名与验签的数据 : 大多数SM2实现(包括 gmssl )的 sign 和 verify 方法期望传入的是 原始消息 ,而不是消息的哈希值。库内部会自动计算SM3哈希(这是SM2标准规定的哈希算法)并进行后续签名操作。如果你传入的是预先计算好的哈希值,可能会导致错误。
  3. 签名结果 : SM2签名结果通常由两个大整数 (r, s) 连接而成,长度固定(例如64字节)。 gmssl 返回的签名字节串就是这种格式。

5. SM2+SM3综合应用案例:一个简单的安全通信模拟

理解了单个组件的用法,我们来看一个综合案例:模拟客户端和服务器之间的一次安全数据交换,结合使用SM2和SM3。

场景 : 客户端需要向服务器安全地提交一份订单数据。要求:

  1. 完整性 : 确保订单在传输过程中未被篡改。
  2. 不可否认性 : 客户端无法抵赖自己发送过该订单。
  3. 保密性 : 订单内容对中间人保密。

方案设计 :

  1. 服务器预先生成SM2密钥对,并将公钥下发给客户端。
  2. 客户端生成随机的对称密钥(这里用模拟的会话密钥)。
  3. 客户端用服务器的公钥加密这个对称密钥。
  4. 客户端用对称密钥加密订单数据(这里用简单XOR模拟,实际应用SM4)。
  5. 客户端计算订单数据的SM3哈希值,并用自己的私钥对该哈希值进行签名(实现不可否认性需要客户端也有自己的密钥对,为简化,本例用服务器公钥对应的私钥模拟,实际中客户端应有自己的密钥对)。
  6. 客户端将加密的对称密钥、加密的订单数据、签名一起发送给服务器。
  7. 服务器用自己的私钥解密出对称密钥。
  8. 服务器用对称密钥解密订单数据。
  9. 服务器计算解密后数据的SM3哈希,并用客户端的公钥验证签名。
from gmssl import sm2, sm3
import os

def simulate_secure_communication():
    print("=== 模拟安全通信流程 (SM2 + SM3) ===")
    
    # ===== 初始化阶段 =====
    print("\n1. 初始化阶段")
    # 服务器生成密钥对
    server_sm2 = sm2.CryptSM2()
    server_priv = server_sm2.generate_private_key()
    server_pub = server_sm2.generate_public_key(server_priv)
    print("  服务器生成SM2密钥对。")
    
    # 客户端“持有”服务器公钥(在实际中,通过安全渠道获取)
    client_knows_server_pub = server_pub
    
    # ===== 客户端:准备并发送安全数据 =====
    print("\n2. 客户端准备安全数据包")
    # 原始订单数据
    order_data = b"Order: ProductID=1001, Quantity=5, Price=299.99, Customer=Alice"
    print(f"  原始订单: {order_data}")
    
    # a. 生成随机对称密钥 (模拟,实际应为安全的随机字节,如用于SM4)
    session_key = os.urandom(32)  # 32字节密钥
    print(f"  生成会话密钥: {session_key.hex()[:32]}...")
    
    # b. 用服务器公钥加密会话密钥
    client_cipher = sm2.CryptSM2()
    encrypted_session_key = client_cipher.encrypt(session_key, client_knows_server_pub)
    print(f"  加密后的会话密钥长度: {len(encrypted_session_key)}")
    
    # c. 用会话密钥加密订单数据 (简化模拟,实际应用SM4)
    # 这里使用简单的XOR进行模拟加密,仅用于演示流程
    encrypted_order = bytearray()
    for i, byte in enumerate(order_data):
        encrypted_order.append(byte ^ session_key[i % len(session_key)])
    encrypted_order = bytes(encrypted_order)
    print(f"  加密后的订单数据: {encrypted_order.hex()[:64]}...")
    
    # d. 计算订单数据的SM3哈希
    order_hash = sm3.sm3_hash(order_data)
    order_hash_bytes = bytes.fromhex(order_hash)
    print(f"  订单SM3哈希: {order_hash}")
    
    # e. 对哈希值进行数字签名 (模拟客户端签名)
    # 注意:实际中客户端应有自己的私钥。此处为演示,我们用服务器私钥模拟客户端私钥。
    # 这在实际中是不安全的!仅为流程演示。
    client_signer = sm2.CryptSM2()
    client_signer.set_private_key(server_priv)  # !!! 仅为演示,实际应用需替换
    user_id = b"ClientAlice"
    signature = client_signer.sign(order_data, user_id)  # 对原始数据签名
    print(f"  生成签名 (长度 {len(signature)}): {signature.hex()[:64]}...")
    
    # 客户端组装数据包
    secure_packet = {
        'encrypted_key': encrypted_session_key,
        'encrypted_data': encrypted_order,
        'signature': signature,
        'user_id': user_id
    }
    print("  安全数据包组装完成。")
    
    # ===== 服务器:接收并处理安全数据 =====
    print("\n3. 服务器处理安全数据包")
    # a. 用自己的私钥解密会话密钥
    server_decryptor = sm2.CryptSM2()
    server_decryptor.set_private_key(server_priv)
    decrypted_session_key = server_decryptor.decrypt(secure_packet['encrypted_key'])
    print(f"  解密出的会话密钥: {decrypted_session_key.hex()[:32]}...")
    assert decrypted_session_key == session_key, "会话密钥解密错误!"
    
    # b. 用解密出的会话密钥解密订单数据
    decrypted_order = bytearray()
    for i, byte in enumerate(secure_packet['encrypted_data']):
        decrypted_order.append(byte ^ decrypted_session_key[i % len(decrypted_session_key)])
    decrypted_order = bytes(decrypted_order)
    print(f"  解密出的订单: {decrypted_order}")
    assert decrypted_order == order_data, "订单数据解密错误!"
    
    # c. 计算解密后订单的SM3哈希
    computed_hash = sm3.sm3_hash(decrypted_order)
    print(f"  服务器计算的订单哈希: {computed_hash}")
    
    # d. 验证客户端签名 (使用客户端的公钥)
    # 注意:实际中服务器应预先持有客户端的公钥。此处为演示,我们用服务器公钥模拟。
    server_verifier = sm2.CryptSM2()
    server_verifier.set_public_key(server_pub)  # !!! 仅为演示,实际应用需替换为客户端公钥
    is_signature_valid = server_verifier.verify(
        secure_packet['signature'],
        decrypted_order,
        secure_packet['user_id']
    )
    
    print(f"\n4. 验证结果")
    print(f"  数据完整性检查: {'通过' if decrypted_order == order_data else '失败'}")
    print(f"  数字签名验证: {'通过' if is_signature_valid else '失败'}")
    
    if decrypted_order == order_data and is_signature_valid:
        print("  ✅ 安全通信成功!数据完整、真实且保密。")
    else:
        print("  ❌ 安全通信失败!")

if __name__ == "__main__":
    simulate_secure_communication()

这个案例虽然简化了加密过程(用XOR代替SM4),但清晰地展示了SM2和SM3如何协同工作,构建一个具备保密性、完整性和不可否认性的安全通信流程。在实际的金融或政务系统中,流程会更加复杂和严谨,但核心思想是一致的。

6. 常见问题、性能调优与兼容性处理

在实际开发和系统集成中,你肯定会遇到各种各样的问题。这里我总结了一些常见的坑和解决思路。

6.1 常见错误与排查指南

  1. ImportError: libgmssl.so: cannot open shared object file

    • 问题 : 这是最典型的错误,意味着Python找不到GmSSL的C语言动态库。
    • 解决 :
      • Linux/macOS : 确保已正确运行 sudo ldconfig (Linux)或将GmSSL的lib目录添加到 LD_LIBRARY_PATH (macOS可能是 DYLD_LIBRARY_PATH )环境变量中。
      • Windows : 将GmSSL的 bin 目录(包含 gmssl.dll )添加到系统的PATH环境变量中。使用WSL2可以避免很多Windows下的库依赖问题。
    • 检查 : 在终端执行 gmssl version ,看是否能找到命令。如果能,说明C库安装成功。
  2. 签名验签失败,尤其是与第三方系统对接时

    • 可能原因1:用户ID不一致 。SM2签名算法要求签名和验签双方使用相同的用户ID。确认对方使用的是默认ID( b'1234567812345678' )还是空ID b'' ,或者特定的标识符。
    • 可能原因2:公钥格式不匹配 。对方提供的公钥可能是带 0x04 前缀的65字节格式,也可能是去掉前缀的64字节格式,或者是PEM格式。你需要根据 gmssl 库的要求进行转换。 gmssl.CryptSM2 的 set_public_key 方法通常需要64字节的裸公钥(X||Y)。
    • 可能原因3:哈希计算方式不同 。确保双方都是对 原始数据 计算SM3哈希后进行签名,而不是对哈希值本身进行签名。有些底层库的接口设计可能让人困惑。
    • 排查步骤 :
      • 使用双方都认可的测试向量(一组标准的明文、私钥、公钥、签名)进行交叉验证。
      • 打印并对比中间值:自己计算的SM3哈希值、签名结果的R和S分量(如果可能拆分的话)。
      • 与对方确认算法参数细节,包括椭圆曲线名称、哈希算法、用户ID、签名编码格式(ASN.1 DER编码还是裸拼接)。
  3. 加密解密数据长度问题

    • 问题 : 使用SM2加密较长的数据时失败或报错。
    • 原因 : 如前所述,SM2作为非对称加密,不适合直接加密大量数据。 gmssl 的 encrypt 方法可能对输入长度有限制。
    • 解决 : 采用 混合加密 。
      1. 生成一个随机的对称密钥(如32字节的随机数,作为SM4的密钥)。
      2. 使用SM2加密这个对称密钥。
      3. 使用SM4(或其他对称加密算法)用该对称密钥加密你的实际数据。
      4. 将加密后的对称密钥和加密后的数据一起发送。
      5. 接收方先用SM2解密出对称密钥,再用对称密钥解密数据。
  4. 性能瓶颈

    • SM2 : 非对称加密/解密、签名/验签是CPU密集型操作,比对称加密慢几个数量级。避免在循环或高频请求中对大量数据直接进行SM2加密。
    • 优化建议 :
      • 会话复用 : 在HTTPS等场景中,通过握手建立连接后,使用对称加密算法(如SM4)来加密后续的通信流量,SM2仅用于初始的密钥交换和身份认证。
      • 异步处理 : 在Web服务器中,将耗时的SM2运算放到异步任务队列中执行,避免阻塞主请求线程。
      • 硬件加速 : 在性能要求极高的场景,寻找支持国密算法硬件加速的密码卡或密码机。

6.2 与其他系统的兼容性处理

国密算法推广过程中,一个很大的挑战就是不同厂商、不同语言实现之间的兼容性。

  1. 与Java后端对接 :

    • Java生态中常用的国密库是BouncyCastle。你需要确保双方使用的曲线参数、点编码格式、签名编码格式一致。
    • 关键点 : Java的BouncyCastle生成的SM2签名默认可能是ASN.1 DER编码格式,而 gmssl 默认可能是 r||s 的裸拼接格式。你需要确认格式并进行必要的转换。 gmssl 库可能提供了 sign 和 verify 的变体方法来处理不同格式。
  2. 与OpenSSL命令行工具互操作 :

    • 新版本的OpenSSL已经支持国密算法。你可以使用 openssl sm2 、 openssl sm3 等命令进行测试和验证。
    • 生成SM2密钥对 : openssl ecparam -genkey -name sm2p256v1 -out sm2-private.pem
    • 提取公钥 : openssl ec -in sm2-private.pem -pubout -out sm2-public.pem
    • 使用OpenSSL验证 gmssl 的签名 : 这需要你将签名和公钥转换成OpenSSL能识别的格式(通常是PEM和DER),是一个很好的交叉验证手段。
  3. 前端(如JavaScript)加密 :

    • 在前端浏览器中使用国密算法,可以考虑 sm-crypto 这个库。同样,需要前后端协商好公钥格式、用户ID、数据编码(如是否Base64)等所有细节。
    • 一个常见的流程是:后端生成SM2密钥对,将公钥(通常转换为Base64)传给前端。前端用 sm-crypto 的SM2加密一个随机生成的对称密钥(或直接加密小数据),将密文传给后端解密。

6.3 生产环境部署建议

  1. 密钥安全管理 :

    • 绝不硬编码 : 私钥必须从安全的配置中心、环境变量或硬件安全模块(HSM)中读取。
    • 使用密码机/云KMS : 对于金融级应用,考虑使用专业的密码机或云服务商提供的密钥管理服务(KMS)来执行签名、解密等核心操作,私钥永不离开安全硬件。
  2. 依赖管理 :

    • 将 gmssl 的C库编译安装步骤写入部署脚本(如Dockerfile),确保环境一致性。
    • 在 requirements.txt 中固定 gmssl-python 的版本号,避免因库更新导致的不兼容。
  3. 监控与日志 :

    • 对加解密、签名验签操作进行适当的日志记录( 注意不要记录敏感数据本身,如私钥、明文 ),记录操作结果(成功/失败)、耗时、数据长度等,便于故障排查和性能分析。
    • 设置告警,当签名验证失败率异常升高时,可能意味着遭受攻击或系统兼容性问题。

国密算法的Python实现,从早期的摸索到现在的逐步成熟,工具链已经完善了很多。 gmssl 库是一个可靠的选择,虽然它在一些高级功能和错误信息的友好度上还有提升空间,但足以支撑起大多数生产应用。核心在于理解算法背后的原理,明确交互的协议细节,并在开发测试阶段就做好充分的交叉验证。当你成功打通与另一个系统的国密通信时,那种成就感,会让你觉得踩过的所有坑都是值得的。

Python实现SM2国密算法:从原理到实战完整指南 椭圆曲线密码学(ECC)作为现代非对称加密的基石,通过基于椭圆曲线离散对数问题的数学原理,在保证安全性的同时,相比RSA等传统算法具有密钥短、计算效率高的优势。其技术价值在于为数字身份认证、安全通信和数据完整性保护提供了高效解决方案,广泛应用于金融支付、物联网安全和政务系统等对数据安全有强合规要求的场景。本文聚焦于国密算法标准中的SM2实现,深入解析其基于特定椭圆曲线参数的加密与签名机制,并针对Python生态中常见的密文格式兼容性(如C1C2C3与C1C3C2顺序差异)和SM3杂凑算法绑定等关键问题,提供 阅读详情

相关推荐

Python国密算法SM2/SM3实战:从标准合规到高并发架构设计

密码学是保障数据安全的核心技术,其核心原理在于通过数学算法对信息进行加密、解密和完整性验证,确保数据的机密性、完整性和不可否认性。在工程实践中,密码学算法的选择与实现直接关系到系统的安全性与性能。国密算法(SM2/SM3)作为我国自主设计的密码标准,在政务、金融等关键领域已成为合规刚需。其技术价值在于满足安全测评要求的同时,保障了密码技术的自主可控。然而,在实际应用场景中,尤其是在高并发、高可用的服务架构下,开发者常面临标准合规性验证、性能瓶颈、线程安全以及生产环境稳定性等挑战。本文聚焦于**Python*

weixin_29741447的博客 312

NokiaS40和S60开发平台1.0已知问题(翻译)

NokiaS40和S60开发平台1.0已知问题(翻译)作者:陈跃峰出自:http://blog.youkuaiyun.com/mailbomb 1、  Nokia3300不支MMA(声音处理)类库。2、  Image.getGraphics()方法在不同的软件版本中工作不同,该方法无法在新版本的7650、3650和N-Gage中正常工作。即这些机器中无法实现双缓冲技术。3、  Nokia7650、3650和N

爪哇米工作室陈跃峰的移动开发博客 1万+

Python国密算法SM2/SM3签名验签不一致问题排查与修复指南

国密算法(SM2、SM3、SM4)作为我国自主研发的商用密码标准,在金融、政务等关键领域的数据安全传输与身份认证中扮演着核心角色。其技术原理基于椭圆曲线密码学(SM2)和密码杂凑算法(SM3),通过非对称加密和哈希校验保障数据的机密性、完整性与不可否认性。在工程实践中,Python开发者常因标准理解偏差、库实现差异和环境编码陷阱,遭遇SM2签名验签不一致、SM3哈希值对不上等典型问题。这些问题的根源往往在于密钥格式、签名输出格式、用户ID处理及数据编码等环节缺乏统一规范。本文聚焦SM2签名验签与SM3哈希校

weixin_34050005的博客 383

关于S40第五版SDK的一些说明(翻译)

 关于S40第五版SDK的一些说明(翻译)作者:陈跃峰出自:http://blog.youkuaiyun.com/mailbomb原文:https://blogs.forum.nokia.com/view_entry.html?id=608        S40第五版SDK(包括Java ME和Flash Lite2.1)已经推出,你可能疑惑的是,我们跳过了推出第四版。      

爪哇米工作室陈跃峰的移动开发博客 3657

Python实现SM2国密算法:加密解密与签名验签实战指南

公钥密码学是现代信息安全的核心技术之一,它基于数学难题构建了非对称加密体系,能够实现安全的数据传输和身份认证。其核心原理是利用一对数学相关的密钥(公钥和私钥),公钥可公开分发用于加密或验证签名,私钥则严格保密用于解密或生成签名。这项技术的价值在于解决了对称加密中密钥分发的难题,并广泛应用于数字签名、密钥协商等场景。在金融、政务、物联网等领域,中国自主研发的国密算法SM2已成为重要的安全标准。SM2基于椭圆曲线密码学(ECC),相比传统RSA算法,在相同安全强度下具有更短的密钥长度和更快的运算速度。本文聚焦于

weixin_32234493的博客 243

Python国密SM2算法实战:基于GmSSL的完整实现与避坑指南

椭圆曲线密码学(ECC)作为现代公钥密码体系的核心,通过椭圆曲线上的数学难题为数据安全提供保障。其原理基于离散对数问题的难解性,在相同安全强度下,比RSA等传统算法拥有更短的密钥长度和更高的运算效率,技术价值体现在兼顾安全性与性能。这一特性使其广泛应用于数字签名、密钥协商和加密传输等场景,特别是在对安全合规性有严格要求的领域。国密SM2算法作为我国自主设计的椭圆曲线密码标准,正是ECC在商用密码领域的典型实践。本文聚焦于SM2算法的Python工程实现,针对开发中常见的密钥管理、签名验签及加密解密等核心操作

weixin_33896726的博客 530

开发NokiaS40系列应用程序初级篇

作者:mingjava  文章来源:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=80 本文讲述如何搭建Nokia S40系列手机应用程序的开发环境,并对Nokia UI包进行简单的介绍。最后提供一个简单的应用程序。    我们把Nokia 7210 MIDP SDK集成到eclipse环境下,这样方便我们进行开发。首先我们搭建起

mobilechannel的专栏 2576

OpenSSL 3.1.1 SM2国密算法实战:如何用C++实现一个安全的文件签名与验签工具

本文详细介绍了如何使用OpenSSL 3.1.1的SM2国密算法实现安全的文件签名与验签工具,涵盖密钥生成、SM3摘要计算、签名验签流程及工程化实践。通过实战案例,帮助开发者构建符合等保2.0要求的企业级安全解决方案,确保数据完整性和来源可信。

weixin_30756499的博客 655

Nokia S40 真机调试

长期以来,诺基亚 Serial 40平台上的J2ME程序一直不支持真机调试,最近诺基亚推出一款叫做Series 40 On-Device Debugger的工具,填补了这一空白。用户可以在http://www.developer.nokia.com/Develop/Java/Tools/Series40_debugger.xhtml 上下载该工具,现在推出的还是Beta版。 Series 40

Roy的IT笔记 1723

个信Gexin_S40_240_320.jar

Gexin_S40_240_320.jar 跨网免费发短信

小智AI语音控制实战:从工具注册到音量调节的MCP交互全流程

本文详细拆解了基于小智AI与MCP协议实现本地智能语音控制的完整交互流程。以ESP32平台为例,从开发环境搭建、MCP服务器初始化、工具注册,到用户语音指令的接收、解析、硬件执行与结果反馈,提供了全链路实战代码。重点阐述了如何通过MCP协议将AI的意图理解与设备功能执行在本地高效耦合,实现毫秒级响应的音量调节等控制,为嵌入式AI开发者提供了清晰的实现路径。

weixin_29165725的博客 347

国密算法 SM2公钥密码 SM3杂凑算法 SM4分组密码 python代码完整实现

国密算法 SM2公钥密码 SM3杂凑算法 SM4分组密码 python代码完整实现 效率高于所有公开的python国密算法库

qq_43339242的博客 1万+

从硬件异常到代码救赎:RH850内存访问错误(MAE)的深层诊断与艺术

本文深入探讨瑞萨RH850微控制器的内存访问错误(MAE)诊断与解决方法。针对程序跑飞和Flash Driver交互中的潜在陷阱,提供系统性硬件异常分析框架和防御性编程实践,帮助嵌入式开发者从底层机制到代码层面有效预防和修复MAE问题,提升系统稳定性。

pytorch8learner的博客 197

python模块gmssl,SM国密算法

gmssl 是一个用于处理国密算法的 Python 模块,它提供了对国密算法的支持,包括对称加密、非对称加密、散列函数和数字签名等,仅列出了其中两个较为完善的第三方库,需要注意的是,SM1 和 SM7 算法不公开,目前大多库仅实现了 SM2、SM3、SM4 三种密算法。

老衲爱洗头的博客 1万+

初学者入门机器学习 (ML)的推荐教程

了解基本的机器学习概念并不难。有大量免费的在线博客文章、视频和编码教程可以引导您了解基础知识——从介绍性内容到常见应用程序,再到算法和应用技能。这篇文章总结了一些用于介绍 ML 的最佳免费选项。它按逻辑顺序排列,每个概念都建立在上一个概念的基础上。

u010542847的博客 4620

Android14到Android16源码移植中的Bluetooth模块规范适配指南

本文详细解析了从Android14到Android16源码移植过程中Bluetooth模块的规范适配挑战,重点介绍了Android.bp配置差异及常见编译报错解决方案。针对代码规范检查、final字段声明、静态方法优化等核心问题提供实用修复方法,帮助开发者高效完成版本升级适配工作。

fire9的博客 254

用Python实现SM2国密算法:国密安全性的可靠选择

用Python实现SM2国密算法:国密安全性的可靠选择 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在数字安全领域,国密算法作为官方指定的加密标准,具有极高的安全性和可靠性。今天,我将为您推荐一个开源项目——用Python实现SM2国密算法。SM2是推荐的椭圆曲线公钥密码算法,广泛应用于数字签名、验签、加密解密等多种场景。这个项目利用Python语言,实现了SM2算...

gitblog_06738的博客 1027

Aruba CX交换机VSX配置实战:如何避免脑裂导致的网络中断(含详细命令)

本文提供Aruba CX交换机VSX配置的实战指南,重点讲解如何通过构建高可靠的ISL链路聚合与独立隔离的Keepalive链路,有效避免网络脑裂风险。文章包含详细的命令步骤,从基础配置到高级故障排查,帮助网络工程师构建坚如磐石的高可用核心网络,确保业务流量零中断。

weixin_29231725的博客 172

SM3国密算法深度研究:原理、实现与应用(Python、Rust)

本论文对中国国家密码管理局发布的商用密码杂凑算法标准——SM3进行了系统性、多层次的深度研究。论文首先从数学基础入手,详细剖析了SM3算法的核心组件,包括其独特的分段布尔函数(FF与GG)和置换函数(P0与P1),并阐述了这些数学概念如何通过实现混淆与扩散来支撑算法的整体安全架构。其次,论文深入探讨了SM3算法的实现原理,系统地介绍了其遵循的Merkle-Damgård结构,并对消息填充、消息扩展、压缩函数等关键模块的运作机制进行了详尽的解释,同时提供了直观的伪代码和性能优化策略。

自律即自由 1961

Python爬虫实战:链家/贝壳租房数据抓取与可视化分析平台

本文详细介绍了如何使用Python爬虫技术抓取链家/贝壳网站的租房信息,并构建一个完整的数据可视化分析平台。文章涵盖了从数据抓取、数据清洗、数据存储到数据可视化的全流程,使用最新的Python技术栈,包括AsyncIOPandasMongoDB和Pyecharts等库。本系统可作为毕业设计项目,提供了完整的代码实现和架构设计。关键词:Python爬虫、数据抓取、数据可视化、链家、贝壳、租房信息、毕业设计。

2201_76125261的博客 1207

轨迹优化 | 图解欧氏距离场与梯度场算法(附ROS C++/Python实现)

距离场在运动规划中则常用于地图建模和轨迹梯度优化。本文图解欧氏距离场EDT的算法原理,并基于双线性插值给出欧氏梯度场的公式推导,并给出ROS C++和Python的算法实现加深理解

FRIGIDWINTER的博客 4646

JavaScript逆向SM国密算法

SM 国密指的是由中国国家密码管理局(State Cryptography Administration)发布的一系列国家商用密码标准。简单来说,“国密”是中国自主研发、拥有完全自主知识产权的一套密码算法体系。SM是“商用密码”的拼音首字母缩写。国密指的是国家密码标准。这套体系的诞生,其核心战略目标是实现信息安全领域的自主可控,摆脱对国际通用加密算法(主要是由美国设计和标准化的算法,如 AES、RSA、SHA-2 等)的依赖,确保在中国境内的关键信息基础设施和重要领域的数据安全。

SamsongSSS的博客 2146

【DaVinci Configurator专题】-5-通过Data Mapping自动创建CAN信号关联的Port并添加到APP SWC

目录 1 导入CAN Matrix变更后的Arxml文件 2 自动创建CAN信号关联的APP Port 3 CAN信号与App SWC的接口映射/连接 4 结尾 <--返回「实战篇」博文-总目录--> <--返回「Autosar从入门到精通-实战篇」专栏主页--> 关键词: DaVinci Developer DaVinci Configurator Pro ARXML AUTOSAR System Description Network Explorer 1

「汽车电子助手」的博客 5130

国密算法 SM2 公钥加密 非对称加密 数字签名 密钥协商 python实现完整代码

国密SM2算法的Python工具包,实现SM2数字签名与验证、公钥加解密以及密钥协商等功能,也可基于本工具包提供的椭圆曲线运算相关函数自行设计算法和协议。代码完整,复制即用。

qq_43339242的博客 1万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

跨语言国密SM2加密解密实战:JavaScript与Python互通指南

通过本文的实战演练,我们成功实现了JavaScript与Python的SM2加密解密互通。密钥格式统一:确保两端使用同一套密钥对,且格式一致。加密模式统一:推荐使用国密标准的C1C3C2模式。编码一致:建议统一使用十六进制字符串传输密文。未来,随着国密算法的普及和生态完善,SM2将在更多场景中替代国际算法,成为数据安全的中坚力量。开发者应积极拥抱国密,为国产化替代贡献力量。参考文献sm-crypto官方文档gmssl-python官方仓库优快云博客《SM2加解密(JS与Java互通)》

未来已来,AI时代,学AI编程,做AI量化,就来大鹏AI教育。 1614

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

用Python实现SM2国密算法

用Python实现SM2国密算法 去发现同类优质开源项目:https://gitcode.com/ 简介 本仓库提供了一份用Python语言编写的SM2国密算法实现压缩包。SM2是中国指定的椭圆曲线公钥密码算法,用于数字签名、验签和加密解密等场景。压缩包内包含了SM3算法的代码,这是因为SM2在运算过程中需要调用SM3杂凑算法来计算hash值。所有代码均按照国密标准进行了实现。 内容概述 sm3...

gitblog_06794的博客 689

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

上一篇: 多维聚合、滚动计算与结构重塑:银行级Pandas生产实践
下一篇: BLDC电机FOC控制方案:A89307与PIC18F86J10实现15A驱动
java2000_test
博客等级 码龄19年 10粉丝 320原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值