schnorr.rs 2.5 KB

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