#pairing #crypto #shangmi

sm9

SM9 (OSCCA GM/T 0044-2016), identity-based cryptography

9 releases

0.3.2 Nov 4, 2024
0.3.0 Oct 25, 2024
0.2.6 Sep 9, 2024
0.2.5 Jul 13, 2024
0.1.0 Dec 16, 2023

#298 in Cryptography

Download history 219/week @ 2024-09-09 24/week @ 2024-09-16 22/week @ 2024-09-23 3/week @ 2024-09-30 102/week @ 2024-10-21 9/week @ 2024-10-28 159/week @ 2024-11-04 4/week @ 2024-11-11 9/week @ 2024-11-18 84/week @ 2024-12-02

104 downloads per month

MIT/Apache

3MB
1K SLoC

SM9

Pure Rust implementation of the SM9 identity-based cryptographic algorithms as defined in the Chinese national standard GM/T 0044-2016 as well as ISO/IEC 11770.

Usage

Add the sm9 crate to your dependencies in Cargo.toml

[dependencies]
sm9 = "0.3.2"

Examples

Example1: Encrypt

(See encryption.rs for the full example.)

    use sm9::*;

    let usr_id = b"Bob";
    let txt = b"Chinese IBE standard";
    let m = Sm9::encrypt("master_public_key.pem", usr_id, txt);
    println!("{:02X?}", m);

    let msg = Sm9::decrypt("bob_private_key.pem", usr_id, m).expect("decrypt error");
    println!("{:02X?}", msg);
    assert_eq!(msg.len(), txt.len());
    assert_eq!(txt, msg.as_slice());

    use std::fs;
    let master_public_key =
        fs::read_to_string("master_public_key.pem").expect("read master_public_key.pem error");
    let m = Sm9::encrypt2(&master_public_key, usr_id, txt);
    println!("{:02X?}", m);

    let bob_private_key =
        fs::read_to_string("bob_private_key.pem").expect("read bob_private_key.pem error");
    let msg = Sm9::decrypt2(&bob_private_key, usr_id, m).expect("decrypt error");
    println!("{:02X?}", msg);
    assert_eq!(msg.len(), txt.len());
    assert_eq!(txt, msg.as_slice());

Example2: Signature

(See signature.rs for the full example.)

    use sm9::*;
    
    //Sign
    let m = b"Chinese IBS standard";
    let user_id = b"Alice";
    let sig = Sm9::sign(
        "master_signature_public_key.pem",
        "alice_signature_private_key.pem",
        m,
    );
    println!("{:02X?}", sig.h_as_ref());
    println!("{:02X?}", sig.s_as_ref());

    //Verify
    let mut bytes = Vec::<u8>::new();
    bytes.extend_from_slice(sig.h_as_ref());
    bytes.extend_from_slice(sig.s_as_ref());
    let sig_rev = Signature::from_slice(bytes.as_ref()).unwrap();
    assert!(Sm9::verify(
        "master_signature_public_key.pem",
        user_id,
        m,
        &sig_rev
    ));

    use std::fs;
    let master_signature_public_key = fs::read_to_string("master_signature_public_key.pem")
        .expect("read master_signature_public_key.pem error");
    let alice_signature_private_key = fs::read_to_string("alice_signature_private_key.pem")
        .expect("read alice_signature_private_key.pem error");
    let sig = Sm9::sign2(
        &master_signature_public_key,
        &alice_signature_private_key,
        m,
    );

    assert!(Sm9::verify2(&master_signature_public_key, user_id, m, &sig));

Example3: Key Exchange

(See exchange.rs for the full example.)

use sm9::*;
    let mpk = MasterPublicKey::read_pem_file("master_exchange_public_key.pem")
        .expect("read master_public_key_file error");
    let alice_id = b"Alice";
    let alice_key = UserPrivateKey::read_pem_file("alice_exchange_private_key.pem")
        .expect("read user_privte_key_file error");
    let bob_id = b"Bob";
    let bob_key = UserPrivateKey::read_pem_file("bob_exchange_private_key.pem")
        .expect("read user_privte_key_file error");
    // the initiator A
    let mut initiator = KeyExchanger::new(alice_id, &alice_key, &mpk, true).unwrap();
    // the responder B
    let mut responder = KeyExchanger::new(bob_id, &bob_key, &mpk, false).unwrap();
    // A Step 3: compute 𝑅𝐴
    let ra = initiator.generate_ephemeral_secret(bob_id).unwrap();
    // A Step 4: send 𝑅𝐴 to B

    // B Step 3: compute 𝑅B
    let rb = responder.generate_ephemeral_secret(alice_id).unwrap();
    //  B Step 4: send 𝑅B to A
    // A compute shared_secret use received rb
    let rb_received = EphemeralSecret::from_slice(rb.as_slice());
    let ska = initiator.generate_shared_secret(&rb_received).unwrap();
    // B compute shared_secret use received ra
    let ra_received = EphemeralSecret::from_slice(ra.as_slice());
    let skb = responder.generate_shared_secret(&ra_received).unwrap();
    assert_eq!(ska, skb);
    // B Step 6: (optional) compute SB, and send it to A
    let sb = responder.generate_comfirmable_secret().unwrap();
    // A (optional) confirmation from B to A
    let sb_received = ComfirmableSecret::from_slice(sb.as_slice());
    let confirmation_a = initiator.comfirm(&sb_received).unwrap();
    // A Step 8: (optional) compute 𝑆𝐴, and send it to B,
    let sa = initiator.generate_comfirmable_secret().unwrap();
    // B (optional) confirmation from A to B
    let sa_received = ComfirmableSecret::from_slice(sa.as_slice());
    let confirmation_b = responder.comfirm(&sa_received).unwrap();
    assert!(confirmation_a);
    assert!(confirmation_b);

License

Licensed under either of

at your option.

Copyright 2024 John-Yu.

Authors

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~10MB
~100K SLoC