summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openpgp/src/crypto/asymmetric.rs153
-rw-r--r--openpgp/src/crypto/mod.rs5
-rw-r--r--openpgp/src/message/mod.rs2
-rw-r--r--openpgp/src/packet/signature/mod.rs151
-rw-r--r--openpgp/src/packet/signature/subpacket.rs2
-rw-r--r--openpgp/src/serialize/stream.rs3
-rw-r--r--openpgp/src/tpk/builder.rs3
-rw-r--r--openpgp/src/tpk/mod.rs3
-rw-r--r--openpgp/src/tsk.rs3
9 files changed, 169 insertions, 156 deletions
diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs
index 9c8a1ae6..51d95934 100644
--- a/openpgp/src/crypto/asymmetric.rs
+++ b/openpgp/src/crypto/asymmetric.rs
@@ -1,9 +1,12 @@
-//! Asymmetric crypto operations.
+//! Asymmetric crypt operations.
+
+use nettle::{dsa, ecdsa, ed25519, rsa, Yarrow};
use packet::Key;
-use crypto::mpis;
-use constants::HashAlgorithm;
+use crypto::mpis::{self, MPI};
+use constants::{Curve, HashAlgorithm};
+use Error;
use Result;
/// Creates a signature.
@@ -20,3 +23,147 @@ pub trait Signer {
fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
-> Result<mpis::Signature>;
}
+
+/// A cryptographic key pair.
+pub struct KeyPair {
+ public: Key,
+ secret: mpis::SecretKey,
+}
+
+impl KeyPair {
+ /// Creates a new key pair.
+ pub fn new(public: Key, secret: mpis::SecretKey) -> Result<Self> {
+ Ok(Self {
+ public: public,
+ secret: secret,
+ })
+ }
+}
+
+impl Signer for KeyPair {
+ fn public(&self) -> &Key {
+ &self.public
+ }
+
+ fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
+ -> Result<mpis::Signature>
+ {
+ use PublicKeyAlgorithm::*;
+ use crypto::mpis::PublicKey;
+ use memsec;
+
+ let mut rng = Yarrow::default();
+
+ #[allow(deprecated)]
+ match (self.public.pk_algo(), self.public.mpis(), &self.secret)
+ {
+ (RSASign,
+ &PublicKey::RSA { ref e, ref n },
+ &mpis::SecretKey::RSA { ref p, ref q, ref d, .. }) |
+ (RSAEncryptSign,
+ &PublicKey::RSA { ref e, ref n },
+ &mpis::SecretKey::RSA { ref p, ref q, ref d, .. }) => {
+ let public = rsa::PublicKey::new(&n.value, &e.value)?;
+ let secret = rsa::PrivateKey::new(&d.value, &p.value,
+ &q.value, Option::None)?;
+
+ // The signature has the length of the modulus.
+ let mut sig = vec![0u8; n.value.len()];
+
+ // As described in [Section 5.2.2 and 5.2.3 of RFC 4880],
+ // to verify the signature, we need to encode the
+ // signature data in a PKCS1-v1.5 packet.
+ //
+ // [Section 5.2.2 and 5.2.3 of RFC 4880]:
+ // https://tools.ietf.org/html/rfc4880#section-5.2.2
+ rsa::sign_digest_pkcs1(&public, &secret, digest,
+ hash_algo.oid()?,
+ &mut rng, &mut sig)?;
+
+ Ok(mpis::Signature::RSA {
+ s: MPI::new(&sig),
+ })
+ },
+
+ (DSA,
+ &PublicKey::DSA { ref p, ref q, ref g, .. },
+ &mpis::SecretKey::DSA { ref x }) => {
+ let params = dsa::Params::new(&p.value, &q.value, &g.value);
+ let secret = dsa::PrivateKey::new(&x.value);
+
+ let sig = dsa::sign(&params, &secret, digest, &mut rng)?;
+
+ Ok(mpis::Signature::DSA {
+ r: MPI::new(&sig.r()),
+ s: MPI::new(&sig.s()),
+ })
+ },
+
+ (EdDSA,
+ &PublicKey::EdDSA { ref curve, ref q },
+ &mpis::SecretKey::EdDSA { ref scalar }) => match curve {
+ Curve::Ed25519 => {
+ let public = q.decode_point(&Curve::Ed25519)?.0;
+
+ let mut sig = vec![0; ed25519::ED25519_SIGNATURE_SIZE];
+
+ // Nettle expects the private key to be exactly
+ // ED25519_KEY_SIZE bytes long but OpenPGP allows leading
+ // zeros to be stripped.
+ // Padding has to be unconditionaly, otherwise we have a
+ // secret-dependant branch.
+ let missing = ed25519::ED25519_KEY_SIZE
+ .saturating_sub(scalar.value.len());
+ let mut sec = [0u8; ed25519::ED25519_KEY_SIZE];
+ sec[missing..].copy_from_slice(&scalar.value[..]);
+
+ let res = ed25519::sign(public, &sec[..], digest, &mut sig);
+ unsafe {
+ memsec::memzero(sec.as_mut_ptr(),
+ ed25519::ED25519_KEY_SIZE);
+ }
+ res?;
+
+ Ok(mpis::Signature::EdDSA {
+ r: MPI::new(&sig[..32]),
+ s: MPI::new(&sig[32..]),
+ })
+ },
+ _ => Err(
+ Error::UnsupportedEllipticCurve(curve.clone()).into()),
+ },
+
+ (ECDSA,
+ &PublicKey::ECDSA { ref curve, .. },
+ &mpis::SecretKey::ECDSA { ref scalar }) => {
+ let secret = match curve {
+ Curve::NistP256 =>
+ ecdsa::PrivateKey::new::<ecdsa::Secp256r1>(
+ &scalar.value)?,
+ Curve::NistP384 =>
+ ecdsa::PrivateKey::new::<ecdsa::Secp384r1>(
+ &scalar.value)?,
+ Curve::NistP521 =>
+ ecdsa::PrivateKey::new::<ecdsa::Secp521r1>(
+ &scalar.value)?,
+ _ =>
+ return Err(
+ Error::UnsupportedEllipticCurve(curve.clone())
+ .into()),
+ };
+
+ let sig = ecdsa::sign(&secret, digest, &mut rng);
+
+ Ok(mpis::Signature::ECDSA {
+ r: MPI::new(&sig.r()),
+ s: MPI::new(&sig.s()),
+ })
+ },
+
+ (pk_algo, _, _) => Err(Error::InvalidArgument(format!(
+ "unsupported combination of algorithm {:?}, key {:?}, \
+ and secret key {:?}",
+ pk_algo, self.public, self.secret)).into()),
+ }
+ }
+}
diff --git a/openpgp/src/crypto/mod.rs b/openpgp/src/crypto/mod.rs
index 300a5aeb..33f27078 100644
--- a/openpgp/src/crypto/mod.rs
+++ b/openpgp/src/crypto/mod.rs
@@ -20,7 +20,10 @@ pub mod mpis;
pub mod s2k;
pub(crate) mod symmetric;
-pub use self::asymmetric::Signer;
+pub use self::asymmetric::{
+ Signer,
+ KeyPair,
+};
/// Holds a session key.
///
diff --git a/openpgp/src/message/mod.rs b/openpgp/src/message/mod.rs
index c7be55ea..9c64f7d9 100644
--- a/openpgp/src/message/mod.rs
+++ b/openpgp/src/message/mod.rs
@@ -402,6 +402,7 @@ mod tests {
use SymmetricAlgorithm;
use PublicKeyAlgorithm;
use SignatureType;
+ use crypto::KeyPair;
use crypto::s2k::S2K;
use crypto::mpis::{Ciphertext, MPI};
use packet::Tag;
@@ -413,7 +414,6 @@ mod tests {
use packet::SEIP;
use packet::MDC;
use packet::key::SecretKey;
- use packet::signature::KeyPair;
use KeyID;
use Container;
diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs
index 22240259..ef040841 100644
--- a/openpgp/src/packet/signature/mod.rs
+++ b/openpgp/src/packet/signature/mod.rs
@@ -7,7 +7,7 @@ use constants::Curve;
use Error;
use Result;
use crypto::{
- mpis::{self, MPI},
+ mpis,
Signer,
};
use HashAlgorithm;
@@ -22,7 +22,7 @@ use packet;
use packet::signature::subpacket::SubpacketArea;
use serialize::Serialize;
-use nettle::{dsa, ecdsa, ed25519, Hash, rsa, Yarrow};
+use nettle::{dsa, ecdsa, ed25519, Hash, rsa};
use nettle::rsa::verify_digest_pkcs1;
#[cfg(test)]
@@ -214,150 +214,6 @@ impl Builder {
}
}
-/// A cryptographic key pair.
-pub struct KeyPair {
- public: Key,
- secret: mpis::SecretKey,
-}
-
-impl KeyPair {
- /// Creates a new key pair.
- pub fn new(public: Key, secret: mpis::SecretKey) -> Result<Self> {
- Ok(Self {
- public: public,
- secret: secret,
- })
- }
-}
-
-impl Signer for KeyPair {
- fn public(&self) -> &Key {
- &self.public
- }
-
- fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
- -> Result<mpis::Signature>
- {
- use PublicKeyAlgorithm::*;
- use crypto::mpis::PublicKey;
- use memsec;
-
- let mut rng = Yarrow::default();
-
- #[allow(deprecated)]
- match (self.public.pk_algo(), self.public.mpis(), &self.secret)
- {
- (RSASign,
- &PublicKey::RSA { ref e, ref n },
- &mpis::SecretKey::RSA { ref p, ref q, ref d, .. }) |
- (RSAEncryptSign,
- &PublicKey::RSA { ref e, ref n },
- &mpis::SecretKey::RSA { ref p, ref q, ref d, .. }) => {
- let public = rsa::PublicKey::new(&n.value, &e.value)?;
- let secret = rsa::PrivateKey::new(&d.value, &p.value,
- &q.value, Option::None)?;
-
- // The signature has the length of the modulus.
- let mut sig = vec![0u8; n.value.len()];
-
- // As described in [Section 5.2.2 and 5.2.3 of RFC 4880],
- // to verify the signature, we need to encode the
- // signature data in a PKCS1-v1.5 packet.
- //
- // [Section 5.2.2 and 5.2.3 of RFC 4880]:
- // https://tools.ietf.org/html/rfc4880#section-5.2.2
- rsa::sign_digest_pkcs1(&public, &secret, digest,
- hash_algo.oid()?,
- &mut rng, &mut sig)?;
-
- Ok(mpis::Signature::RSA {
- s: MPI::new(&sig),
- })
- },
-
- (DSA,
- &PublicKey::DSA { ref p, ref q, ref g, .. },
- &mpis::SecretKey::DSA { ref x }) => {
- let params = dsa::Params::new(&p.value, &q.value, &g.value);
- let secret = dsa::PrivateKey::new(&x.value);
-
- let sig = dsa::sign(&params, &secret, digest, &mut rng)?;
-
- Ok(mpis::Signature::DSA {
- r: MPI::new(&sig.r()),
- s: MPI::new(&sig.s()),
- })
- },
-
- (EdDSA,
- &PublicKey::EdDSA { ref curve, ref q },
- &mpis::SecretKey::EdDSA { ref scalar }) => match curve {
- Curve::Ed25519 => {
- let public = q.decode_point(&Curve::Ed25519)?.0;
-
- let mut sig = vec![0; ed25519::ED25519_SIGNATURE_SIZE];
-
- // Nettle expects the private key to be exactly
- // ED25519_KEY_SIZE bytes long but OpenPGP allows leading
- // zeros to be stripped.
- // Padding has to be unconditionaly, otherwise we have a
- // secret-dependant branch.
- let missing = ed25519::ED25519_KEY_SIZE
- .saturating_sub(scalar.value.len());
- let mut sec = [0u8; ed25519::ED25519_KEY_SIZE];
- sec[missing..].copy_from_slice(&scalar.value[..]);
-
- let res = ed25519::sign(public, &sec[..], digest, &mut sig);
- unsafe {
- memsec::memzero(sec.as_mut_ptr(),
- ed25519::ED25519_KEY_SIZE);
- }
- res?;
-
- Ok(mpis::Signature::EdDSA {
- r: MPI::new(&sig[..32]),
- s: MPI::new(&sig[32..]),
- })
- },
- _ => Err(
- Error::UnsupportedEllipticCurve(curve.clone()).into()),
- },
-
- (ECDSA,
- &PublicKey::ECDSA { ref curve, .. },
- &mpis::SecretKey::ECDSA { ref scalar }) => {
- let secret = match curve {
- Curve::NistP256 =>
- ecdsa::PrivateKey::new::<ecdsa::Secp256r1>(
- &scalar.value)?,
- Curve::NistP384 =>
- ecdsa::PrivateKey::new::<ecdsa::Secp384r1>(
- &scalar.value)?,
- Curve::NistP521 =>
- ecdsa::PrivateKey::new::<ecdsa::Secp521r1>(
- &scalar.value)?,
- _ =>
- return Err(
- Error::UnsupportedEllipticCurve(curve.clone())
- .into()),
- };
-
- let sig = ecdsa::sign(&secret, digest, &mut rng);
-
- Ok(mpis::Signature::ECDSA {
- r: MPI::new(&sig.r()),
- s: MPI::new(&sig.s()),
- })
- },
-
- (pk_algo, _, _) => Err(Error::InvalidArgument(format!(
- "unsupported combination of algorithm {:?}, key {:?}, \
- and secret key {:?}",
- pk_algo, self.public, self.secret)).into()),
- }
- }
-}
-
impl From<Signature> for Builder {
fn from(sig: Signature) -> Self {
sig.fields
@@ -904,7 +760,10 @@ impl From<Signature> for Packet {
#[cfg(test)]
mod test {
+ use nettle::Yarrow;
use super::*;
+ use crypto::KeyPair;
+ use crypto::mpis::MPI;
use TPK;
use parse::Parse;
diff --git a/openpgp/src/packet/signature/subpacket.rs b/openpgp/src/packet/signature/subpacket.rs
index 90b48b3c..6506cca1 100644
--- a/openpgp/src/packet/signature/subpacket.rs
+++ b/openpgp/src/packet/signature/subpacket.rs
@@ -2238,7 +2238,7 @@ impl signature::Builder {
#[test]
fn accessors() {
use packet::key::SecretKey;
- use packet::signature::KeyPair;
+ use crypto::KeyPair;
let pk_algo = PublicKeyAlgorithm::EdDSA;
let hash_algo = HashAlgorithm::SHA512;
diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs
index 9deebe65..503ad11c 100644
--- a/openpgp/src/serialize/stream.rs
+++ b/openpgp/src/serialize/stream.rs
@@ -16,6 +16,7 @@ use time;
use nettle::{Hash, Yarrow};
use {
+ crypto::KeyPair,
Error,
Fingerprint,
HashAlgorithm,
@@ -31,7 +32,7 @@ use {
crypto::SessionKey,
packet::SKESK4,
packet::SKESK5,
- packet::signature::{self, Signature, KeyPair},
+ packet::signature::{self, Signature},
packet::Tag,
TPK,
};
diff --git a/openpgp/src/tpk/builder.rs b/openpgp/src/tpk/builder.rs
index 6a1e5c03..fa145720 100644
--- a/openpgp/src/tpk/builder.rs
+++ b/openpgp/src/tpk/builder.rs
@@ -3,9 +3,10 @@ use packet::{Features, KeyFlags};
use packet::Key;
use Result;
use packet::UserID;
+use crypto::KeyPair;
use SymmetricAlgorithm;
use HashAlgorithm;
-use packet::signature::{self, Signature, KeyPair};
+use packet::signature::{self, Signature};
use TPK;
use PublicKeyAlgorithm;
use Error;
diff --git a/openpgp/src/tpk/mod.rs b/openpgp/src/tpk/mod.rs
index 5203940a..34788c24 100644
--- a/openpgp/src/tpk/mod.rs
+++ b/openpgp/src/tpk/mod.rs
@@ -11,6 +11,7 @@ use time;
use failure;
use {
+ crypto::KeyPair,
Error,
Result,
RevocationStatus,
@@ -18,7 +19,7 @@ use {
HashAlgorithm,
packet::Tag,
packet::key::SecretKey,
- packet::signature::{self, Signature, KeyPair},
+ packet::signature::{self, Signature},
packet::Key,
packet::UserID,
packet::UserAttribute,
diff --git a/openpgp/src/tsk.rs b/openpgp/src/tsk.rs
index 05734be8..d9ec86bf 100644
--- a/openpgp/src/tsk.rs
+++ b/openpgp/src/tsk.rs
@@ -9,8 +9,9 @@ use {
Error,
};
+use crypto::KeyPair;
use packet::{
- signature::{Signature, KeyPair},
+ signature::Signature,
Tag,
UserID,
Key,