1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
//! Generate and manage the ECC keys use curve25519_dalek::{ constants::RISTRETTO_BASEPOINT_POINT, ristretto::{CompressedRistretto, RistrettoPoint}, scalar::Scalar, }; use rand::OsRng; use Error::{WiredRistrettoPointMalformed, WiredScalarMalformed}; /// An elliptic curve cryptography keypair. The private key (Xs) is used by the /// signer for creating the blind signature on the blinded hash(msg||R), and the /// public key (Qs) is usable by anyone for verifying the authenticity of the /// unblinded signature on the unblinded hash(msg||R). #[derive(Copy, Clone, Debug)] pub struct BlindKeypair { private: Scalar, public: RistrettoPoint, } impl BlindKeypair { /// Generates an ECC keypair for use with the blind signature protocol. /// The private key is a random scalar, and the public key is an elliptic /// curve point equal to this scalar multiplied by the Ristretto generator /// point. This is based on the wikipedia description of ECDSA key /// generation seeing as the whitepaper doesn't specify key generation. /// /// # Returns /// /// * Ok(BlindKeypair) on success. /// /// * Err(::Error) on error, which can only be the failure to initiate the /// internal RNG. /// /// # Mathematics /// /// * Xs = a randomly generated scalar /// * Qs = Xs * P /// * P = The ECC generator point pub fn generate() -> ::Result<Self> { let mut rng = OsRng::new()?; let private = Scalar::random(&mut rng); let public = private * RISTRETTO_BASEPOINT_POINT; Ok(BlindKeypair { private, public }) } /// Creates a new BlindKeypair object from the provided private and public /// key components (in wired form). /// /// # Returns /// /// * Ok(BlindKeypair) on success. /// /// * Err(::Error) on failure, which can indicate either that the private /// or public key inputs were malformed. pub fn from_wired(private: [u8; 32], public: [u8; 32]) -> ::Result<Self> { Ok(BlindKeypair { private: Scalar::from_canonical_bytes(private).ok_or(WiredScalarMalformed)?, public: CompressedRistretto(public) .decompress() .ok_or(WiredRistrettoPointMalformed)?, }) } /// Returns the private key in Scalar form pub fn private(&self) -> Scalar { self.private } /// Returns the public key in RistrettoPoint form pub fn public(&self) -> RistrettoPoint { self.public } /// Returns the public key in wired form pub fn public_wired(&self) -> [u8; 32] { self.public.compress().to_bytes() } /// Returns the private key in wired form pub fn private_wired(&self) -> [u8; 32] { self.private.to_bytes() } }