diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2023-05-12 18:32:21 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2023-05-22 12:00:10 +0200 |
commit | 995a7cff7fa0cd3273d8dad8080f6b50de79eaa9 (patch) | |
tree | ce5b429214dfc3ceb5bce5c9d39f58403ebb7557 | |
parent | d7ba06e299e3f8f76a744d9728b86c80d05f19da (diff) |
openpgp: Deduplicate EdDSA signing.
-rw-r--r-- | openpgp/src/crypto/asymmetric.rs | 25 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/botan/asymmetric.rs | 24 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/cng/asymmetric.rs | 42 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle/asymmetric.rs | 26 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/openssl/asymmetric.rs | 24 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust/asymmetric.rs | 38 |
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 {:?}, \ |