package sm
Install
dune-project
Dependency
Authors
Maintainers
Sources
sha256=4d85071a2448f91c7d6d792c1563ca2690c20e22ba188ed7bd20356e4ba684dc
sha512=0e2bbcaaeeab12a9af1287ff4ae3e0197eb6f2eafdcc337d8baf9feefca0b1575fbc043517033b22b78918d214e9ae613c2db033fd51c97a5ca5a8d28cd2198c
doc/README.html
SM - Chinese National Cryptographic Algorithms in Pure OCaml
A pure OCaml implementation of the Chinese National Cryptographic Algorithm suite, providing SM2 (elliptic curve cryptography), SM3 (cryptographic hash), SM4 (block cipher), and ZUC-128 (stream cipher) algorithms.
Table of Contents
Features
- SM2: Key generation, signature generation/verification, encryption/decryption, key exchange, DER/PEM/ASN.1 encoding and decoding
- SM3: Hash digest computation, HMAC, KDF (Key Derivation Function)
- SM4: Single-block operations, CBC, CTR, GCM modes, streaming context support
- ZUC-128: Keystream generation and stream encryption/decryption
- Pure OCaml: No external C dependencies, works across all platforms supported by OCaml
Installation
Via OPAM
opam install smFrom Source
git clone https://github.com/daysv/ocaml-sm.git
cd ocaml-sm
dune buildAdd sm to your dune project dependencies:
(executable
(name my_app)
(libraries sm))Quick Start
open Sm
(* SM3 Hash *)
let hash = Sm3.digest_string "Hello, SM!"
let hash_hex = Sm3.digest_hex "Hello, SM!"
(* SM4 Encryption (CBC mode) *)
let key = Bytes.of_string "0123456789abcdef" (* 16 bytes *)
let iv = Bytes.of_string "0123456789abcdef" (* 16 bytes *)
let plaintext = Bytes.of_string "Secret message"
let ciphertext = Sm4.Cbc.encrypt_pkcs7 ~key ~iv plaintext
let decrypted = Sm4.Cbc.decrypt_pkcs7 ~key ~iv ciphertextAPI Overview
SM2 - Elliptic Curve Cryptography
SM2 is an elliptic curve cryptographic algorithm based on the SM2 curve parameters, defined in GM/T 0003-2012.
Key Management
(* Generate or import private key *)
let scalar = Sm2.scalar_of_hex "..."
let priv_key = Sm2.private_key_of_scalar scalar
let pub_point = Sm2.derive_public_key scalar
(* PEM encoding/decoding *)
let pem = Sm2.encode_private_key_pem `Pkcs8 priv_key
let priv_key' = Sm2.decode_private_key_pem pemDigital Signature
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)Encryption/Decryption
let ciphertext = Sm2.encrypt ~k:ephemeral_scalar ~pub:pub_point plaintext
let plaintext = Sm2.decrypt ~priv:scalar ciphertextKey Exchange
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:16SM3 - Cryptographic Hash
SM3 produces a 256-bit (32-byte) hash value, specified in GM/T 0004-2012.
Basic Hashing
let hash = Sm3.digest_string "message" (* raw bytes *)
let hash_hex = Sm3.digest_hex "message" (* hex string *)
(* Incremental hashing *)
let ctx = Sm3.init ()
let ctx = Sm3.update_string ctx "chunk1"
let ctx = Sm3.update_string ctx "chunk2"
let hash = Sm3.finalize ctxHMAC
let tag = Sm3.hmac ~key:"secret_key" "message"
let tag_hex = Sm3.hmac_hex ~key:"secret_key" "message"Key Derivation (KDF)
let derived_key = Sm3.kdf ~z:shared_secret ~klen:32SM4 - Block Cipher
SM4 is a 128-bit block cipher with a 128-bit key, defined in GM/T 0002-2012.
Single Block
let ciphertext = Sm4.encrypt_block_with_key key plaintext (* 16-byte blocks *)
let plaintext = Sm4.decrypt_block_with_key key ciphertextCBC Mode
(* With PKCS#7 padding *)
let ciphertext = Sm4.Cbc.encrypt_pkcs7 ~key ~iv plaintext
let plaintext = Sm4.Cbc.decrypt_pkcs7 ~key ~iv ciphertext
(* No padding *)
let ciphertext = Sm4.Cbc.encrypt_no_pad ~key ~iv plaintextCTR Mode
let ciphertext = Sm4.Ctr.crypt ~key ~iv plaintext
(* Encryption and decryption are identical in CTR mode *)
let plaintext = Sm4.Ctr.crypt ~key ~iv ciphertextGCM Mode (Authenticated Encryption)
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 ciphertextStreaming API
(* CBC encryption with streaming *)
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 ctxZUC - Stream Cipher
ZUC is a word-oriented stream cipher that produces a 32-bit keystream word per call, specified in GM/T 0001-2012.
Stream Encryption
let ctx = Zuc.init ~key ~iv
let keystream_word = Zuc.next_word ctx
let keystream_words = Zuc.keystream_words ctx 10
(* Encrypt/decrypt bytes *)
let ciphertext = Zuc.crypt ctx plaintext
(* One-shot encryption *)
let ciphertext = Zuc.crypt_with_key ~key ~iv plaintextDocumentation
Full API documentation can be generated using odoc:
dune build @docThe generated HTML documentation will be available in _build/default/_doc/_html/.
Testing
Run the test suite:
dune runtestTest files are located in the test/ directory, covering:
- SM2 cryptographic operations
- SM3 hash and HMAC
- SM4 block cipher modes
- ZUC stream cipher
License
MIT License - see the LICENSE file for details.