ironfish_reddsa/
lib.rs

1// -*- mode: rust; -*-
2//
3// This file is part of reddsa.
4// Copyright (c) 2019-2021 Zcash Foundation
5// See LICENSE for licensing information.
6//
7// Authors:
8// - Deirdre Connolly <deirdre@zfnd.org>
9// - Henry de Valence <hdevalence@hdevalence.ca>
10
11#![no_std]
12#![deny(missing_docs)]
13#![doc = include_str!("../README.md")]
14
15//! Docs require the `nightly` feature until RFC 1990 lands.
16
17#[cfg(feature = "alloc")]
18#[macro_use]
19extern crate alloc;
20#[cfg(feature = "std")]
21extern crate std;
22
23#[cfg(feature = "alloc")]
24pub mod batch;
25mod constants;
26mod error;
27#[cfg(feature = "frost")]
28pub mod frost;
29mod hash;
30pub mod orchard;
31pub mod sapling;
32#[cfg(feature = "alloc")]
33mod scalar_mul;
34pub(crate) mod signature;
35mod signing_key;
36mod verification_key;
37
38/// An element of the protocol's scalar field used for randomization of public and secret keys.
39pub type Randomizer<S> = <S as private::Sealed<S>>::Scalar;
40
41use hash::HStar;
42
43pub use error::Error;
44pub use signature::Signature;
45pub use signing_key::SigningKey;
46pub use verification_key::{VerificationKey, VerificationKeyBytes};
47
48/// Abstracts over different RedDSA parameter choices, [`Binding`]
49/// and [`SpendAuth`].
50///
51/// As described [at the end of ยง5.4.6][concretereddsa] of the Zcash
52/// protocol specification, the generator used in RedDSA is left as
53/// an unspecified parameter, chosen differently for each of
54/// `BindingSig` and `SpendAuthSig`.
55///
56/// To handle this, we encode the parameter choice as a genuine type
57/// parameter.
58///
59/// [concretereddsa]: https://zips.z.cash/protocol/protocol.pdf#concretereddsa
60pub trait SigType: private::Sealed<Self> {}
61
62/// A trait corresponding to `BindingSig` in Zcash protocols.
63pub trait Binding: SigType {}
64
65/// A trait corresponding to `SpendAuthSig` in Zcash protocols.
66pub trait SpendAuth: SigType {}
67
68pub(crate) mod private {
69    use super::*;
70
71    pub trait SealedScalar {
72        fn from_bytes_wide(bytes: &[u8; 64]) -> Self;
73        fn from_raw(val: [u64; 4]) -> Self;
74    }
75
76    impl SealedScalar for jubjub::Scalar {
77        fn from_bytes_wide(bytes: &[u8; 64]) -> Self {
78            jubjub::Scalar::from_bytes_wide(bytes)
79        }
80        fn from_raw(val: [u64; 4]) -> Self {
81            jubjub::Scalar::from_raw(val)
82        }
83    }
84
85    pub trait Sealed<T: SigType>:
86        Copy + Clone + Default + Eq + PartialEq + core::fmt::Debug
87    {
88        const H_STAR_PERSONALIZATION: &'static [u8; 16];
89        type Scalar: group::ff::PrimeField + SealedScalar;
90
91        // `Point: VartimeMultiscalarMul` is conditioned by `alloc` feature flag
92        // This is fine because `Sealed` is an internal trait.
93        #[cfg(feature = "alloc")]
94        type Point: group::cofactor::CofactorCurve<Scalar = Self::Scalar>
95            + scalar_mul::VartimeMultiscalarMul<Scalar = Self::Scalar, Point = Self::Point>;
96        #[cfg(not(feature = "alloc"))]
97        type Point: group::cofactor::CofactorCurve<Scalar = Self::Scalar>;
98
99        fn basepoint() -> T::Point;
100    }
101    impl Sealed<sapling::Binding> for sapling::Binding {
102        const H_STAR_PERSONALIZATION: &'static [u8; 16] = b"Zcash_RedJubjubH";
103        type Point = jubjub::ExtendedPoint;
104        type Scalar = jubjub::Scalar;
105
106        fn basepoint() -> jubjub::ExtendedPoint {
107            jubjub::AffinePoint::from_bytes(constants::BINDINGSIG_BASEPOINT_BYTES)
108                .unwrap()
109                .into()
110        }
111    }
112    impl Sealed<sapling::SpendAuth> for sapling::SpendAuth {
113        const H_STAR_PERSONALIZATION: &'static [u8; 16] = b"Zcash_RedJubjubH";
114        type Point = jubjub::ExtendedPoint;
115        type Scalar = jubjub::Scalar;
116
117        fn basepoint() -> jubjub::ExtendedPoint {
118            jubjub::AffinePoint::from_bytes(constants::SPENDAUTHSIG_BASEPOINT_BYTES)
119                .unwrap()
120                .into()
121        }
122    }
123}
124
125/// Return the given byte array as a hex-encoded string.
126#[cfg(feature = "alloc")]
127pub(crate) fn hex_if_possible(bytes: &[u8]) -> alloc::string::String {
128    hex::encode(bytes)
129}
130
131/// Return the given byte array.
132#[cfg(not(feature = "alloc"))]
133pub(crate) fn hex_if_possible(bytes: &[u8]) -> &[u8] {
134    bytes
135}