lit_utilities_wasm/
bls.rs

1use std::convert::TryFrom;
2
3use blsful::{
4    Bls12381G1Impl, Bls12381G2Impl, BlsSignatureImpl, PublicKey, Signature, SignatureSchemes,
5    TimeCryptCiphertext,
6};
7use elliptic_curve::group::GroupEncoding;
8use js_sys::Uint8Array;
9use serde::Deserialize;
10use tsify::Tsify;
11use wasm_bindgen::prelude::*;
12
13use crate::abi::{from_js, from_uint8array, into_uint8array, JsResult};
14
15#[derive(Tsify, Deserialize)]
16#[tsify(from_wasm_abi)]
17pub enum BlsVariant {
18    Bls12381G1,
19    Bls12381G2,
20}
21
22struct Bls<C>(C);
23
24impl<C: BlsSignatureImpl> Bls<C>
25where
26    C::PublicKey: TryFrom<Vec<u8>>,
27    C::Signature: TryFrom<Vec<u8>>,
28    C::SignatureShare: TryFrom<Vec<u8>>,
29{
30    pub fn combine(signature_shares: Vec<Uint8Array>) -> JsResult<Uint8Array> {
31        let signature_shares = signature_shares
32            .into_iter()
33            .map(from_uint8array)
34            .collect::<JsResult<Vec<_>>>()?;
35
36        let signature = C::core_combine_signature_shares(&signature_shares)?;
37
38        into_uint8array(signature.to_bytes())
39    }
40
41    pub fn verify(
42        public_key: Uint8Array,
43        message: Uint8Array,
44        signature: Uint8Array,
45    ) -> JsResult<()> {
46        let public_key = from_uint8array(public_key)?;
47        let signature = from_uint8array(signature)?;
48        let message = from_js::<Vec<u8>>(message)?;
49
50        let signature = Signature::<C>::ProofOfPossession(signature);
51
52        signature.verify(&PublicKey(public_key), message)?;
53
54        Ok(())
55    }
56
57    pub fn encrypt(
58        encryption_key: Uint8Array,
59        message: Uint8Array,
60        identity: Uint8Array,
61    ) -> JsResult<Uint8Array> {
62        let encryption_key = from_uint8array(encryption_key)?;
63        let encryption_key = PublicKey::<C>(encryption_key);
64
65        let message = from_js::<Vec<u8>>(message)?;
66        let identity = from_js::<Vec<u8>>(identity)?;
67
68        let ciphertext = encryption_key.encrypt_time_lock(
69            SignatureSchemes::ProofOfPossession,
70            message,
71            identity,
72        )?;
73        let ciphertext = serde_bare::to_vec(&ciphertext)?;
74
75        into_uint8array(ciphertext)
76    }
77
78    pub fn decrypt(ciphertext: Uint8Array, decryption_key: Uint8Array) -> JsResult<Uint8Array> {
79        let decryption_key = from_uint8array(decryption_key)?;
80
81        let ciphertext = from_js::<Vec<u8>>(ciphertext)?;
82        let ciphertext = serde_bare::from_slice::<TimeCryptCiphertext<C>>(&ciphertext)?;
83
84        let message = ciphertext.decrypt(&Signature::ProofOfPossession(decryption_key));
85        let message =
86            Option::<Vec<u8>>::from(message).ok_or_else(|| JsError::new("decryption failed"))?;
87
88        into_uint8array(message)
89    }
90}
91
92#[wasm_bindgen(js_name = "blsCombine")]
93pub fn bls_combine(variant: BlsVariant, signature_shares: Vec<Uint8Array>) -> JsResult<Uint8Array> {
94    match variant {
95        BlsVariant::Bls12381G1 => Bls::<Bls12381G1Impl>::combine(signature_shares),
96        BlsVariant::Bls12381G2 => Bls::<Bls12381G2Impl>::combine(signature_shares),
97    }
98}
99
100#[wasm_bindgen(js_name = "blsVerify")]
101pub fn bls_verify(
102    variant: BlsVariant,
103    public_key: Uint8Array,
104    message: Uint8Array,
105    signature: Uint8Array,
106) -> JsResult<()> {
107    match variant {
108        BlsVariant::Bls12381G1 => Bls::<Bls12381G1Impl>::verify(public_key, message, signature),
109        BlsVariant::Bls12381G2 => Bls::<Bls12381G2Impl>::verify(public_key, message, signature),
110    }
111}
112
113#[wasm_bindgen(js_name = "blsEncrypt")]
114pub fn bls_encrypt(
115    variant: BlsVariant,
116    encryption_key: Uint8Array,
117    message: Uint8Array,
118    identity: Uint8Array,
119) -> JsResult<Uint8Array> {
120    match variant {
121        BlsVariant::Bls12381G1 => Bls::<Bls12381G1Impl>::encrypt(encryption_key, message, identity),
122        BlsVariant::Bls12381G2 => Bls::<Bls12381G2Impl>::encrypt(encryption_key, message, identity),
123    }
124}
125
126#[wasm_bindgen(js_name = "blsDecrypt")]
127pub fn bls_decrypt(
128    variant: BlsVariant,
129    ciphertext: Uint8Array,
130    decryption_key: Uint8Array,
131) -> JsResult<Uint8Array> {
132    match variant {
133        BlsVariant::Bls12381G1 => Bls::<Bls12381G1Impl>::decrypt(ciphertext, decryption_key),
134        BlsVariant::Bls12381G2 => Bls::<Bls12381G2Impl>::decrypt(ciphertext, decryption_key),
135    }
136}