Rust implementation of commuting signatures, a primitive introduced in the paper Commuting Signatures and Verifiable Encryption and an Application to Non-Interactively Delegatable Credentials.
a signer can encrypt both signature and message and prove validity; more importantly, given a ciphertext, a signer can create a verifiably encrypted signature on the encrypted message; thus signing and encrypting commute.
The scheme uses commitment scheme as an encryption, and a zero knowledge proof to verify the committed (or encrypted) values are actually the message being signed or the signature on that message.
// public parameters
let params = Params::<E>::rand(rng);
let signer = Signer::rand(rng);
let verifier = signer.verifier(¶ms);
// the value being signed
let value = Fr::rand(rng);
// ciphertexts are the commitments and the ZK proofs.
let (message, signature, ciphertexts) = signer.sign(rng, ¶ms, value);
// verify signature
assert!(verifier.verify(¶ms, &message, &signature));
// verify ciphertexts
assert!(verifier.verify_ciphertexts(¶ms, &ciphertexts));
// Here is another signer. You can also use the same signer.
let signer2 = Signer::rand(rng);
let verifier2 = signer2.verifier(¶ms);
// sign on the encrypted message, output another ciphertexts that contains commitment to the signature
let ciphertexts2 = signer2.sign_on_ciphertexts(rng, ¶ms, &ciphertexts);
// verify different ciphertexts
assert!(verifier2.verify_ciphertexts(¶ms, &ciphertexts2));