summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-05-12 18:32:21 +0200
committerJustus Winter <justus@sequoia-pgp.org>2023-05-22 12:00:10 +0200
commit995a7cff7fa0cd3273d8dad8080f6b50de79eaa9 (patch)
treece5b429214dfc3ceb5bce5c9d39f58403ebb7557
parentd7ba06e299e3f8f76a744d9728b86c80d05f19da (diff)
openpgp: Deduplicate EdDSA signing.
-rw-r--r--openpgp/src/crypto/asymmetric.rs25
-rw-r--r--openpgp/src/crypto/backend/botan/asymmetric.rs24
-rw-r--r--openpgp/src/crypto/backend/cng/asymmetric.rs42
-rw-r--r--openpgp/src/crypto/backend/nettle/asymmetric.rs26
-rw-r--r--openpgp/src/crypto/backend/openssl/asymmetric.rs24
-rw-r--r--openpgp/src/crypto/backend/rust/asymmetric.rs38
6 files changed, 23 insertions, 156 deletions
diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs
index 936f292c..6420048d 100644
--- a/openpgp/src/crypto/asymmetric.rs
+++ b/openpgp/src/crypto/asymmetric.rs
@@ -3,9 +3,9 @@
use crate::packet::{self, key, Key};
use crate::crypto::SessionKey;
use crate::crypto::mpi;
-use crate::types::HashAlgorithm;
+use crate::types::{Curve, HashAlgorithm, PublicKeyAlgorithm};
-use crate::Result;
+use crate::{Error, Result};
/// Creates a signature.
///
@@ -218,9 +218,28 @@ impl Signer for KeyPair {
fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
-> Result<mpi::Signature>
{
+ use crate::crypto::backend::{Backend, interface::Asymmetric};
+
self.secret().map(|secret| {
- #[allow(clippy::match_single_binding)]
match (self.public().pk_algo(), self.public().mpis(), secret) {
+ (PublicKeyAlgorithm::EdDSA,
+ mpi::PublicKey::EdDSA { curve, q },
+ mpi::SecretKeyMaterial::EdDSA { scalar }) => match curve {
+ Curve::Ed25519 => {
+ let public = q.decode_point(&Curve::Ed25519)?.0
+ .try_into()?;
+ let secret = scalar.value_padded(32);
+ let sig =
+ Backend::ed25519_sign(&secret, &public, digest)?;
+ Ok(mpi::Signature::EdDSA {
+ r: mpi::MPI::new(&sig[..32]),
+ s: mpi::MPI::new(&sig[32..]),
+ })
+ },
+ _ => Err(
+ Error::UnsupportedEllipticCurve(curve.clone()).into()),
+ },
+
(_algo, _public, secret) =>
self.sign_backend(secret, hash_algo, digest),
}
diff --git a/openpgp/src/crypto/backend/botan/asymmetric.rs b/openpgp/src/crypto/backend/botan/asymmetric.rs
index 66e64b35..d9f989ad 100644
--- a/openpgp/src/crypto/backend/botan/asymmetric.rs
+++ b/openpgp/src/crypto/backend/botan/asymmetric.rs
@@ -185,30 +185,6 @@ impl KeyPair {
})
},
- (EdDSA,
- PublicKey::EdDSA { curve, .. },
- mpi::SecretKeyMaterial::EdDSA { scalar }) => match curve {
- Curve::Ed25519 => {
- let size = 32;
- let scalar = scalar.value_padded(size);
- let secret = Privkey::load_ed25519(&scalar)?;
- let sig = secret.sign(digest, "", &mut rng)?;
-
- if sig.len() != size * 2 {
- return Err(Error::MalformedMPI(
- format!("Expected signature with length {}, got {}",
- size * 2, sig.len())).into());
- }
-
- Ok(mpi::Signature::EdDSA {
- r: MPI::new(&sig[..size]),
- s: MPI::new(&sig[size..]),
- })
- },
- _ => Err(
- Error::UnsupportedEllipticCurve(curve.clone()).into()),
- },
-
(ECDSA,
PublicKey::ECDSA { curve, .. },
mpi::SecretKeyMaterial::ECDSA { scalar }) => {
diff --git a/openpgp/src/crypto/backend/cng/asymmetric.rs b/openpgp/src/crypto/backend/cng/asymmetric.rs
index f2a9e241..91c7700c 100644
--- a/openpgp/src/crypto/backend/cng/asymmetric.rs
+++ b/openpgp/src/crypto/backend/cng/asymmetric.rs
@@ -238,47 +238,7 @@ impl KeyPair {
s: mpi::MPI::new(s),
}
},
- (
- PublicKeyAlgorithm::EdDSA,
- mpi::PublicKey::EdDSA { curve, q },
- mpi::SecretKeyMaterial::EdDSA { scalar },
- ) => match curve {
- Curve::Ed25519 => {
- // CNG doesn't support EdDSA, use ed25519-dalek instead
- use ed25519_dalek::{Keypair, Signer};
- use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH};
-
- let (public, ..) = q.decode_point(&Curve::Ed25519)?;
- // MPI::decode_point ensures we got the right length.
- assert_eq!(public.len(), PUBLIC_KEY_LENGTH);
-
- // It's expected for the private key to be exactly
- // SECRET_KEY_LENGTH bytes long but OpenPGP allows leading
- // zeros to be stripped.
- // Padding has to be unconditional; otherwise we have a
- // secret-dependent branch.
- let mut keypair = Protected::from(
- vec![0u8; SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH]
- );
- keypair[..SECRET_KEY_LENGTH]
- .copy_from_slice(
- &scalar.value_padded(SECRET_KEY_LENGTH));
- keypair[SECRET_KEY_LENGTH..]
- .copy_from_slice(&public);
- let pair = Keypair::from_bytes(&keypair).unwrap();
-
- let sig = pair.sign(digest).to_bytes();
-
- // https://tools.ietf.org/html/rfc8032#section-5.1.6
- let (r, s) = sig.split_at(sig.len() / 2);
- mpi::Signature::EdDSA {
- r: mpi::MPI::new(r),
- s: mpi::MPI::new(s),
- }
- },
- _ => return Err(
- Error::UnsupportedEllipticCurve(curve.clone()).into()),
- },
+
(PublicKeyAlgorithm::DSA,
mpi:: PublicKey::DSA { y, p, q, g },
mpi::SecretKeyMaterial::DSA { x },
diff --git a/openpgp/src/crypto/backend/nettle/asymmetric.rs b/openpgp/src/crypto/backend/nettle/asymmetric.rs
index 16c1d3d2..06dcf2aa 100644
--- a/openpgp/src/crypto/backend/nettle/asymmetric.rs
+++ b/openpgp/src/crypto/backend/nettle/asymmetric.rs
@@ -130,32 +130,6 @@ impl KeyPair {
})
},
- (EdDSA,
- &PublicKey::EdDSA { ref curve, ref q },
- &mpi::SecretKeyMaterial::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 unconditional; otherwise we have a
- // secret-dependent branch.
- let sec = scalar.value_padded(ed25519::ED25519_KEY_SIZE);
-
- ed25519::sign(public, &sec[..], digest, &mut sig)?;
-
- Ok(mpi::Signature::EdDSA {
- r: MPI::new(&sig[..ed25519::ED25519_KEY_SIZE]),
- s: MPI::new(&sig[ed25519::ED25519_KEY_SIZE..]),
- })
- },
- _ => Err(
- Error::UnsupportedEllipticCurve(curve.clone()).into()),
- },
-
(ECDSA,
&PublicKey::ECDSA { ref curve, .. },
&mpi::SecretKeyMaterial::ECDSA { ref scalar }) => {
diff --git a/openpgp/src/crypto/backend/openssl/asymmetric.rs b/openpgp/src/crypto/backend/openssl/asymmetric.rs
index b5e3ab02..396ab0f1 100644
--- a/openpgp/src/crypto/backend/openssl/asymmetric.rs
+++ b/openpgp/src/crypto/backend/openssl/asymmetric.rs
@@ -222,30 +222,6 @@ impl KeyPair {
})
}
- (
- EdDSA,
- mpi::PublicKey::EdDSA { curve, .. },
- mpi::SecretKeyMaterial::EdDSA { scalar },
- ) => match curve {
- Curve::Ed25519 => {
- let scalar = scalar.value_padded(32);
-
- let key =
- PKey::private_key_from_raw_bytes(&scalar, openssl::pkey::Id::ED25519)?;
-
- let mut signer = OpenSslSigner::new_without_digest(&key)?;
- let signature = signer.sign_oneshot_to_vec(digest)?;
-
- // https://tools.ietf.org/html/rfc8032#section-5.1.6
- let (r, s) = signature.split_at(signature.len() / 2);
- Ok(mpi::Signature::EdDSA {
- r: r.to_vec().into(),
- s: s.to_vec().into(),
- })
- }
- _ => Err(crate::Error::UnsupportedEllipticCurve(curve.clone()).into()),
- },
-
(pk_algo, _, _) => Err(crate::Error::InvalidOperation(format!(
"unsupported combination of algorithm {:?}, key {:?}, \
and secret key {:?} by OpenSSL backend",
diff --git a/openpgp/src/crypto/backend/rust/asymmetric.rs b/openpgp/src/crypto/backend/rust/asymmetric.rs
index fafac2b1..d6729e3d 100644
--- a/openpgp/src/crypto/backend/rust/asymmetric.rs
+++ b/openpgp/src/crypto/backend/rust/asymmetric.rs
@@ -219,44 +219,6 @@ impl KeyPair {
_ => Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
},
- (EdDSA,
- mpi::PublicKey::EdDSA { curve, q },
- mpi::SecretKeyMaterial::EdDSA { scalar }) => match curve
- {
- Curve::Ed25519 => {
- use ed25519_dalek::{Keypair, Signer};
- use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH};
-
- let (public, ..) = q.decode_point(&Curve::Ed25519)?;
- assert_eq!(public.len(), PUBLIC_KEY_LENGTH);
-
- // It's expected for the private key to be exactly
- // SECRET_KEY_LENGTH bytes long but OpenPGP allows leading
- // zeros to be stripped.
- // Padding has to be unconditional; otherwise we have a
- // secret-dependent branch.
- let mut keypair = Protected::from(
- vec![0u8; SECRET_KEY_LENGTH + PUBLIC_KEY_LENGTH]
- );
- keypair.as_mut()[..SECRET_KEY_LENGTH]
- .copy_from_slice(
- &scalar.value_padded(SECRET_KEY_LENGTH));
- keypair.as_mut()[SECRET_KEY_LENGTH..]
- .copy_from_slice(public);
- let pair = Keypair::from_bytes(&keypair)?;
-
- let sig = pair.sign(digest).to_bytes();
-
- // https://tools.ietf.org/html/rfc8032#section-5.1.6
- let (r, s) = sig.split_at(sig.len() / 2);
- Ok(mpi::Signature::EdDSA {
- r: mpi::MPI::new(r),
- s: mpi::MPI::new(s),
- })
- },
- _ => Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
- },
-
(pk_algo, _, _) => {
Err(Error::InvalidOperation(format!(
"unsupported combination of algorithm {:?}, key {:?}, \