schnorr.rs 2.5 KB

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