Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Commit

Permalink
[clap-v3-utils, sdk, zk-token-sdk] Split EncodableKey into `Encodab…
Browse files Browse the repository at this point in the history
…leKey` + `SeedDerivable` (#31668)

* add `SeedDerivable` trait

* implement `SeedDerivable` for `Keypair`

* implement `SeedDerivable` for `ElGamalKeypair`

* update clap-v3-utils to use `EncodableKey + SeedDerivable`

* implement `SeedDerivable` trait for `AeKey`

* implement `EncodableKey` and `SeedDerivable` for `ElGamalSecretKey`

* implement `SeedDerivable` trait for `ElGamalPubkey`
  • Loading branch information
samkim-crypto authored May 17, 2023
1 parent 2cdb43f commit 6de581a
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 7 deletions.
7 changes: 4 additions & 3 deletions clap-v3-utils/src/keypair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ use {
pubkey::Pubkey,
signature::{
generate_seed_from_seed_phrase_and_passphrase, read_keypair, read_keypair_file,
EncodableKey, EncodableKeypair, Keypair, NullSigner, Presigner, Signature, Signer,
EncodableKey, EncodableKeypair, Keypair, NullSigner, Presigner, SeedDerivable,
Signature, Signer,
},
},
solana_zk_token_sdk::encryption::{auth_encryption::AeKey, elgamal::ElGamalKeypair},
Expand Down Expand Up @@ -1106,7 +1107,7 @@ pub fn ae_key_from_path(
encodable_key_from_path(matches, path, key_name)
}

fn encodable_key_from_path<K: EncodableKey>(
fn encodable_key_from_path<K: EncodableKey + SeedDerivable>(
matches: &ArgMatches,
path: &str,
keypair_name: &str,
Expand Down Expand Up @@ -1202,7 +1203,7 @@ pub fn ae_key_from_seed_phrase(
encodable_key_from_seed_phrase(keypair_name, skip_validation, derivation_path, legacy)
}

fn encodable_key_from_seed_phrase<K: EncodableKey>(
fn encodable_key_from_seed_phrase<K: EncodableKey + SeedDerivable>(
key_name: &str,
skip_validation: bool,
derivation_path: Option<DerivationPath>,
Expand Down
4 changes: 3 additions & 1 deletion sdk/src/signer/keypair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use {
derivation_path::DerivationPath,
pubkey::Pubkey,
signature::Signature,
signer::{EncodableKey, EncodableKeypair, Signer, SignerError},
signer::{EncodableKey, EncodableKeypair, SeedDerivable, Signer, SignerError},
},
ed25519_dalek::Signer as DalekSigner,
ed25519_dalek_bip32::Error as Bip32Error,
Expand Down Expand Up @@ -120,7 +120,9 @@ impl EncodableKey for Keypair {
fn write<W: Write>(&self, writer: &mut W) -> Result<String, Box<dyn error::Error>> {
write_keypair(self, writer)
}
}

impl SeedDerivable for Keypair {
fn from_seed(seed: &[u8]) -> Result<Self, Box<dyn error::Error>> {
keypair_from_seed(seed)
}
Expand Down
5 changes: 5 additions & 0 deletions sdk/src/signer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ pub trait EncodableKey: Sized {

self.write(&mut f)
}
}

/// The `SeedDerivable` trait defines the interface by which cryptographic keys/keypairs are
/// derived from byte seeds, derivation paths, and passphrases.
pub trait SeedDerivable: Sized {
fn from_seed(seed: &[u8]) -> Result<Self, Box<dyn error::Error>>;
fn from_seed_and_derivation_path(
seed: &[u8],
Expand Down
6 changes: 4 additions & 2 deletions zk-token-sdk/src/encryption/auth_encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use {
pubkey::Pubkey,
signature::Signature,
signer::{
keypair::generate_seed_from_seed_phrase_and_passphrase, EncodableKey, Signer,
SignerError,
keypair::generate_seed_from_seed_phrase_and_passphrase, EncodableKey, SeedDerivable,
Signer, SignerError,
},
},
std::{
Expand Down Expand Up @@ -126,7 +126,9 @@ impl EncodableKey for AeKey {
writer.write_all(&json.clone().into_bytes())?;
Ok(json)
}
}

impl SeedDerivable for AeKey {
fn from_seed(seed: &[u8]) -> Result<Self, Box<dyn error::Error>> {
const MINIMUM_SEED_LEN: usize = 16;

Expand Down
59 changes: 58 additions & 1 deletion zk-token-sdk/src/encryption/elgamal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use {
signature::Signature,
signer::{
keypair::generate_seed_from_seed_phrase_and_passphrase, EncodableKey, EncodableKeypair,
Signer, SignerError,
SeedDerivable, Signer, SignerError,
},
},
std::convert::TryInto,
Expand Down Expand Up @@ -248,7 +248,9 @@ impl EncodableKey for ElGamalKeypair {
fn write<W: Write>(&self, writer: &mut W) -> Result<String, Box<dyn error::Error>> {
self.write_json(writer)
}
}

impl SeedDerivable for ElGamalKeypair {
fn from_seed(seed: &[u8]) -> Result<Self, Box<dyn error::Error>> {
let secret = ElGamalSecretKey::from_seed(seed)?;
let public = ElGamalPubkey::new(&secret);
Expand Down Expand Up @@ -336,6 +338,22 @@ impl ElGamalPubkey {
}
}

impl EncodableKey for ElGamalPubkey {
fn read<R: Read>(reader: &mut R) -> Result<Self, Box<dyn error::Error>> {
let bytes: Vec<u8> = serde_json::from_reader(reader)?;
Self::from_bytes(&bytes).ok_or_else(|| {
std::io::Error::new(std::io::ErrorKind::Other, "Invalid ElGamalPubkey").into()
})
}

fn write<W: Write>(&self, writer: &mut W) -> Result<String, Box<dyn error::Error>> {
let bytes = self.to_bytes();
let json = serde_json::to_string(&bytes.to_vec())?;
writer.write_all(&json.clone().into_bytes())?;
Ok(json)
}
}

impl fmt::Display for ElGamalPubkey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", BASE64_STANDARD.encode(self.to_bytes()))
Expand Down Expand Up @@ -425,6 +443,45 @@ impl ElGamalSecretKey {
}
}

impl EncodableKey for ElGamalSecretKey {
fn read<R: Read>(reader: &mut R) -> Result<Self, Box<dyn error::Error>> {
let bytes: Vec<u8> = serde_json::from_reader(reader)?;
Self::from_bytes(&bytes).ok_or_else(|| {
std::io::Error::new(std::io::ErrorKind::Other, "Invalid ElGamalSecretKey").into()
})
}

fn write<W: Write>(&self, writer: &mut W) -> Result<String, Box<dyn error::Error>> {
let bytes = self.to_bytes();
let json = serde_json::to_string(&bytes.to_vec())?;
writer.write_all(&json.clone().into_bytes())?;
Ok(json)
}
}

impl SeedDerivable for ElGamalSecretKey {
fn from_seed(seed: &[u8]) -> Result<Self, Box<dyn error::Error>> {
Self::from_seed(seed)
}

fn from_seed_and_derivation_path(
_seed: &[u8],
_derivation_path: Option<DerivationPath>,
) -> Result<Self, Box<dyn error::Error>> {
Err(ElGamalError::DerivationMethodNotSupported.into())
}

fn from_seed_phrase_and_passphrase(
seed_phrase: &str,
passphrase: &str,
) -> Result<Self, Box<dyn error::Error>> {
Self::from_seed(&generate_seed_from_seed_phrase_and_passphrase(
seed_phrase,
passphrase,
))
}
}

impl From<Scalar> for ElGamalSecretKey {
fn from(scalar: Scalar) -> ElGamalSecretKey {
ElGamalSecretKey(scalar)
Expand Down

0 comments on commit 6de581a

Please sign in to comment.