Skip to content

Commit

Permalink
zcash_primitives: Introduce newtypes for ask and ak
Browse files Browse the repository at this point in the history
The Sapling key components specification places more constraints on the
values of `ask` and `ak` than general RedJubjub signing and verification
keys.
  • Loading branch information
str4d committed Dec 1, 2023
1 parent de1ed21 commit cb72231
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 63 deletions.
11 changes: 11 additions & 0 deletions zcash_primitives/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ and this library adheres to Rust's notion of
- `circuit::{SpendVerifyingKey, PreparedSpendVerifyingKey}`
- `circuit::{OutputVerifyingKey, PreparedOutputVerifyingKey}`
- `constants` module.
- `keys::SpendAuthorizingKey`
- `keys::SpendValidatingKey`
- `note_encryption::CompactOutputDescription` (moved from
`zcash_primitives::transaction::components::sapling`).
- `note_encryption::SaplingDomain::new`
Expand Down Expand Up @@ -145,6 +147,9 @@ and this library adheres to Rust's notion of
- `circuit::ValueCommitmentOpening::value` is now represented as a `NoteValue`
instead of as a bare `u64`.
- `keys::DecodingError` has a new variant `UnsupportedChildIndex`.
- `keys::ExpandedSpendingKey.ask` now has type `SpendAuthorizingKey`.
- `keys::ProofGenerationKey.ak` now has type `SpendValidatingKey`.
- `keys::ViewingKey.ak` now has type `SpendValidatingKey`.
- `note_encryption`:
- `SaplingDomain` no longer has a `P: consensus::Parameters` type parameter.
- The following methods now take a `Zip212Enforcement` argument instead of a
Expand Down Expand Up @@ -237,6 +242,12 @@ and this library adheres to Rust's notion of
- `ChildIndex::NonHardened`
- `sapling::ExtendedFullViewingKey::derive_child`

### Fixed
- `zcash_primitives::keys::ExpandedSpendingKey::from_spending_key` now panics if the
spending key expands to `ask = 0`. This has a negligible probability of occurring.
- `zcash_primitives::zip32::ExtendedSpendingKey::derive_child` now panics if the
child key has `ask = 0`. This has a negligible probability of occurring.

## [0.13.0] - 2023-09-25
### Added
- `zcash_primitives::consensus::BlockHeight::saturating_sub`
Expand Down
29 changes: 9 additions & 20 deletions zcash_primitives/src/sapling/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use core::fmt;
use std::{marker::PhantomData, sync::mpsc::Sender};

