Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,108 @@ impl SpendValidatingKey {
}
}

/// An issuer authorizing key, used to create issuer authorization signatures.
/// This type enforces that the corresponding public point (ik^ℙ) has ỹ = 0.
///
/// $\mathsf{isk}$ as defined in
/// [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
///
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents
#[derive(Clone, Debug)]
pub struct IssuerAuthorizingKey(redpallas::SigningKey<SpendAuth>);

impl IssuerAuthorizingKey {
/// Derives ask from sk. Internal use only, does not enforce all constraints.
fn derive_inner(sk: &SpendingKey) -> pallas::Scalar {
to_scalar(PrfExpand::ZsaIsk.expand(&sk.0))
}

/// Randomizes this spend authorizing key with the given `randomizer`.
/// TODO: not sure we need a randomizer (remove?)
Comment thread
PaulLaux marked this conversation as resolved.
Outdated
/// The resulting key can be used to actually sign a spend.
pub fn randomize(&self, randomizer: &pallas::Scalar) -> redpallas::SigningKey<SpendAuth> {
self.0.randomize(randomizer)
}
}

impl From<&SpendingKey> for IssuerAuthorizingKey {
fn from(sk: &SpendingKey) -> Self {
let isk = Self::derive_inner(sk);
// IssuerSigningKey cannot be constructed such that this assertion would fail.
assert!(!bool::from(isk.is_zero()));
// TODO: Add TryFrom<S::Scalar> for IssuerAuthorizingKey.
Comment thread
PaulLaux marked this conversation as resolved.
Outdated
let ret = IssuerAuthorizingKey(isk.to_repr().try_into().unwrap());
// If the last bit of repr_P(ik) is 1, negate isk.
if (<[u8; 32]>::from(IssuerValidatingKey::from(&ret).0)[31] >> 7) == 1 {
IssuerAuthorizingKey((-isk).to_repr().try_into().unwrap())
} else {
ret
}
}
}

/// A key used to validate issuer authorization signatures.
///
/// Defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
/// Note that this is $\mathsf{ik}^\mathbb{P}$, which by construction is equivalent to
/// $\mathsf{ik}$ but stored here as a RedPallas verification key.
///
/// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents
#[derive(Debug, Clone, PartialOrd, Ord)]
pub struct IssuerValidatingKey(redpallas::VerificationKey<SpendAuth>);
// Discuss <SpendAuth>
Comment thread
PaulLaux marked this conversation as resolved.
Outdated
impl From<&IssuerAuthorizingKey> for IssuerValidatingKey {
fn from(isk: &IssuerAuthorizingKey) -> Self {
IssuerValidatingKey((&isk.0).into())
}
}

impl From<&IssuerValidatingKey> for pallas::Point {
fn from(issuer_validating_key: &IssuerValidatingKey) -> pallas::Point {
pallas::Point::from_bytes(&(&issuer_validating_key.0).into()).unwrap()
}
}

impl PartialEq for IssuerValidatingKey {
fn eq(&self, other: &Self) -> bool {
<[u8; 32]>::from(&self.0).eq(&<[u8; 32]>::from(&other.0))
}
}

impl Eq for IssuerValidatingKey {}

