package sm

  1. Overview
  2. Docs

SM - 纯 OCaml 实现的中国国家密码算法库

[版本](https://github.com/daysv/ocaml-sm) [许可证](LICENSE) [OCaml](https://ocaml.org)

纯 OCaml 实现的中国国家密码算法套件,提供 SM2(椭圆曲线密码)、SM3(密码杂凑)、SM4(分组密码)和 ZUC-128(流密码)算法。

目录

特性

  • SM2:密钥生成、签名生成与验证、加解密、密钥交换、DER/PEM/ASN.1 编解码
  • SM3:杂凑值计算、HMAC、KDF(密钥派生函数)
  • SM4:单分组操作、CBC、CTR、GCM 模式、流式上下文支持
  • ZUC-128:密钥流生成与流式加解密
  • 纯 OCaml:无外部 C 依赖,可在 OCaml 支持的所有平台上运行

安装

通过 OPAM

opam install sm

从源码构建

git clone https://github.com/daysv/ocaml-sm.git
cd ocaml-sm
dune build

在你的 dune 项目中添加 sm 依赖:

(executable
 (name my_app)
 (libraries sm))

快速开始

open Sm

(* SM3 杂凑 *)
let hash = Sm3.digest_string "Hello, SM!"
let hash_hex = Sm3.digest_hex "Hello, SM!"

(* SM4 加密(CBC 模式) *)
let key = Bytes.of_string "0123456789abcdef"  (* 16 字节 *)
let iv = Bytes.of_string "0123456789abcdef"   (* 16 字节 *)
let plaintext = Bytes.of_string "Secret message"
let ciphertext = Sm4.Cbc.encrypt_pkcs7 ~key ~iv plaintext
let decrypted = Sm4.Cbc.decrypt_pkcs7 ~key ~iv ciphertext

API 概览

SM2 - 椭圆曲线公钥密码算法

SM2 是基于 SM2 曲线参数的椭圆曲线密码算法,定义于 GM/T 0003-2012。

密钥管理

(* 生成或导入私钥 *)
let scalar = Sm2.scalar_of_hex "..."
let priv_key = Sm2.private_key_of_scalar scalar
let pub_point = Sm2.derive_public_key scalar

(* PEM 编解码 *)
let pem = Sm2.encode_private_key_pem `Pkcs8 priv_key
let priv_key' = Sm2.decode_private_key_pem pem

数字签名

let digest = Sm2.digest_for_sign ~id:"1234567812345678" pub_point message
let (r, s) = Sm2.sign_digest ~k:ephemeral_scalar ~priv:scalar ~digest
let valid = Sm2.verify_digest ~pub:pub_point ~digest ~signature:(r, s)

加解密

let ciphertext = Sm2.encrypt ~k:ephemeral_scalar ~pub:pub_point plaintext
let plaintext = Sm2.decrypt ~priv:scalar ciphertext

密钥交换

let result = Sm2.key_exchange
  ~role:`Initiator
  ~self_id:"1234567812345678"
  ~self_static:static_priv
  ~self_ephemeral:ephemeral_scalar
  ~peer_id:"8765432187654321"
  ~peer_static:peer_pub
  ~peer_ephemeral:peer_ephemeral_pub
  ~key_length:16

SM3 - 密码杂凑算法

SM3 输出 256 位(32 字节)的杂凑值,定义于 GM/T 0004-2012。

基本杂凑

let hash = Sm3.digest_string "message"           (* 原始字节 *)
let hash_hex = Sm3.digest_hex "message"          (* 十六进制字符串 *)

(* 增量杂凑 *)
let ctx = Sm3.init ()
let ctx = Sm3.update_string ctx "chunk1"
let ctx = Sm3.update_string ctx "chunk2"
let hash = Sm3.finalize ctx

HMAC

let tag = Sm3.hmac ~key:"secret_key" "message"
let tag_hex = Sm3.hmac_hex ~key:"secret_key" "message"

密钥派生(KDF)

let derived_key = Sm3.kdf ~z:shared_secret ~klen:32

SM4 - 分组密码算法

SM4 是分组长度为 128 比特、密钥长度为 128 比特的分组密码算法,定义于 GM/T 0002-2012。

单分组

let ciphertext = Sm4.encrypt_block_with_key key plaintext   (* 16 字节分组 *)
let plaintext = Sm4.decrypt_block_with_key key ciphertext

CBC 模式

(* 使用 PKCS#7 填充 *)
let ciphertext = Sm4.Cbc.encrypt_pkcs7 ~key ~iv plaintext
let plaintext = Sm4.Cbc.decrypt_pkcs7 ~key ~iv ciphertext

(* 无填充 *)
let ciphertext = Sm4.Cbc.encrypt_no_pad ~key ~iv plaintext

CTR 模式

let ciphertext = Sm4.Ctr.crypt ~key ~iv plaintext
(* CTR 模式下加密与解密操作相同 *)
let plaintext = Sm4.Ctr.crypt ~key ~iv ciphertext

GCM 模式(认证加密)

let result = Sm4.Gcm.encrypt ~key ~iv ~aad:"additional_data" plaintext
let ciphertext = result.Sm4.Gcm.ciphertext
let tag = result.Sm4.Gcm.tag

let plaintext = Sm4.Gcm.decrypt ~key ~iv ~aad:"additional_data" ~tag ciphertext

流式 API

(* 流式 CBC 加密 *)
module Stream = Sm4.Stream.Cbc_encrypt
let ctx = Stream.init ~key ~iv ~padding:`Pkcs7
Stream.update ctx chunk1
Stream.update ctx chunk2
let final_block = Stream.finalize ctx

ZUC - 流密码算法

ZUC 是面向字的流密码算法,每次调用产生一个 32 位的密钥流字,定义于 GM/T 0001-2012。

流式加解密

let ctx = Zuc.init ~key ~iv
let keystream_word = Zuc.next_word ctx
let keystream_words = Zuc.keystream_words ctx 10

(* 加解密字节 *)
let ciphertext = Zuc.crypt ctx plaintext

(* 一次性加解密 *)
let ciphertext = Zuc.crypt_with_key ~key ~iv plaintext

文档

可以使用 odoc 生成完整的 API 文档:

dune build @doc

生成的 HTML 文档位于 _build/default/_doc/_html/ 目录。

测试

运行测试套件:

dune runtest

测试文件位于 test/ 目录,覆盖:

  • SM2 密码运算
  • SM3 杂凑与 HMAC
  • SM4 分组密码模式
  • ZUC 流密码

许可证

MIT 许可证 - 详见 LICENSE 文件。