diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-12-05 16:13:54 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-12-05 16:21:52 +0100 |
commit | 41fd3f08adff856ec558f8b06214e0f392893a26 (patch) | |
tree | e7894d4e77074109692503fab3b3b46d343f70b6 | |
parent | 71a3a540bda400f52a841c04b8d33a51959fa8f0 (diff) |
openpgp: Make crypto::{Signer,Decryptor} non-polymorphic.
- These are low-level cryptographic traits that are not concerned
with the role of a key.
- Fixes #382.
-rw-r--r-- | ipc/examples/gpg-agent-sign.rs | 2 | ||||
-rw-r--r-- | ipc/src/gnupg.rs | 30 | ||||
-rw-r--r-- | openpgp-ffi/src/cert.rs | 14 | ||||
-rw-r--r-- | openpgp-ffi/src/crypto.rs | 13 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/key.rs | 3 | ||||
-rw-r--r-- | openpgp-ffi/src/serialize.rs | 6 | ||||
-rw-r--r-- | openpgp/examples/decrypt-with.rs | 3 | ||||
-rw-r--r-- | openpgp/src/cert/bindings.rs | 47 | ||||
-rw-r--r-- | openpgp/src/cert/mod.rs | 17 | ||||
-rw-r--r-- | openpgp/src/cert/revoke.rs | 32 | ||||
-rw-r--r-- | openpgp/src/crypto/asymmetric.rs | 48 | ||||
-rw-r--r-- | openpgp/src/packet/mod.rs | 9 | ||||
-rw-r--r-- | openpgp/src/packet/pkesk.rs | 3 | ||||
-rw-r--r-- | openpgp/src/packet/signature/mod.rs | 47 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 12 | ||||
-rw-r--r-- | tool/src/commands/decrypt.rs | 2 | ||||
-rw-r--r-- | tool/src/commands/mod.rs | 3 |
17 files changed, 121 insertions, 170 deletions
diff --git a/ipc/examples/gpg-agent-sign.rs b/ipc/examples/gpg-agent-sign.rs index 5e8c28c6..e0cfeb98 100644 --- a/ipc/examples/gpg-agent-sign.rs +++ b/ipc/examples/gpg-agent-sign.rs @@ -42,7 +42,7 @@ fn main() { cert.keys_valid().for_signing().filter_map(|(_, _, key)| { KeyPair::new(&ctx, key).ok() }) - }).collect::<Vec<KeyPair<_>>>(); + }).collect::<Vec<KeyPair>>(); // Compose a writer stack corresponding to the output format and // packet structure we want. First, we want the output to be diff --git a/ipc/src/gnupg.rs b/ipc/src/gnupg.rs index d2f28f4d..561c749b 100644 --- a/ipc/src/gnupg.rs +++ b/ipc/src/gnupg.rs @@ -685,34 +685,30 @@ impl<'a, 'b, 'c, R> Future for DecryptionRequest<'a, 'b, 'c, R> /// A `KeyPair` is a combination of public and secret key. This /// particular implementation does not have the secret key, but /// diverges the cryptographic operations to `gpg-agent`. -pub struct KeyPair<'a, R> - where R: key::KeyRole -{ - public: &'a Key<key::PublicParts, R>, +pub struct KeyPair<'a> { + public: &'a Key<key::PublicParts, key::UnspecifiedRole>, agent_socket: PathBuf, } -impl<'a, R> KeyPair<'a, R> - where R: key::KeyRole -{ +impl<'a> KeyPair<'a> { /// Returns a `KeyPair` for `key` with the secret bits managed by /// the agent. /// /// This provides a convenient, synchronous interface for use with /// the low-level Sequoia crate. - pub fn new(ctx: &Context, key: &'a Key<key::PublicParts, R>) - -> Result<KeyPair<'a, R>> { + pub fn new<R>(ctx: &Context, key: &'a Key<key::PublicParts, R>) + -> Result<KeyPair<'a>> + where R: key::KeyRole + { Ok(KeyPair { - public: key, + public: key.mark_role_unspecified_ref(), agent_socket: ctx.socket("agent")?.into(), }) } } -impl<'a, R> crypto::Signer<R> for KeyPair<'a, R> - where R: key::KeyRole -{ - fn public(&self) -> &Key<key::PublicParts, R> { +impl<'a> crypto::Signer for KeyPair<'a> { + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { self.public } @@ -742,10 +738,8 @@ impl<'a, R> crypto::Signer<R> for KeyPair<'a, R> } } -impl<'a, R> crypto::Decryptor<R> for KeyPair<'a, R> - where R: key::KeyRole -{ - fn public(&self) -> &Key<key::PublicParts, R> { +impl<'a> crypto::Decryptor for KeyPair<'a> { + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { self.public } diff --git a/openpgp-ffi/src/cert.rs b/openpgp-ffi/src/cert.rs index 561d0c2c..00e7b3b4 100644 --- a/openpgp-ffi/src/cert.rs +++ b/openpgp-ffi/src/cert.rs @@ -232,8 +232,7 @@ fn int_to_reason_for_revocation(code: c_int) -> ReasonForRevocation { #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_cert_revoke(errp: Option<&mut *mut crate::error::Error>, cert: *const Cert, - primary_signer: *mut Box<dyn crypto::Signer< - openpgp::packet::key::UnspecifiedRole>>, + primary_signer: *mut Box<dyn crypto::Signer>, code: c_int, reason: Option<&c_char>) -> Maybe<Signature> @@ -299,8 +298,7 @@ fn pgp_cert_revoke(errp: Option<&mut *mut crate::error::Error>, #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_cert_revoke_in_place(errp: Option<&mut *mut crate::error::Error>, cert: *mut Cert, - primary_signer: *mut Box<dyn crypto::Signer< - openpgp::packet::key::UnspecifiedRole>>, + primary_signer: *mut Box<dyn crypto::Signer>, code: c_int, reason: Option<&c_char>) -> Maybe<Cert> @@ -342,10 +340,10 @@ fn pgp_cert_alive(cert: *const Cert, when: time_t) /// This function consumes `cert` and returns a new `Cert`. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_cert_set_expiry(errp: Option<&mut *mut crate::error::Error>, - cert: *mut Cert, primary_signer: *mut Box<dyn crypto::Signer< - openpgp::packet::key::UnspecifiedRole>>, - expiry: u32) - -> Maybe<Cert> { + cert: *mut Cert, + primary_signer: *mut Box<dyn crypto::Signer>, + expiry: u32) + -> Maybe<Cert> { let cert = cert.move_from_raw(); let signer = ffi_param_ref_mut!(primary_signer); diff --git a/openpgp-ffi/src/crypto.rs b/openpgp-ffi/src/crypto.rs index 41c58504..d4e7ace9 100644 --- a/openpgp-ffi/src/crypto.rs +++ b/openpgp-ffi/src/crypto.rs @@ -58,8 +58,7 @@ fn pgp_password_from_bytes(buf: *const u8, size: size_t) -> *mut Password { /// Frees a signer. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_signer_free - (s: Option<&mut &'static mut dyn crypto::Signer< - openpgp::packet::key::UnspecifiedRole>>) + (s: Option<&mut &'static mut dyn crypto::Signer>) { ffi_free!(s) } @@ -69,7 +68,7 @@ pub extern "C" fn pgp_signer_free pub extern "C" fn pgp_key_pair_new (errp: Option<&mut *mut crate::error::Error>, public: *mut Key, secret: *mut openpgp::packet::key::Unencrypted) - -> *mut crypto::KeyPair<openpgp::packet::key::UnspecifiedRole> + -> *mut crypto::KeyPair { ffi_make_fry_from_errp!(errp); let public = public.move_from_raw(); @@ -80,7 +79,7 @@ pub extern "C" fn pgp_key_pair_new /// Frees a key pair. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_key_pair_free - (kp: Option<&mut crypto::KeyPair<openpgp::packet::key::UnspecifiedRole>>) + (kp: Option<&mut crypto::KeyPair>) { ffi_free!(kp) } @@ -91,11 +90,11 @@ pub extern "C" fn pgp_key_pair_free /// must not outlive the key pair. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_key_pair_as_signer - (kp: *mut crypto::KeyPair<openpgp::packet::key::UnspecifiedRole>) - -> *mut &'static mut dyn crypto::Signer<openpgp::packet::key::UnspecifiedRole> + (kp: *mut crypto::KeyPair) + -> *mut &'static mut dyn crypto::Signer { let kp = ffi_param_ref_mut!(kp); - let signer: &mut dyn crypto::Signer<_> = kp; + let signer: &mut dyn crypto::Signer = kp; box_raw!(signer) //box_raw!(kp) } diff --git a/openpgp-ffi/src/packet/key.rs b/openpgp-ffi/src/packet/key.rs index 7f08d040..e612e4ae 100644 --- a/openpgp-ffi/src/packet/key.rs +++ b/openpgp-ffi/src/packet/key.rs @@ -76,8 +76,7 @@ fn pgp_key_public_key_bits(key: *const Key) -> c_int { #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_key_into_key_pair(errp: Option<&mut *mut crate::error::Error>, key: *mut Key) - -> *mut self::openpgp::crypto::KeyPair< - self::openpgp::packet::key::UnspecifiedRole> + -> *mut self::openpgp::crypto::KeyPair { ffi_make_fry_from_errp!(errp); let key : self::openpgp::packet::key::UnspecifiedSecret diff --git a/openpgp-ffi/src/serialize.rs b/openpgp-ffi/src/serialize.rs index 5c74b413..6f24a5aa 100644 --- a/openpgp-ffi/src/serialize.rs +++ b/openpgp-ffi/src/serialize.rs @@ -150,8 +150,7 @@ pub extern "C" fn pgp_arbitrary_writer_new pub extern "C" fn pgp_signer_new (errp: Option<&mut *mut crate::error::Error>, inner: *mut writer::Stack<'static, Cookie>, - signers: *const *mut Box<dyn self::openpgp::crypto::Signer< - self::openpgp::packet::key::UnspecifiedRole>>, + signers: *const *mut Box<dyn self::openpgp::crypto::Signer>, signers_len: size_t, hash_algo: u8) -> *mut writer::Stack<'static, Cookie> @@ -188,8 +187,7 @@ pub extern "C" fn pgp_signer_new pub extern "C" fn pgp_signer_new_detached (errp: Option<&mut *mut crate::error::Error>, inner: *mut writer::Stack<'static, Cookie>, - signers: *const *mut Box<dyn self::openpgp::crypto::Signer< - self::openpgp::packet::key::UnspecifiedRole>>, + signers: *const *mut Box<dyn self::openpgp::crypto::Signer>, signers_len: size_t, hash_algo: u8) -> *mut writer::Stack<'static, Cookie> diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs index 537e8f8b..224a8726 100644 --- a/openpgp/examples/decrypt-with.rs +++ b/openpgp/examples/decrypt-with.rs @@ -10,7 +10,6 @@ extern crate sequoia_openpgp as openpgp; use crate::openpgp::crypto::{KeyPair, SessionKey}; use crate::openpgp::types::SymmetricAlgorithm; -use crate::openpgp::packet::key; use crate::openpgp::parse::{ Parse, stream::{ @@ -50,7 +49,7 @@ pub fn main() { /// keys for the signature verification and implements the /// verification policy. struct Helper { - keys: HashMap<openpgp::KeyID, KeyPair<key::UnspecifiedRole>>, + keys: HashMap<openpgp::KeyID, KeyPair>, } impl Helper { diff --git a/openpgp/src/cert/bindings.rs b/openpgp/src/cert/bindings.rs index 70ade707..c6d9e6c6 100644 --- a/openpgp/src/cert/bindings.rs +++ b/openpgp/src/cert/bindings.rs @@ -52,12 +52,11 @@ impl<P: key::KeyParts> Key<P, key::SubordinateRole> { /// // Check that we have an encryption subkey. /// assert_eq!(cert.keys_valid().key_flags(flags).count(), 1); /// # Ok(()) } - pub fn bind<T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature: signature::Builder, - creation_time: T) + pub fn bind<T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature: signature::Builder, + creation_time: T) -> Result<Signature> - where T: Into<Option<time::SystemTime>>, - R: key::KeyRole + where T: Into<Option<time::SystemTime>> { signature .set_signature_creation_time( @@ -110,12 +109,11 @@ impl UserID { /// // Check that we have a userid. /// assert_eq!(cert.userids().len(), 1); /// # Ok(()) } - pub fn bind<T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature: signature::Builder, - creation_time: T) - -> Result<Signature> - where T: Into<Option<time::SystemTime>>, - R: key::KeyRole + pub fn bind<T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature: signature::Builder, + creation_time: T) + -> Result<Signature> + where T: Into<Option<time::SystemTime>> { signature .set_signature_creation_time( @@ -180,14 +178,13 @@ impl UserID { /// // Check that we have a certification on the userid. /// assert_eq!(bob.userids().nth(0).unwrap().certifications().len(), 1); /// # Ok(()) } - pub fn certify<S, H, T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature_type: S, - hash_algo: H, creation_time: T) + pub fn certify<S, H, T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature_type: S, + hash_algo: H, creation_time: T) -> Result<Signature> where S: Into<Option<SignatureType>>, H: Into<Option<HashAlgorithm>>, - T: Into<Option<time::SystemTime>>, - R: key::KeyRole + T: Into<Option<time::SystemTime>> { let typ = signature_type.into(); let typ = match typ { @@ -257,12 +254,11 @@ impl UserAttribute { /// // Check that we have a user attribute. /// assert_eq!(cert.user_attributes().len(), 1); /// # Ok(()) } - pub fn bind<T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature: signature::Builder, - creation_time: T) + pub fn bind<T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature: signature::Builder, + creation_time: T) -> Result<Signature> - where T: Into<Option<time::SystemTime>>, - R: key::KeyRole + where T: Into<Option<time::SystemTime>> { signature .set_signature_creation_time( @@ -331,14 +327,13 @@ impl UserAttribute { /// assert_eq!(bob.user_attributes().nth(0).unwrap().certifications().len(), /// 1); /// # Ok(()) } - pub fn certify<S, H, T, R>(&self, signer: &mut dyn Signer<R>, cert: &Cert, - signature_type: S, - hash_algo: H, creation_time: T) + pub fn certify<S, H, T>(&self, signer: &mut dyn Signer, cert: &Cert, + signature_type: S, + hash_algo: H, creation_time: T) -> Result<Signature> where S: Into<Option<SignatureType>>, H: Into<Option<HashAlgorithm>>, - T: Into<Option<time::SystemTime>>, - R: key::KeyRole + T: Into<Option<time::SystemTime>> { let typ = signature_type.into(); let typ = match typ { diff --git a/openpgp/src/cert/mod.rs b/openpgp/src/cert/mod.rs index 23db1bc8..d0999a95 100644 --- a/openpgp/src/cert/mod.rs +++ b/openpgp/src/cert/mod.rs @@ -1095,10 +1095,9 @@ impl Cert { /// # Ok(()) /// # } /// ``` - pub fn revoke_in_place<R>(self, primary_signer: &mut dyn Signer<R>, - code: ReasonForRevocation, reason: &[u8]) + pub fn revoke_in_place(self, primary_signer: &mut dyn Signer, + code: ReasonForRevocation, reason: &[u8]) -> Result<Cert> - where R: key::KeyRole { let sig = CertRevocationBuilder::new() .set_reason_for_revocation(code, reason)? @@ -1137,11 +1136,10 @@ impl Cert { /// /// This function exists to facilitate testing, which is why it is /// not exported. - fn set_expiry_as_of<R>(self, primary_signer: &mut dyn Signer<R>, - expiration: Option<time::Duration>, - now: time::SystemTime) + fn set_expiry_as_of(self, primary_signer: &mut dyn Signer, + expiration: Option<time::Duration>, + now: time::SystemTime) -> Result<Cert> - where R: key::KeyRole { let sig = { let (template, userid) = self @@ -1173,10 +1171,9 @@ impl Cert { /// /// Note: the time is relative to the key's creation time, not the /// current time! - pub fn set_expiry<R>(self, primary_signer: &mut dyn Signer<R>, - expiration: Option<time::Duration>) + pub fn set_expiry(self, primary_signer: &mut dyn Signer, + expiration: Option<time::Duration>) -> Result<Cert> - where R: key::KeyRole { self.set_expiry_as_of(primary_signer, expiration, time::SystemTime::now()) diff --git a/openpgp/src/cert/revoke.rs b/openpgp/src/cert/revoke.rs index f4f6e31c..a4876e0f 100644 --- a/openpgp/src/cert/revoke.rs +++ b/openpgp/src/cert/revoke.rs @@ -100,10 +100,9 @@ impl CertRevocationBuilder { /// Returns a revocation certificate for the cert `Cert` signed by /// `signer`. - pub fn build<H, R>(self, signer: &mut dyn Signer<R>, cert: &Cert, hash_algo: H) + pub fn build<H>(self, signer: &mut dyn Signer, cert: &Cert, hash_algo: H) -> Result<Signature> - where H: Into<Option<HashAlgorithm>>, - R: key::KeyRole + where H: Into<Option<HashAlgorithm>> { let hash_algo = hash_algo.into().unwrap_or(HashAlgorithm::SHA512); let mut hash = hash_algo.context()?; @@ -221,12 +220,11 @@ impl SubkeyRevocationBuilder { /// Returns a revocation certificate for the cert `Cert` signed by /// `signer`. - pub fn build<H, R>(mut self, signer: &mut dyn Signer<R>, - cert: &Cert, key: &key::PublicSubkey, - hash_algo: H) + pub fn build<H>(mut self, signer: &mut dyn Signer, + cert: &Cert, key: &key::PublicSubkey, + hash_algo: H) -> Result<Signature> - where H: Into<Option<HashAlgorithm>>, - R: key::KeyRole + where H: Into<Option<HashAlgorithm>> { let hash_algo = hash_algo.into().unwrap_or(HashAlgorithm::SHA512); let creation_time @@ -337,12 +335,11 @@ impl UserIDRevocationBuilder { /// Returns a revocation certificate for the cert `Cert` signed by /// `signer`. - pub fn build<H, R>(mut self, signer: &mut dyn Signer<R>, - cert: &Cert, userid: &UserID, - hash_algo: H) + pub fn build<H>(mut self, signer: &mut dyn Signer, + cert: &Cert, userid: &UserID, + hash_algo: H) -> Result<Signature> - where H: Into<Option<HashAlgorithm>>, - R: key::KeyRole + where H: Into<Option<HashAlgorithm>> { let hash_algo = hash_algo.into().unwrap_or(HashAlgorithm::SHA512); let creation_time @@ -456,12 +453,11 @@ impl UserAttributeRevocationBuilder { /// Returns a revocation certificate for the cert `Cert` signed by /// `signer`. - pub fn build<H, R>(mut self, signer: &mut dyn Signer<R>, - cert: &Cert, ua: &UserAttribute, - hash_algo: H) + pub fn build<H>(mut self, signer: &mut dyn Signer, + cert: &Cert, ua: &UserAttribute, + hash_algo: H) -> Result<Signature> - where H: Into<Option<HashAlgorithm>>, - R: key::KeyRole + where H: Into<Option<HashAlgorithm>> { let hash_algo = hash_algo.into().unwrap_or(HashAlgorithm::SHA512); let creation_time diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs index e67461ce..7185a471 100644 --- a/openpgp/src/crypto/asymmetric.rs +++ b/openpgp/src/crypto/asymmetric.rs @@ -16,19 +16,17 @@ use crate::Result; /// signature. Using this trait allows Sequoia to perform all /// operations involving signing to use a variety of secret key /// storage mechanisms (e.g. smart cards). -pub trait Signer<R> - where R: key::KeyRole -{ +pub trait Signer { /// Returns a reference to the public key. - fn public(&self) -> &Key<key::PublicParts, R>; + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole>; /// Creates a signature over the `digest` produced by `hash_algo`. fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8]) -> Result<mpis::Signature>; } -impl<R: key::KeyRole> Signer<R> for Box<dyn Signer<R>> { - fn public(&self) -> &Key<key::PublicParts, R> { +impl Signer for Box<dyn Signer> { + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { self.as_ref().public() } @@ -44,11 +42,9 @@ impl<R: key::KeyRole> Signer<R> for Box<dyn Signer<R>> { /// ciphertext. Using this trait allows Sequoia to perform all /// operations involving decryption to use a variety of secret key /// storage mechanisms (e.g. smart cards). -pub trait Decryptor<R> - where R: key::KeyRole -{ +pub trait Decryptor { /// Returns a reference to the public key. - fn public(&self) -> &Key<key::PublicParts, R>; + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole>; /// Decrypts `ciphertext`, returning the plain session key. fn decrypt(&mut self, ciphertext: &mpis::Ciphertext) @@ -64,18 +60,14 @@ pub trait Decryptor<R> /// [`Signer`]: trait.Signer.html /// [`Decryptor`]: trait.Decryptor.html #[derive(Clone)] -pub struct KeyPair<R> - where R: key::KeyRole -{ - public: Key<key::PublicParts, R>, +pub struct KeyPair { + public: Key<key::PublicParts, key::UnspecifiedRole>, secret: packet::key::Unencrypted, } -impl<R> KeyPair<R> - where R: key::KeyRole -{ +impl KeyPair { /// Creates a new key pair. - pub fn new(public: Key<key::PublicParts, R>, + pub fn new(public: Key<key::PublicParts, key::UnspecifiedRole>, secret: packet::key::Unencrypted) -> Result<Self> { @@ -86,7 +78,7 @@ impl<R> KeyPair<R> } /// Returns a reference to the public key. - pub fn public(&self) -> &Key<key::PublicParts, R> { + pub fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { &self.public } @@ -96,10 +88,8 @@ impl<R> KeyPair<R> } } -impl<R> Signer<R> for KeyPair<R> - where R: key::KeyRole -{ - fn public(&self) -> &Key<key::PublicParts, R> { +impl Signer for KeyPair { + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { &self.public } @@ -226,10 +216,8 @@ impl<R> Signer<R> for KeyPair<R> } } -impl<R> Decryptor<R> for KeyPair<R> - where R: key::KeyRole -{ - fn public(&self) -> &Key<key::PublicParts, R> { +impl Decryptor for KeyPair { + fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> { &self.public } @@ -274,10 +262,8 @@ impl<R> Decryptor<R> for KeyPair<R> } } -impl<R> From<KeyPair<R>> for Key<key::SecretParts, R> - where R: key::KeyRole -{ - fn from(p: KeyPair<R>) -> Self { +impl From<KeyPair> for Key<key::SecretParts, key::UnspecifiedRole> { + fn from(p: KeyPair) -> Self { let (mut key, secret) = (p.public, p.secret); key.set_secret(Some(secret.into())); key.mark_parts_secret().expect("XXX") |