schnorr.rs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. use std::io;
  2. use halo2_gadgets::ecc::FixedPoints;
  3. use pasta_curves::{arithmetic::Field, group::GroupEncoding};
  4. use rand::rngs::OsRng;
  5. use super::{
  6. constants::{OrchardFixedBases, DRK_SCHNORR_DOMAIN},
  7. types::*,
  8. util::{hash_to_scalar, mod_r_p},
  9. };
  10. use crate::error::Result;
  11. use crate::serial::{Decodable, Encodable};
  12. pub struct SecretKey(pub DrkSecretKey);
  13. impl SecretKey {
  14. pub fn random() -> Self {
  15. Self(DrkSecretKey::random(&mut OsRng))
  16. }
  17. pub fn sign(&self, message: &[u8]) -> Signature {
  18. let mask = DrkValueBlind::random(&mut OsRng);
  19. let commit = OrchardFixedBases::SpendAuthG.generator() * mask;
  20. let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &commit.to_bytes(), message);
  21. let response = mask + challenge * mod_r_p(self.0);
  22. Signature { commit, response }
  23. }
  24. pub fn public_key(&self) -> PublicKey {
  25. PublicKey(derive_publickey(self.0))
  26. }
  27. }
  28. pub struct PublicKey(pub DrkPublicKey);
  29. pub struct Signature {
  30. commit: DrkValueCommit,
  31. response: DrkValueBlind,
  32. }
  33. impl Encodable for Signature {
  34. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  35. let mut len = 0;
  36. len += self.commit.encode(&mut s)?;
  37. len += self.response.encode(s)?;
  38. Ok(len)
  39. }
  40. }
  41. impl Decodable for Signature {
  42. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  43. Ok(Self {
  44. commit: Decodable::decode(&mut d)?,
  45. response: Decodable::decode(d)?,
  46. })
  47. }
  48. }
  49. impl PublicKey {
  50. pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
  51. let challenge = hash_to_scalar(DRK_SCHNORR_DOMAIN, &signature.commit.to_bytes(), message);
  52. OrchardFixedBases::SpendAuthG.generator() * signature.response - self.0 * challenge
  53. == signature.commit
  54. }
  55. }
  56. #[test]
  57. fn test_schnorr() {
  58. let secret = SecretKey::random();
  59. let message = b"Foo bar";
  60. let signature = secret.sign(&message[..]);
  61. let public = secret.public_key();
  62. assert!(public.verify(&message[..], &signature));
  63. }