summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--guide/src/chapter_01.md14
-rw-r--r--guide/src/chapter_02.md8
-rw-r--r--openpgp-ffi/src/common.rs24
-rw-r--r--openpgp-ffi/src/packet/key.rs4
-rw-r--r--openpgp-ffi/src/packet/pkesk.rs4
-rw-r--r--openpgp/examples/decrypt-with.rs4
-rw-r--r--openpgp/examples/generate-encrypt-decrypt.rs2
-rw-r--r--openpgp/examples/generate-sign-verify.rs2
-rw-r--r--openpgp/examples/notarize.rs2
-rw-r--r--openpgp/examples/sign-detached.rs2
-rw-r--r--openpgp/examples/sign.rs2
-rw-r--r--openpgp/src/crypto/asymmetric.rs2
-rw-r--r--openpgp/src/packet/key/mod.rs59
-rw-r--r--openpgp/src/packet/pkesk.rs13
-rw-r--r--openpgp/src/packet/signature/mod.rs2
-rw-r--r--openpgp/src/packet/signature/subpacket.rs3
-rw-r--r--openpgp/src/parse/stream.rs3
-rw-r--r--openpgp/src/serialize/mod.rs2
-rw-r--r--openpgp/src/serialize/stream.rs9
-rw-r--r--openpgp/src/serialize/tpk.rs5
-rw-r--r--openpgp/src/tpk/bindings.rs10
-rw-r--r--openpgp/src/tpk/builder.rs3
-rw-r--r--openpgp/src/tpk/mod.rs26
-rw-r--r--openpgp/src/tpk/revoke.rs8
24 files changed, 152 insertions, 61 deletions
diff --git a/guide/src/chapter_01.md b/guide/src/chapter_01.md
index 5c9d177f..b2b143bb 100644
--- a/guide/src/chapter_01.md
+++ b/guide/src/chapter_01.md
@@ -10,6 +10,7 @@ fragments yields the [`openpgp/examples/generate-sign-verify.rs`].
```rust
use std::io::{self, Write};
+use std::convert::TryInto;
extern crate failure;
extern crate sequoia_openpgp as openpgp;
@@ -51,7 +52,7 @@ fn main() {
# -> openpgp::Result<()> {
# // Get the keypair to do the signing from the TPK.
# let key : key::UnspecifiedSecret
-# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into();
+# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().try_into()?;
# let keypair = key.into_keypair()?;
#
# // Start streaming an OpenPGP message.
@@ -155,6 +156,7 @@ create it:
```rust
# use std::io::{self, Write};
+# use std::convert::TryInto;
#
# extern crate failure;
# extern crate sequoia_openpgp as openpgp;
@@ -196,7 +198,7 @@ fn generate() -> openpgp::Result<openpgp::TPK> {
# -> openpgp::Result<()> {
# // Get the keypair to do the signing from the TPK.
# let key : key::UnspecifiedSecret
-# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into();
+# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().try_into()?;
# let keypair = key.into_keypair()?;
#
# // Start streaming an OpenPGP message.
@@ -300,6 +302,7 @@ implements [`io::Write`], and we simply write the plaintext to it.
```rust
# use std::io::{self, Write};
+# use std::convert::TryInto;
#
# extern crate failure;
# extern crate sequoia_openpgp as openpgp;
@@ -341,7 +344,7 @@ fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::TPK)
-> openpgp::Result<()> {
// Get the keypair to do the signing from the TPK.
let key : key::UnspecifiedSecret
- = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into();
+ = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().try_into()?;
let keypair = key.into_keypair()?;
// Start streaming an OpenPGP message.
@@ -456,7 +459,8 @@ Verified data can be read from this using [`io::Read`].
```rust
# use std::io::{self, Write};
-#
+# use std::convert::TryInto;
+#
# extern crate failure;
# extern crate sequoia_openpgp as openpgp;
# use openpgp::serialize::stream::*;
@@ -497,7 +501,7 @@ Verified data can be read from this using [`io::Read`].
# -> openpgp::Result<()> {
# // Get the keypair to do the signing from the TPK.
# let key : key::UnspecifiedSecret
-# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into();
+# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().try_into()?;
# let keypair = key.into_keypair()?;
#
# // Start streaming an OpenPGP message.
diff --git a/guide/src/chapter_02.md b/guide/src/chapter_02.md
index acc2cb2e..d2d11964 100644
--- a/guide/src/chapter_02.md
+++ b/guide/src/chapter_02.md
@@ -132,7 +132,7 @@ fn main() {
# .unwrap();
#
# // The secret key is not encrypted.
-# let mut pair = key.mark_parts_secret().into_keypair().unwrap();
+# let mut pair = key.mark_parts_secret().unwrap().into_keypair().unwrap();
#
# pkesks[0].decrypt(&mut pair)
# .and_then(|(algo, session_key)| decrypt(algo, &session_key))
@@ -275,7 +275,7 @@ fn generate() -> openpgp::Result<openpgp::TPK> {
# .unwrap();
#
# // The secret key is not encrypted.
-# let mut pair = key.mark_parts_secret().into_keypair().unwrap();
+# let mut pair = key.mark_parts_secret().unwrap().into_keypair().unwrap();
#
# pkesks[0].decrypt(&mut pair)
# .and_then(|(algo, session_key)| decrypt(algo, &session_key))
@@ -418,7 +418,7 @@ fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK)
# .unwrap();
#
# // The secret key is not encrypted.
-# let mut pair = key.mark_parts_secret().into_keypair().unwrap();
+# let mut pair = key.mark_parts_secret().unwrap().into_keypair().unwrap();
#
# pkesks[0].decrypt(&mut pair)
# .and_then(|(algo, session_key)| decrypt(algo, &session_key))
@@ -575,7 +575,7 @@ impl<'a> DecryptionHelper for Helper<'a> {
.unwrap();
// The secret key is not encrypted.
- let mut pair = key.mark_parts_secret().into_keypair().unwrap();
+ let mut pair = key.mark_parts_secret().unwrap().into_keypair().unwrap();
pkesks[0].decrypt(&mut pair)
.and_then(|(algo, session_key)| decrypt(algo, &session_key))
diff --git a/openpgp-ffi/src/common.rs b/openpgp-ffi/src/common.rs
index 078c035e..7c615bab 100644
--- a/openpgp-ffi/src/common.rs
+++ b/openpgp-ffi/src/common.rs
@@ -164,6 +164,30 @@ macro_rules! ffi_make_fry_from_errp {
/// Like try! for ffi glue.
///
+ /// Evaluates the given expression. `Ok(v)` evaluates to `v`.
+ /// On failure, stashes the error in the context and returns
+ /// the appropriate Status code.
+ #[allow(unused_macros)]
+ macro_rules! ffi_try_or_status {
+ ($expr:expr) => {
+ match $expr {
+ Ok(v) => v,
+ Err(e) => {
+ use crate::MoveIntoRaw;
+ use failure::Error;
+ let status = crate::error::Status::from(&e);
+ if let Some(errp) = $errp {
+ let e : Error = e.into();
+ *errp = e.move_into_raw();
+ }
+ return status;
+ },
+ }
+ };
+ }
+
+ /// Like try! for ffi glue.
+ ///
/// Unwraps the given expression. On failure, stashes the
/// error in the context and returns $or.
#[allow(unused_macros)]
diff --git a/openpgp-ffi/src/packet/key.rs b/openpgp-ffi/src/packet/key.rs
index e0eead22..7f08d040 100644
--- a/openpgp-ffi/src/packet/key.rs
+++ b/openpgp-ffi/src/packet/key.rs
@@ -4,6 +4,8 @@
//!
//! [Section 5.5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.5
+use std::convert::TryInto;
+
use libc::{c_int, time_t};
extern crate sequoia_openpgp as openpgp;
@@ -79,6 +81,6 @@ fn pgp_key_into_key_pair(errp: Option<&mut *mut crate::error::Error>,
{
ffi_make_fry_from_errp!(errp);
let key : self::openpgp::packet::key::UnspecifiedSecret
- = key.move_from_raw().into();
+ = ffi_try!(key.move_from_raw().try_into());
ffi_try_box!(key.into_keypair())
}
diff --git a/openpgp-ffi/src/packet/pkesk.rs b/openpgp-ffi/src/packet/pkesk.rs
index 8f844d6c..82227065 100644
--- a/openpgp-ffi/src/packet/pkesk.rs
+++ b/openpgp-ffi/src/packet/pkesk.rs
@@ -44,7 +44,9 @@ pub extern "C" fn pgp_pkesk_decrypt(errp: Option<&mut *mut crate::error::Error>,
let algo = ffi_param_ref_mut!(algo);
let key_len = ffi_param_ref_mut!(key_len);
- match secret_key.clone().mark_parts_secret().into_keypair() {
+ match ffi_try_or_status!(secret_key.clone().mark_parts_secret())
+ .into_keypair()
+ {
Ok(mut keypair) => {
match pkesk.decrypt(&mut keypair) {
Ok((a, k)) => {
diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs
index 4b5d231a..99ec1fd7 100644
--- a/openpgp/examples/decrypt-with.rs
+++ b/openpgp/examples/decrypt-with.rs
@@ -65,8 +65,8 @@ impl Helper {
.unwrap_or(false)
{
// This only works for unencrypted secret keys.
- if let Ok(keypair)
- = key.clone().mark_parts_secret().into_keypair()
+ if let Ok(keypair) =
+ key.clone().mark_parts_secret().unwrap().into_keypair()
{
keys.insert(key.keyid(), keypair);
}
diff --git a/openpgp/examples/generate-encrypt-decrypt.rs b/openpgp/examples/generate-encrypt-decrypt.rs
index d20219ab..a2577906 100644
--- a/openpgp/examples/generate-encrypt-decrypt.rs
+++ b/openpgp/examples/generate-encrypt-decrypt.rs
@@ -123,7 +123,7 @@ impl<'a> DecryptionHelper for Helper<'a> {
.unwrap();
// The secret key is not encrypted.
- let mut pair = key.mark_parts_secret().into_keypair().unwrap();
+ let mut pair = key.mark_parts_secret().unwrap().into_keypair().unwrap();
pkesks[0].decrypt(&mut pair)
.and_then(|(algo, session_key)| decrypt(algo, &session_key))
diff --git a/openpgp/examples/generate-sign-verify.rs b/openpgp/examples/generate-sign-verify.rs
index 98e94f21..0ab1c7a5 100644
--- a/openpgp/examples/generate-sign-verify.rs
+++ b/openpgp/examples/generate-sign-verify.rs
@@ -41,7 +41,7 @@ fn sign(sink: &mut dyn Write, plaintext: &str, tsk: &openpgp::TPK)
-> openpgp::Result<()> {
// Get the keypair to do the signing from the TPK.
let keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2
- .clone().mark_parts_secret().into_keypair()?;
+ .clone().mark_parts_secret().unwrap().into_keypair()?;
// Start streaming an OpenPGP message.
let message = Message::new(sink);
diff --git a/openpgp/examples/notarize.rs b/openpgp/examples/notarize.rs
index d17aec44..fc161373 100644
--- a/openpgp/examples/notarize.rs
+++ b/openpgp/examples/notarize.rs
@@ -41,7 +41,7 @@ fn main() {
.expect("decryption failed");
}
n += 1;
- key.mark_parts_secret().into_keypair().unwrap()
+ key.mark_parts_secret().unwrap().into_keypair().unwrap()
});
}
diff --git a/openpgp/examples/sign-detached.rs b/openpgp/examples/sign-detached.rs
index 98202bd2..54c9ceef 100644
--- a/openpgp/examples/sign-detached.rs
+++ b/openpgp/examples/sign-detached.rs
@@ -37,7 +37,7 @@ fn main() {
.expect("decryption failed");
}
n += 1;
- key.mark_parts_secret().into_keypair().unwrap()
+ key.mark_parts_secret().unwrap().into_keypair().unwrap()
});
}
diff --git a/openpgp/examples/sign.rs b/openpgp/examples/sign.rs
index 523c9e26..ec80e87f 100644
--- a/openpgp/examples/sign.rs
+++ b/openpgp/examples/sign.rs
@@ -36,7 +36,7 @@ fn main() {
.expect("decryption failed");
}
n += 1;
- key.mark_parts_secret().into_keypair().unwrap()
+ key.mark_parts_secret().unwrap().into_keypair().unwrap()
});
}
diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs
index 144bcc4c..41d61014 100644
--- a/openpgp/src/crypto/asymmetric.rs
+++ b/openpgp/src/crypto/asymmetric.rs
@@ -280,6 +280,6 @@ impl<R> From<KeyPair<R>> for Key<key::SecretParts, R>
fn from(p: KeyPair<R>) -> Self {
let (mut key, secret) = (p.public, p.secret);
key.set_secret(Some(secret.into()));
- key.mark_parts_secret()
+ key.mark_parts_secret().expect("XXX")
}
}
diff --git a/openpgp/src/packet/key/mod.rs b/openpgp/src/packet/key/mod.rs
index b6337ce0..389d16f5 100644
--- a/openpgp/src/packet/key/mod.rs
+++ b/openpgp/src/packet/key/mod.rs
@@ -42,16 +42,18 @@
//! # .generate()?;
//! // Get a handle to the TPK's primary key that allows using the
//! // secret key material.
-//! let sk : &key::SecretKey = tpk.primary().into();
+//! use std::convert::TryInto;
+//! let sk : &key::SecretKey = tpk.primary().try_into()?;
//!
//! // Make the conversion explicit.
-//! let sk : &key::SecretKey = tpk.primary().mark_parts_secret_ref();
+//! let sk : &key::SecretKey = tpk.primary().mark_parts_secret_ref()?;
//! # Ok(())
//! # }
//! ```
use std::fmt;
use std::cmp::Ordering;
+use std::convert::TryFrom;
use std::time;
use crate::Error;
@@ -249,14 +251,43 @@ macro_rules! create_conversions {
}
}
- p!(<PublicParts> -> <SecretParts>);
+ // Likewise, but using TryFrom.
+ macro_rules! p_try {
+ ( <$from_parts:ty> -> <$to_parts:ty>) => {
+ impl<R> TryFrom<$Key<$from_parts, R>> for $Key<$to_parts, R>
+ where R: KeyRole
+ {
+ type Error = failure::Error;
+ fn try_from(p: $Key<$from_parts, R>) -> Result<Self> {
+ p.mark_parts_secret()
+ }
+ }
+
+ impl<R> TryFrom<&$Key<$from_parts, R>> for &$Key<$to_parts, R>
+ where R: KeyRole
+ {
+ type Error = failure::Error;
+ fn try_from(p: &$Key<$from_parts, R>) -> Result<Self> {
+ if p.secret().is_some() {
+ Ok(convert_ref!(p))
+ } else {
+ Err(Error::InvalidArgument("No secret key".into())
+ .into())
+ }
+ }
+ }
+ }
+ }
+
+
+ p_try!(<PublicParts> -> <SecretParts>);
p!(<PublicParts> -> <UnspecifiedParts>);
p!(<SecretParts> -> <PublicParts>);
p!(<SecretParts> -> <UnspecifiedParts>);
p!(<UnspecifiedParts> -> <PublicParts>);
- p!(<UnspecifiedParts> -> <SecretParts>);
+ p_try!(<UnspecifiedParts> -> <SecretParts>);
// Convert between two KeyRoles for a constant KeyParts. See
// the comment for the p macro above.
@@ -438,13 +469,22 @@ macro_rules! create_conversions {
}
/// Changes the key's parts tag to `SecretParts`.
- pub fn mark_parts_secret(self) -> $Key<SecretParts, R> {
- convert!(self)
+ pub fn mark_parts_secret(self) -> Result<$Key<SecretParts, R>> {
+ if self.secret().is_some() {
+ Ok(convert!(self))
+ } else {
+ Err(Error::InvalidArgument("No secret key".into()).into())
+ }
}
/// Changes the key's parts tag to `SecretParts`.
- pub fn mark_parts_secret_ref(&self) -> &$Key<SecretParts, R> {
- convert_ref!(self)
+ pub fn mark_parts_secret_ref(&self) -> Result<&$Key<SecretParts, R>>
+ {
+ if self.secret().is_some() {
+ Ok(convert_ref!(self))
+ } else {
+ Err(Error::InvalidArgument("No secret key".into()).into())
+ }
}
/// Changes the key's parts tag to `UnspecifiedParts`.
@@ -1370,7 +1410,8 @@ mod tests {
for key in keys.into_iter() {
let key : key::PublicKey = key.into();
let mut keypair
- = key.clone().mark_parts_secret().into_keypair().unwrap();
+ = key.clone().mark_parts_secret().unwrap()
+ .into_keypair().unwrap();
let cipher = SymmetricAlgorithm::AES256;
let sk = SessionKey::new(cipher.key_size().unwrap());
diff --git a/openpgp/src/packet/pkesk.rs b/openpgp/src/packet/pkesk.rs
index b2e9a0f4..29fd715f 100644
--- a/openpgp/src/packet/pkesk.rs
+++ b/openpgp/src/packet/pkesk.rs
@@ -229,7 +229,7 @@ mod tests {
crate::tests::message("encrypted-to-testy.gpg")).unwrap();
let mut keypair =
tpk.subkeys().next().unwrap()
- .key().clone().mark_parts_secret().into_keypair().unwrap();
+ .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap();
let pkg = pile.descendants().skip(0).next().clone();
@@ -250,7 +250,7 @@ mod tests {
crate::tests::message("encrypted-to-testy-new.pgp")).unwrap();
let mut keypair =
tpk.subkeys().next().unwrap()
- .key().clone().mark_parts_secret().into_keypair().unwrap();
+ .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap();
let pkg = pile.descendants().skip(0).next().clone();
@@ -271,7 +271,7 @@ mod tests {
crate::tests::message("encrypted-to-testy-nistp256.pgp")).unwrap();
let mut keypair =
tpk.subkeys().next().unwrap()
- .key().clone().mark_parts_secret().into_keypair().unwrap();
+ .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap();
let pkg = pile.descendants().skip(0).next().clone();
@@ -292,7 +292,7 @@ mod tests {
crate::tests::message("encrypted-to-testy-nistp384.pgp")).unwrap();
let mut keypair =
tpk.subkeys().next().unwrap()
- .key().clone().mark_parts_secret().into_keypair().unwrap();
+ .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap();
let pkg = pile.descendants().skip(0).next().clone();
@@ -313,7 +313,7 @@ mod tests {
crate::tests::message("encrypted-to-testy-nistp521.pgp")).unwrap();
let mut keypair =
tpk.subkeys().next().unwrap()
- .key().clone().mark_parts_secret().into_keypair().unwrap();
+ .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap();
let pkg = pile.descendants().skip(0).next().clone();
@@ -370,7 +370,8 @@ mod tests {
let sess_key = SessionKey::new(32);
let pkesk = PKESK3::for_recipient(SymmetricAlgorithm::AES256, &sess_key,
&key).unwrap();
- let mut keypair = key.mark_parts_secret().into_keypair().unwrap();
+ let mut keypair =
+ key.mark_parts_secret().unwrap().into_keypair().unwrap();
pkesk.decrypt(&mut keypair).unwrap();
}
}
diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs
index ab7762b9..211a4447 100644
--- a/openpgp/src/packet/signature/mod.rs
+++ b/openpgp/src/packet/signature/mod.rs
@@ -1260,7 +1260,7 @@ mod test {
] {
let tpk = TPK::from_bytes(crate::tests::key(key)).unwrap();
let mut pair = tpk.primary().clone()
- .mark_parts_secret()
+ .mark_parts_secret().unwrap()
.into_keypair()
.expect("secret key is encrypted/missing");
diff --git a/openpgp/src/packet/signature/subpacket.rs b/openpgp/src/packet/signature/subpacket.rs
index b801eb6c..2a83920b 100644
--- a/openpgp/src/packet/signature/subpacket.rs
+++ b/openpgp/src/packet/signature/subpacket.rs
@@ -2735,7 +2735,8 @@ fn accessors() {
let mut sig = signature::Builder::new(crate::constants::SignatureType::Binary);
let mut key: crate::packet::key::PublicKey =
crate::packet::key::Key4::generate_ecc(true, Curve::Ed25519).unwrap().into();
- let mut keypair = key.clone().mark_parts_secret().into_keypair().unwrap();
+ let mut keypair = key.clone().mark_parts_secret().unwrap()
+ .into_keypair().unwrap();
// Cook up a timestamp without ns resolution.
let now = time::SystemTime::now().canonicalize();
diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs
index bab21e4c..48c1fd2a 100644
--- a/openpgp/src/parse/stream.rs
+++ b/openpgp/src/parse/stream.rs
@@ -1911,7 +1911,8 @@ mod test {
{
let key = tpk.keys_all().signing_capable().nth(0).unwrap().2;
let keypair =
- key.clone().mark_parts_secret().into_keypair().unwrap();
+ key.clone().mark_parts_secret().unwrap()
+ .into_keypair().unwrap();
let m = Message::new(&mut buf);
let signer = Signer::new(m, keypair).build().unwrap();
diff --git a/openpgp/src/serialize/mod.rs b/openpgp/src/serialize/mod.rs
index d37c0c7e..325b181f 100644
--- a/openpgp/src/serialize/mod.rs
+++ b/openpgp/src/serialize/mod.rs
@@ -2938,7 +2938,7 @@ mod test {
let (tpk, _) = TPKBuilder::new().generate().unwrap();
let mut keypair = tpk.primary().clone().mark_parts_secret()
- .into_keypair().unwrap();
+ .unwrap().into_keypair().unwrap();
let uid = UserID::from("foo");
// Make a signature w/o an exportable certification subpacket.
diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs
index 4b1e0d88..5af424d3 100644
--- a/openpgp/src/serialize/stream.rs
+++ b/openpgp/src/serialize/stream.rs
@@ -230,7 +230,7 @@ impl<'a> Signer<'a> {
/// # "../../tests/data/keys/testy-new-private.pgp")[..])
/// # .unwrap();
/// # let keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2
- /// # .clone().mark_parts_secret().into_keypair().unwrap();
+ /// # .clone().mark_parts_secret().unwrap().into_keypair().unwrap();
/// # f(tsk, keypair).unwrap();
/// # fn f(tpk: TPK, mut signing_keypair: KeyPair<key::UnspecifiedRole>)
/// # -> Result<()> {
@@ -333,7 +333,7 @@ impl<'a> Signer<'a> {
/// # "../../tests/data/keys/testy-new-private.pgp")[..])
/// # .unwrap();
/// # let keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2
- /// # .clone().mark_parts_secret().into_keypair().unwrap();
+ /// # .clone().mark_parts_secret().unwrap().into_keypair().unwrap();
/// # f(tsk, keypair).unwrap();
/// # fn f(tpk: TPK, mut signing_keypair: KeyPair<key::UnspecifiedRole>)
/// # -> Result<()> {
@@ -1478,7 +1478,7 @@ mod test {
let mut o = vec![];
{
let mut signers = keys.iter().map(|(_, key)| {
- key.clone().mark_parts_secret().into_keypair()
+ key.clone().mark_parts_secret().unwrap().into_keypair()
.expect("expected unencrypted secret key")
}).collect::<Vec<KeyPair<_>>>();