impl IssuerValidatingKey {
/// Randomizes this spend validating key with the given `randomizer`.
pub fn randomize(&self, randomizer: &pallas::Scalar) -> redpallas::VerificationKey<SpendAuth> {
self.0.randomize(randomizer)
}

/// Converts this spend validating key to its serialized form,
/// I2LEOSP_256(ak).
Comment thread
PaulLaux marked this conversation as resolved.
Outdated
pub(crate) fn to_bytes(&self) -> [u8; 32] {
// This is correct because the wrapped point must have ỹ = 0, and
// so the point repr is the same as I2LEOSP of its x-coordinate.
<[u8; 32]>::from(&self.0)
}

pub(crate) fn from_bytes(bytes: &[u8]) -> Option<Self> {
<[u8; 32]>::try_from(bytes)
.ok()
.and_then(|b| {
// Structural validity checks for ik_P:
// - The point must not be the identity
// (which for Pallas is canonically encoded as all-zeroes).
// - The sign of the y-coordinate must be positive.
if b != [0; 32] && b[31] & 0x80 == 0 {
<redpallas::VerificationKey<SpendAuth>>::try_from(b).ok()
} else {
None
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is critical, let's extract this into a function to prevent duplication with ak,
something like

fn check_structural_validity(verification_key_bytes: &[u8; 32]) -> Option<&[u8; 32]> {

}

})
.map(IssuerValidatingKey)
}
}

/// A key used to derive [`Nullifier`]s from [`Note`]s.
///
/// $\mathsf{nk}$ as defined in [Zcash Protocol Spec § 4.2.3: Orchard Key Components][orchardkeycomponents].
Expand Down Expand Up @@ -1021,9 +1123,15 @@ mod tests {
let ask: SpendAuthorizingKey = (&sk).into();
assert_eq!(<[u8; 32]>::from(&ask.0), tv.ask);

let isk: IssuerAuthorizingKey = (&sk).into();
assert_eq!(<[u8; 32]>::from(&isk.0), tv.isk);

let ak: SpendValidatingKey = (&ask).into();
assert_eq!(<[u8; 32]>::from(ak.0), tv.ak);

let ik: IssuerValidatingKey = (&isk).into();
assert_eq!(<[u8; 32]>::from(ik.0), tv.ik);

let nk: NullifierDerivingKey = (&sk).into();
assert_eq!(nk.0.to_repr(), tv.nk);

Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#![deny(missing_docs)]
#![deny(unsafe_code)]

extern crate pasta_curves;

Comment thread
PaulLaux marked this conversation as resolved.
Outdated
mod action;
mod address;
pub mod builder;
Expand Down
2 changes: 2 additions & 0 deletions src/spec/prf_expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub(crate) enum PrfExpand {
OrchardNk,
OrchardRivk,
Psi,
ZsaIsk,
OrchardZip32Child,
OrchardDkOvk,
OrchardRivkInternal,
Expand All @@ -24,6 +25,7 @@ impl PrfExpand {
Self::OrchardNk => 0x07,
Self::OrchardRivk => 0x08,
Self::Psi => 0x09,
Self::ZsaIsk => 0x0a,
Self::OrchardZip32Child => 0x81,
Self::OrchardDkOvk => 0x82,
Self::OrchardRivkInternal => 0x83,
Expand Down
102 changes: 102 additions & 0 deletions src/test_vectors/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pub(crate) struct TestVector {
pub(crate) sk: [u8; 32],
pub(crate) ask: [u8; 32],
pub(crate) ak: [u8; 32],
pub(crate) isk: [u8; 32],
pub(crate) ik: [u8; 32],
pub(crate) nk: [u8; 32],
pub(crate) rivk: [u8; 32],
pub(crate) ivk: [u8; 32],
Expand Down Expand Up @@ -41,6 +43,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0x12, 0x8b, 0x9a, 0x14, 0x0d, 0x5e, 0x07, 0xc1, 0x51, 0x72, 0x1d, 0xc1, 0x6d, 0x25,
0xd4, 0xe2, 0x0f, 0x15,
],
isk: [
0x95, 0x4a, 0x86, 0xc7, 0xa7, 0x15, 0x53, 0xfa, 0x6c, 0x8b, 0x67, 0x58, 0x54, 0x26,
0x8e, 0xa5, 0x4c, 0x51, 0xfb, 0x17, 0xd8, 0x3d, 0x80, 0xee, 0x71, 0xd4, 0xae, 0x42,
0xa1, 0xf8, 0xc8, 0x16,
],
ik: [
0x2e, 0x4f, 0xd4, 0xa6, 0xec, 0x39, 0x94, 0x87, 0xd3, 0x78, 0xb4, 0xc7, 0x25, 0xfb,
0x9b, 0xaf, 0xbc, 0x01, 0xa5, 0xe2, 0xb7, 0xf3, 0x68, 0x2e, 0xf4, 0x53, 0x95, 0x91,
0xbc, 0xf0, 0x59, 0x02,
],
nk: [
0x9f, 0x2f, 0x82, 0x67, 0x38, 0x94, 0x5a, 0xd0, 0x1f, 0x47, 0xf7, 0x0d, 0xb0, 0xc3,
0x67, 0xc2, 0x46, 0xc2, 0x0c, 0x61, 0xff, 0x55, 0x83, 0x94, 0x8c, 0x39, 0xde, 0xa9,
Expand Down Expand Up @@ -132,6 +144,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0x2a, 0xd6, 0x43, 0x23, 0x62, 0x9c, 0xfe, 0xd1, 0xe3, 0xaa, 0x24, 0xef, 0x05, 0x2f,
0x56, 0xe4, 0x00, 0x2a,
],
isk: [
0xee, 0xf5, 0xe9, 0x1b, 0x36, 0xb8, 0x06, 0x86, 0x72, 0x3d, 0x14, 0xdc, 0xc7, 0x04,
0xad, 0x59, 0x67, 0x08, 0x0b, 0x7d, 0x6e, 0x49, 0xaf, 0x97, 0x03, 0x0e, 0x4f, 0xa0,
0xbf, 0x5a, 0xd9, 0x0b,
],
ik: [
0x2e, 0xde, 0xfb, 0x15, 0x8e, 0xa4, 0x48, 0x82, 0x57, 0x2b, 0xcd, 0xb2, 0x35, 0xca,
0x36, 0xab, 0x39, 0xc7, 0x47, 0xbb, 0x71, 0xfe, 0x0f, 0x10, 0xfa, 0xa3, 0x9b, 0xfd,
0x62, 0x0a, 0xcc, 0x04,
],
nk: [
0xa8, 0xb7, 0x3d, 0x97, 0x9b, 0x6e, 0xaa, 0xda, 0x89, 0x24, 0xbc, 0xbd, 0xc6, 0x3a,
0x9e, 0xf4, 0xe8, 0x73, 0x46, 0xf2, 0x30, 0xab, 0xa6, 0xbb, 0xe1, 0xe2, 0xb4, 0x3c,
Expand Down Expand Up @@ -223,6 +245,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0xed, 0xb4, 0x26, 0x65, 0x7b, 0x2d, 0x07, 0x40, 0x66, 0x64, 0xd8, 0x95, 0x31, 0x2e,
0xa1, 0xc3, 0xb3, 0x34,
],
isk: [
0x5b, 0x1f, 0xc4, 0x57, 0xae, 0x71, 0x38, 0x3c, 0x53, 0xf4, 0x69, 0x41, 0xb7, 0xcb,
0x4c, 0xec, 0x3d, 0xea, 0xc0, 0xc6, 0x03, 0xe2, 0xcd, 0xd0, 0xd1, 0x8d, 0x94, 0x01,
0x9e, 0x43, 0xe2, 0x07,
],
ik: [
0x4f, 0x43, 0xeb, 0x7d, 0x9e, 0x03, 0x6f, 0xa6, 0x15, 0xfd, 0x04, 0xa5, 0xef, 0x6a,
0xeb, 0x21, 0x6e, 0x06, 0x9b, 0xe9, 0x2d, 0x30, 0xe8, 0xf7, 0x16, 0x3e, 0xe3, 0x15,
0x11, 0x6f, 0x18, 0x32,
],
nk: [
0x04, 0x51, 0x4e, 0xa0, 0x48, 0xb9, 0x43, 0x63, 0xde, 0xa7, 0xcb, 0x3b, 0xe8, 0xd6,
0x25, 0x82, 0xac, 0x52, 0x92, 0x2e, 0x08, 0x65, 0xf6, 0x62, 0x74, 0x3b, 0x05, 0xea,
Expand Down Expand Up @@ -314,6 +346,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0xe7, 0x2c, 0x3b, 0x64, 0x00, 0x06, 0xff, 0x08, 0x50, 0x52, 0x80, 0xe4, 0xf0, 0x0f,
0xad, 0xf7, 0x63, 0x28,
],
isk: [
0x71, 0xd0, 0x64, 0xaa, 0xa0, 0x82, 0x63, 0xb8, 0xe4, 0xc3, 0xed, 0x70, 0x3c, 0x6f,
0x54, 0x25, 0x4a, 0x88, 0x8c, 0x36, 0xec, 0x69, 0x86, 0x62, 0xf7, 0x1f, 0xbb, 0xf4,
0x26, 0xd9, 0x09, 0x28,
],
ik: [
0x12, 0xb3, 0xab, 0xff, 0x96, 0x75, 0x20, 0x9e, 0x94, 0x54, 0x07, 0x0c, 0x14, 0xac,
0x15, 0x54, 0x65, 0xae, 0x83, 0xbe, 0x2c, 0x39, 0x46, 0x63, 0x5e, 0x38, 0x77, 0xba,
0x67, 0xdf, 0x49, 0x12,
],
nk: [
0xcf, 0x36, 0xad, 0x6a, 0x06, 0x6c, 0xd2, 0x13, 0xe1, 0xd7, 0x67, 0xab, 0x07, 0x1d,
0xc1, 0x16, 0x78, 0x85, 0xc4, 0x16, 0x8b, 0xc2, 0xe2, 0x17, 0x54, 0x48, 0x56, 0x3a,
Expand Down Expand Up @@ -405,6 +447,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0xf5, 0x6d, 0x83, 0x20, 0x09, 0xf7, 0x24, 0x2e, 0x1f, 0x7c, 0x77, 0x0a, 0x12, 0x24,
0x1d, 0xfa, 0x28, 0x07,
],
isk: [
0x44, 0x36, 0x1a, 0x7b, 0xa6, 0xa1, 0xaa, 0x17, 0x8e, 0x72, 0xaf, 0x47, 0xbd, 0xc1,
0x60, 0x40, 0xce, 0x1c, 0x54, 0xdd, 0x4b, 0x56, 0x33, 0x21, 0x55, 0xba, 0x9d, 0x04,
0x09, 0x71, 0xd0, 0x07,
],
ik: [
0x1f, 0x17, 0x2d, 0x79, 0xae, 0xdc, 0xc2, 0x06, 0x8c, 0x3a, 0x09, 0x08, 0x93, 0xe1,
0xa1, 0x75, 0xd9, 0xb5, 0x78, 0xf8, 0x91, 0xaf, 0x9a, 0xb6, 0x8d, 0x4f, 0xe1, 0xe9,
0x05, 0xa3, 0xb2, 0x11,
],
nk: [
0x51, 0xba, 0xf3, 0x33, 0xcf, 0xf1, 0xf2, 0xd0, 0xc7, 0xe3, 0xcf, 0xf4, 0xd3, 0x01,
0x29, 0x9d, 0xc1, 0xef, 0xe9, 0x83, 0x00, 0x31, 0x4a, 0x54, 0x19, 0x38, 0x02, 0x9b,
Expand Down Expand Up @@ -496,6 +548,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0xdf, 0x28, 0xbb, 0x0f, 0x10, 0x21, 0xea, 0x84, 0x3f, 0x86, 0x7f, 0x8a, 0x17, 0x0f,
0x5c, 0x33, 0x90, 0x1f,
],
isk: [
0xdc, 0x93, 0x72, 0x9f, 0x3f, 0x28, 0x30, 0xed, 0x79, 0x1c, 0x21, 0xbe, 0xbe, 0x45,
0x0f, 0xcf, 0x1f, 0x8f, 0xef, 0x49, 0x81, 0x39, 0xc7, 0x99, 0xd1, 0x63, 0x66, 0x5a,
0x8c, 0x51, 0xe5, 0x2d,
],
ik: [
0x1d, 0xb6, 0x1c, 0x29, 0x3e, 0x3a, 0x93, 0x34, 0x5d, 0x06, 0xb9, 0x0b, 0xd7, 0x1f,
0xd3, 0x21, 0x5c, 0x2c, 0x1c, 0x29, 0x53, 0x5a, 0x10, 0xde, 0x9d, 0x31, 0x40, 0xb7,
0x4d, 0xb6, 0x1d, 0x07,
],
nk: [
0x9e, 0x99, 0x7d, 0x9d, 0x26, 0x97, 0x87, 0x26, 0x8e, 0x09, 0x2a, 0x7c, 0x85, 0x41,
0x7d, 0xa5, 0x30, 0xea, 0x42, 0xfa, 0xc6, 0x68, 0xa7, 0x49, 0xaf, 0x55, 0xdf, 0xb7,
Expand Down Expand Up @@ -587,6 +649,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0x65, 0x43, 0x46, 0x2a, 0x13, 0x7f, 0xfe, 0xa3, 0x7b, 0xaf, 0x41, 0xef, 0x28, 0x6b,
0xb7, 0x32, 0xbe, 0x2c,
],
isk: [
0xf2, 0x34, 0x52, 0x32, 0xc9, 0x19, 0xc1, 0x29, 0xe0, 0x4b, 0x0c, 0x46, 0xac, 0x2c,
0xa8, 0x50, 0x65, 0xd9, 0x54, 0x85, 0xb9, 0x02, 0xab, 0x0f, 0x98, 0xf9, 0x3a, 0xee,
0x59, 0x4b, 0x5f, 0x02,
],
ik: [
0x2c, 0x83, 0xd9, 0x20, 0xe9, 0xf6, 0x6d, 0xa5, 0x04, 0x86, 0x37, 0xad, 0x9a, 0xa2,
0xcc, 0xe6, 0xe1, 0x6e, 0xf4, 0x8f, 0x86, 0x50, 0xea, 0x00, 0xd8, 0xc2, 0xd7, 0x68,
0x61, 0x8a, 0xe3, 0x36,
],
nk: [
0xfd, 0x31, 0x64, 0xc6, 0x32, 0xbe, 0xc9, 0x4c, 0xe9, 0xfb, 0x2f, 0x30, 0x22, 0x63,
0xb8, 0x84, 0xab, 0xb9, 0xc1, 0x0e, 0x55, 0xe4, 0x48, 0x64, 0x7f, 0x67, 0x98, 0x49,
Expand Down Expand Up @@ -678,6 +750,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0xb3, 0x65, 0x1f, 0xfa, 0x1c, 0x69, 0x69, 0x15, 0xac, 0x00, 0xa2, 0x5e, 0xa3, 0xac,
0x7d, 0xff, 0x99, 0x01,
],
isk: [
0x3d, 0xa9, 0x08, 0x88, 0xba, 0x18, 0x24, 0xc8, 0x16, 0x29, 0x2d, 0x7f, 0x17, 0x33,
0xac, 0x4c, 0xbe, 0x72, 0x2c, 0x6a, 0x12, 0x1c, 0xc7, 0x80, 0x17, 0x06, 0x26, 0xb7,
0x0a, 0x26, 0x95, 0x28,
],
ik: [
0x16, 0xa8, 0xff, 0x29, 0xb5, 0x17, 0xb5, 0xa8, 0xf7, 0xd0, 0x9b, 0x4e, 0x5e, 0x71,
0x3a, 0x9a, 0x78, 0x4c, 0x74, 0x04, 0xd6, 0x1e, 0x3a, 0xf5, 0x30, 0x19, 0xc3, 0x47,
0x0e, 0x90, 0x95, 0x22,
],
nk: [
0x02, 0xab, 0x99, 0x5c, 0xe9, 0x8f, 0x63, 0x02, 0x5f, 0xb6, 0x24, 0x28, 0xa0, 0xfb,
0xf5, 0x2f, 0x25, 0x22, 0xe6, 0xa2, 0x72, 0x61, 0x07, 0x8a, 0x9f, 0x4d, 0x6a, 0x36,
Expand Down Expand Up @@ -769,6 +851,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0x3b, 0x02, 0xd2, 0x5c, 0xc1, 0x0c, 0x90, 0x71, 0xfc, 0x02, 0x19, 0xe9, 0x7f, 0x93,
0x92, 0xd0, 0x67, 0x0c,
],
isk: [
0x01, 0x65, 0x33, 0x68, 0x4f, 0xb9, 0x81, 0x15, 0xa4, 0x05, 0xc9, 0xc7, 0xad, 0x47,
0x72, 0x76, 0xab, 0x7c, 0x72, 0xfd, 0x67, 0x1a, 0x27, 0xe3, 0x6c, 0x0a, 0x7a, 0xbe,
0x0a, 0x76, 0x90, 0x09,
],
ik: [
0xff, 0xd7, 0x5f, 0x6f, 0x9e, 0xf4, 0x27, 0xf3, 0x26, 0xcd, 0xbf, 0x3a, 0x98, 0xbc,
0xb5, 0x93, 0x63, 0x5a, 0x2c, 0x1a, 0xd7, 0x2b, 0x39, 0x99, 0x12, 0x61, 0xe2, 0x75,
0xa9, 0xec, 0x6f, 0x10,
],
nk: [
0x25, 0x91, 0xed, 0xf7, 0xef, 0x4c, 0xf2, 0x18, 0x4c, 0x34, 0xbe, 0x93, 0xfc, 0xf6,
0x12, 0x91, 0x50, 0x42, 0xf1, 0x5a, 0xb5, 0x08, 0x4b, 0x14, 0xe1, 0x66, 0x79, 0x5b,
Expand Down Expand Up @@ -860,6 +952,16 @@ pub(crate) fn test_vectors() -> Vec<TestVector> {
0x8d, 0x4b, 0x02, 0x5f, 0x8c, 0xc1, 0x60, 0xe1, 0xf4, 0xe9, 0x5f, 0x0a, 0x85, 0x3e,
0xbc, 0x41, 0x6a, 0x2b,
],
isk: [
0x76, 0x08, 0x32, 0x9d, 0xfa, 0x77, 0xc4, 0x2c, 0x4f, 0xc7, 0x6a, 0xc2, 0x95, 0x94,
0xa2, 0x72, 0x83, 0x93, 0x4f, 0x5a, 0x93, 0x40, 0x71, 0xb9, 0xf8, 0xcd, 0x34, 0x4e,
0x1f, 0x98, 0x45, 0x0e,
],
ik: [
0x72, 0xa0, 0xac, 0x97, 0x8a, 0x2d, 0xa1, 0x61, 0xf4, 0x1f, 0x5b, 0x7a, 0x40, 0xbd,
0x83, 0xc0, 0x58, 0x41, 0xf8, 0x1b, 0xc5, 0x11, 0x40, 0x67, 0xb8, 0x85, 0x98, 0x7f,
0x48, 0xca, 0x52, 0x2d,
],
nk: [
0x3e, 0x88, 0xf2, 0x07, 0x1f, 0xd9, 0xa2, 0xbb, 0x26, 0xcd, 0xa2, 0xea, 0x85, 0x6a,
0xa0, 0xfb, 0x3a, 0x80, 0xa8, 0x7d, 0x2f, 0xb6, 0x13, 0x6f, 0xab, 0x85, 0xe3, 0x6c,
Expand Down