use group::{ff::Field, GroupEncoding};
use group::ff::Field;
use rand::{seq::SliceRandom, RngCore};
use rand_core::CryptoRng;
use redjubjub::{Binding, SpendAuth};
Expand All @@ -15,7 +15,7 @@ use crate::{
Authorization, Authorized, Bundle, GrothProofBytes, MapAuth, OutputDescription,
SpendDescription,
},
keys::OutgoingViewingKey,
keys::{OutgoingViewingKey, SpendAuthorizingKey, SpendValidatingKey},
note_encryption::{sapling_note_encryption, Zip212Enforcement},
prover::{OutputProver, SpendProver},
util::generate_random_rseed_internal,
Expand Down Expand Up @@ -114,8 +114,7 @@ impl SpendDescriptionInfo {
// Construct the value commitment.
let cv = ValueCommitment::derive(self.note.value(), self.rcv.clone());

let ak = redjubjub::VerificationKey::try_from(self.proof_generation_key.ak.to_bytes())
.expect("valid points are valid verification keys");
let ak = self.proof_generation_key.ak.clone();

// This is the result of the re-randomization, we compute it for the caller
let rk = ak.randomize(&self.alpha);
Expand Down Expand Up @@ -691,7 +690,7 @@ impl InProgressSignatures for Unsigned {
pub struct SigningParts {
/// The spend validating key for this spend description. Used to match spend
/// authorizing keys to spend descriptions they can create signatures for.
ak: redjubjub::VerificationKey<SpendAuth>,
ak: SpendValidatingKey,
/// The randomization needed to derive the actual signing key for this note.
alpha: jubjub::Scalar,
}
Expand Down Expand Up @@ -760,7 +759,7 @@ impl<V> Bundle<InProgress<Proven, Unsigned>, V> {
self,
mut rng: R,
sighash: [u8; 32],
signing_keys: &[redjubjub::SigningKey<SpendAuth>],
signing_keys: &[SpendAuthorizingKey],
) -> Result<Bundle<Authorized, V>, Error> {
signing_keys
.iter()
Expand All @@ -775,20 +774,15 @@ impl<P: InProgressProofs, V> Bundle<InProgress<P, PartiallyAuthorized>, V> {
/// Signs this bundle with the given [`redjubjub::SigningKey`].
///
/// This will apply signatures for all notes controlled by this spending key.
pub fn sign<R: RngCore + CryptoRng>(
self,
mut rng: R,
ask: &redjubjub::SigningKey<SpendAuth>,
) -> Self {
let expected_ak = redjubjub::VerificationKey::from(ask);
pub fn sign<R: RngCore + CryptoRng>(self, mut rng: R, ask: &SpendAuthorizingKey) -> Self {
let expected_ak = ask.into();
let sighash = self.authorization().sigs.sighash;
self.map_authorization((
|proof| proof,
|proof| proof,
|maybe| match maybe {
MaybeSigned::SigningMetadata(parts) if parts.ak == expected_ak => {
let rsk = ask.randomize(&parts.alpha);
MaybeSigned::Signature(rsk.sign(&mut rng, &sighash))
MaybeSigned::Signature(ask.randomize(&parts.alpha).sign(&mut rng, &sighash))
}
s => s,
},
Expand Down Expand Up @@ -920,12 +914,7 @@ pub mod testing {
bundle.create_proofs(&MockSpendProver, &MockOutputProver, &mut rng, None);

bundle
.apply_signatures(
&mut rng,
fake_sighash_bytes,
&[redjubjub::SigningKey::try_from(extsk.expsk.ask.to_bytes())
.expect("valid scalars are valid signing keys")],
)
.apply_signatures(&mut rng, fake_sighash_bytes, &[extsk.expsk.ask])

Check warning on line 917 in zcash_primitives/src/sapling/builder.rs

View check run for this annotation

Codecov / codecov/patch

zcash_primitives/src/sapling/builder.rs#L917

Added line #L917 was not covered by tests
.unwrap()
},
)
Expand Down
31 changes: 19 additions & 12 deletions zcash_primitives/src/sapling/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ impl Circuit<bls12_381::Scalar> for Spend {
// Prover witnesses ak (ensures that it's on the curve)
let ak = ecc::EdwardsPoint::witness(
cs.namespace(|| "ak"),
self.proof_generation_key.as_ref().map(|k| k.ak.into()),
self.proof_generation_key.as_ref().map(|k| (&k.ak).into()),
)?;

// There are no sensible attacks on small order points
Expand Down Expand Up @@ -634,9 +634,12 @@ pub struct PreparedOutputVerifyingKey(pub(crate) groth16::PreparedVerifyingKey<B

#[test]
fn test_input_circuit_with_bls12_381() {
use crate::sapling::{pedersen_hash, Diversifier, Note, ProofGenerationKey, Rseed};
use crate::sapling::{
keys::SpendValidatingKey, pedersen_hash, Diversifier, Note, ProofGenerationKey, Rseed,
};

use bellman::gadgets::test::*;
use group::{ff::Field, Group};
use group::ff::Field;
use rand_core::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

Expand All @@ -654,7 +657,7 @@ fn test_input_circuit_with_bls12_381() {
};

let proof_generation_key = ProofGenerationKey {
ak: jubjub::SubgroupPoint::random(&mut rng),
ak: SpendValidatingKey::fake_random(&mut rng),
nsk: jubjub::Fr::random(&mut rng),
};

Expand All @@ -681,7 +684,7 @@ fn test_input_circuit_with_bls12_381() {
let ar = jubjub::Fr::random(&mut rng);

{
let rk = jubjub::ExtendedPoint::from(viewing_key.rk(ar)).to_affine();
let rk = jubjub::AffinePoint::from_bytes(viewing_key.rk(ar).into()).unwrap();
let expected_value_commitment = value_commitment.commitment().to_affine();
let note = Note::from_parts(
payment_address,
Expand Down Expand Up @@ -780,9 +783,12 @@ fn test_input_circuit_with_bls12_381() {

#[test]
fn test_input_circuit_with_bls12_381_external_test_vectors() {
use crate::sapling::{pedersen_hash, Diversifier, Note, ProofGenerationKey, Rseed};
use crate::sapling::{
keys::SpendValidatingKey, pedersen_hash, Diversifier, Note, ProofGenerationKey, Rseed,
};

use bellman::gadgets::test::*;
use group::{ff::Field, Group};
use group::ff::Field;
use rand_core::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

Expand Down Expand Up @@ -826,7 +832,7 @@ fn test_input_circuit_with_bls12_381_external_test_vectors() {
};

let proof_generation_key = ProofGenerationKey {
ak: jubjub::SubgroupPoint::random(&mut rng),
ak: SpendValidatingKey::fake_random(&mut rng),
nsk: jubjub::Fr::random(&mut rng),
};

Expand All @@ -853,7 +859,7 @@ fn test_input_circuit_with_bls12_381_external_test_vectors() {
let ar = jubjub::Fr::random(&mut rng);

{
let rk = jubjub::ExtendedPoint::from(viewing_key.rk(ar)).to_affine();
let rk = jubjub::AffinePoint::from_bytes(viewing_key.rk(ar).into()).unwrap();
let expected_value_commitment = value_commitment.commitment().to_affine();
assert_eq!(
expected_value_commitment.get_u(),
Expand Down Expand Up @@ -960,9 +966,10 @@ fn test_input_circuit_with_bls12_381_external_test_vectors() {

#[test]
fn test_output_circuit_with_bls12_381() {
use crate::sapling::{Diversifier, ProofGenerationKey, Rseed};
use crate::sapling::{keys::SpendValidatingKey, Diversifier, ProofGenerationKey, Rseed};

use bellman::gadgets::test::*;
use group::{ff::Field, Group};
use group::ff::Field;
use rand_core::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

Expand All @@ -978,7 +985,7 @@ fn test_output_circuit_with_bls12_381() {
};

let nsk = jubjub::Fr::random(&mut rng);
let ak = jubjub::SubgroupPoint::random(&mut rng);
let ak = SpendValidatingKey::fake_random(&mut rng);

let proof_generation_key = ProofGenerationKey { ak, nsk };

Expand Down
Loading

0 comments on commit cb72231

Please sign in to comment.