CCM加密模式及客户端示例
1 简介
CCM (Counter with CBC-MAC) - 计数器与 CBC-MAC 模式
定义:CCM 是 CTR 与 CBC-MAC 的组合,提供 AEAD 功能。
工作原理:
先用 CBC-MAC 计算认证标签(基于明文、AAD 和 nonce)。
然后用 CTR 加密明文。
加密:MAC = CBC-MAC(K, B),其中 B 是格式化的块(nonce、长度、AAD、明文);然后 C = P \oplus CTR_stream,Tag = MAC \oplus CTR_0。

解密:验证 Tag 后解密。
优缺点:
优点:单密钥、提供认证、适合资源受限设备。
缺点:两次遍历数据(MAC + 加密),不如 GCM 高效;nonce 必须唯一。
安全考虑:IND-CCA2 安全,但对 nonce 长度有要求(7-13 字节)。SM4-CCM 在无线传感器网络标准中常见。
SM4 应用:IoT 设备加密、Zigbee 协议。
2 CCM模式 vs SCM标准模式分析
- 基本概念对比
1.1 SM4标准模式
SM4标准定义了几种基础分组密码模式:
ECB (Electronic Codebook):电子密码本模式
CBC (Cipher Block Chaining):密码分组链接模式
CFB (Cipher Feedback):密码反馈模式
OFB (Output Feedback):输出反馈模式
CTR (Counter):计数器模式
这些是基础的分组密码模式,主要提供机密性。
- CCM模式
CCM (Counter with CBC-MAC):计数器模式与CBC-MAC结合
属于认证加密模式 (Authenticated Encryption)
同时提供机密性 + 完整性认证 + 消息认
CCM vs GCM:
- CCM: 软件实现较好,抗侧信道攻击
- GCM: 硬件加速更好,支持流处理
- CCM: 专利问题(已过期)
- GCM: NIST推荐,更常用
3 客户端实现示例
-
创建SM4-CCM加解密模块
require github.com/tjfoc/gmsm v1.4.1 internal/sm4ccm/sm4ccm.go: import ( "crypto/cipher" "crypto/rand" "errors" "fmt" "io" "github.com/tjfoc/gmsm/sm4" )
SM4CCM 结构体
type SM4CCM struct {
key []byte
}
NewSM4CCM 创建SM4-CCM实例
func NewSM4CCM(key []byte) (*SM4CCM, error) {
if len(key) != 16 {
return nil, errors.New("SM4 key must be 16 bytes")
}
return &SM4CCM{key: key}, nil
}
Encrypt 加密数据 (CCM模式)
func (s *SM4CCM) Encrypt(plaintext []byte) ([]byte, error) {
// 创建SM4块
block, err := sm4.NewCipher(s.key)
if err != nil {
return nil, fmt.Errorf("create cipher failed: %v", err)
}
生成随机nonce (13字节推荐用于CCM)
nonce := make([]byte, 13)
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return nil, fmt.Errorf("generate nonce failed: %v", err)
}
创建CCM模式的AEAD
aead, err := cipher.NewCCM(block, 7, 13) // tag长度7字节,nonce长度13字节
if err != nil {
return nil, fmt.Errorf("create CCM failed: %v", err)
}
附加数据(可以为空)
additionalData := []byte("CCM Mode")
加密
ciphertext := aead.Seal(nil, nonce, plaintext, additionalData)
返回 nonce + ciphertex
result := make([]byte, len(nonce)+len(ciphertext))
copy(result[:13], nonce)
copy(result[13:], ciphertext)
return result, nil
}
Decrypt 解密数据
func (s *SM4CCM) Decrypt(ciphertext []byte) ([]byte, error) {
if len(ciphertext) < 13 {
return nil, errors.New("ciphertext too short")
}
block, err := sm4.NewCipher(s.key)
if err != nil {
return nil, fmt.Errorf("create cipher failed: %v", err)
}
创建CCM模式的AEAD
aead, err := cipher.NewCCM(block, 7, 13)
if err != nil {
return nil, fmt.Errorf("create CCM failed: %v", err)
}
分离nonce和密文
nonce := ciphertext[:13]
actualCiphertext := ciphertext[13:]
附加数据(必须与加密时一致)
additionalData := []byte("CCM Mode")
解密
plaintext, err := aead.Open(nil, nonce, actualCiphertext, additionalData)
if err != nil {
return nil, fmt.Errorf("decrypt failed: %v", err)
}
return plaintext, nil
}
GenerateKey 生成随机SM4密钥
func GenerateKey() ([]byte, error) {
key := make([]byte, 16)
if _, err := io.ReadFull(rand.Reader, key); err != nil {
return nil, err
}
return key, nil
}
- 点赞
- 收藏
- 关注作者
评论(0)