mirror of https://github.com/zcash/orchard.git
Merge pull request #296 from zcash/commitivk-identity-error
spec.rs: Check that commit_ivk returns a nonzero base.
This commit is contained in:
commit
0ee6cf894f
21
src/keys.rs
21
src/keys.rs
|
@ -537,9 +537,30 @@ impl From<&FullViewingKey> for KeyAgreementPrivateKey {
|
|||
|
||||
impl KeyAgreementPrivateKey {
|
||||
/// Derives ivk from fvk. Internal use only, does not enforce all constraints.
|
||||
///
|
||||
/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
|
||||
///
|
||||
/// [orchardkeycomponents]: https://zips.z.cash/protocol/protocol.pdf#orchardkeycomponents
|
||||
fn derive_inner(fvk: &FullViewingKey) -> CtOption<NonZeroPallasBase> {
|
||||
let ak = extract_p(&pallas::Point::from_bytes(&(&fvk.ak.0).into()).unwrap());
|
||||
commit_ivk(&ak, &fvk.nk.0, &fvk.rivk.0)
|
||||
// sinsemilla::CommitDomain::short_commit returns a value in range
|
||||
// [0..q_P] ∪ {⊥}:
|
||||
// - sinsemilla::HashDomain::hash_to_point uses incomplete addition and
|
||||
// returns a point in P* ∪ {⊥}.
|
||||
// - sinsemilla::CommitDomain::commit applies a final complete addition step
|
||||
// and returns a point in P ∪ {⊥}.
|
||||
// - 0 is not a valid x-coordinate for any Pallas point.
|
||||
// - sinsemilla::CommitDomain::short_commit calls extract_p_bottom, which
|
||||
// replaces the identity (which has no affine coordinates) with 0.
|
||||
//
|
||||
// Commit^ivk.Output is specified as [1..q_P] ∪ {⊥}, so we explicitly check
|
||||
// for 0 and map it to None. Note that we are collapsing this case (which is
|
||||
// rejected by the circuit) with ⊥ (which the circuit explicitly allows for
|
||||
// efficiency); this is fine because we don't want users of the `orchard`
|
||||
// crate to encounter either case (and it matches the behaviour described in
|
||||
// Section 4.2.3 of the protocol spec when generating spending keys).
|
||||
.and_then(NonZeroPallasBase::from_base)
|
||||
}
|
||||
|
||||
/// Returns the payment address for this key corresponding to the given diversifier.
|
||||
|
|
16
src/spec.rs
16
src/spec.rs
|
@ -166,31 +166,23 @@ pub(crate) fn mod_r_p(x: pallas::Base) -> pallas::Scalar {
|
|||
pallas::Scalar::from_repr(x.to_repr()).unwrap()
|
||||
}
|
||||
|
||||
/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
|
||||
/// Defined in [Zcash Protocol Spec § 5.4.8.4: Sinsemilla commitments][concretesinsemillacommit].
|
||||
///
|
||||
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents
|
||||
/// [concretesinsemillacommit]: https://zips.z.cash/protocol/protocol.pdf#concretesinsemillacommit
|
||||
pub(crate) fn commit_ivk(
|
||||
ak: &pallas::Base,
|
||||
nk: &pallas::Base,
|
||||
rivk: &pallas::Scalar,
|
||||
) -> CtOption<NonZeroPallasBase> {
|
||||
) -> CtOption<pallas::Base> {
|
||||
// We rely on the API contract that to_le_bits() returns at least PrimeField::NUM_BITS
|
||||
// bits, which is equal to L_ORCHARD_BASE.
|
||||
let domain = sinsemilla::CommitDomain::new(COMMIT_IVK_PERSONALIZATION);
|
||||
domain
|
||||
.short_commit(
|
||||
domain.short_commit(
|
||||
iter::empty()
|
||||
.chain(ak.to_le_bits().iter().by_val().take(L_ORCHARD_BASE))
|
||||
.chain(nk.to_le_bits().iter().by_val().take(L_ORCHARD_BASE)),
|
||||
rivk,
|
||||
)
|
||||
// Commit^ivk.Output is specified as [1..q_P] ∪ {⊥}. We get this from
|
||||
// sinsemilla::CommitDomain::short_commit by construction:
|
||||
// - 0 is not a valid x-coordinate for any Pallas point.
|
||||
// - sinsemilla::CommitDomain::short_commit calls extract_p_bottom, which replaces
|
||||
// the identity (which has no affine coordinates) with 0. but Sinsemilla is
|
||||
// defined using incomplete addition, and thus will never produce the identity.
|
||||
.map(NonZeroPallasBase::guaranteed)
|
||||
}
|
||||
|
||||
/// Defined in [Zcash Protocol Spec § 5.4.1.6: DiversifyHash^Sapling and DiversifyHash^Orchard Hash Functions][concretediversifyhash].
|
||||
|
|
Loading…
Reference in New Issue