summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWiktor Kwapisiewicz <wiktor@metacode.biz>2023-03-23 09:59:46 +0100
committerWiktor Kwapisiewicz <wiktor@metacode.biz>2023-03-23 14:22:59 +0100
commiteab194fceb8acbe436ad6ab60f89a957f2e61bd2 (patch)
tree9430f02db8e9d9be07a8a9ba5ac9d0a9eae5837a
parentb1d8527d1fb56e2d97c8a285d2ff1dc1e931d4c6 (diff)
openpgp: Move `Key4::import_secret_cv25519` into common code.
- Most of the logic in this function is the same across backends. - Introduce `Key4::derive_cv25519_public_key` that does backend-specific derivation. - Fixes https://gitlab.com/sequoia-pgp/sequoia/-/issues/958
-rw-r--r--openpgp/src/crypto/backend/botan/asymmetric.rs34
-rw-r--r--openpgp/src/crypto/backend/cng/asymmetric.rs47
-rw-r--r--openpgp/src/crypto/backend/nettle/asymmetric.rs39
-rw-r--r--openpgp/src/crypto/backend/openssl/asymmetric.rs44
-rw-r--r--openpgp/src/crypto/backend/rust/asymmetric.rs38
-rw-r--r--openpgp/src/packet/key.rs37
6 files changed, 53 insertions, 186 deletions
diff --git a/openpgp/src/crypto/backend/botan/asymmetric.rs b/openpgp/src/crypto/backend/botan/asymmetric.rs
index bf9b53c6..51ed2edc 100644
--- a/openpgp/src/crypto/backend/botan/asymmetric.rs
+++ b/openpgp/src/crypto/backend/botan/asymmetric.rs
@@ -29,7 +29,6 @@ use crate::{
Curve,
HashAlgorithm,
PublicKeyAlgorithm,
- SymmetricAlgorithm,
},
};
@@ -392,40 +391,11 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
impl<R> Key4<SecretParts, R>
where R: key::KeyRole,
{
- /// Creates a new OpenPGP secret key packet for an existing X25519 key.
- ///
- /// The ECDH key will use hash algorithm `hash` and symmetric
- /// algorithm `sym`. If one or both are `None` secure defaults
- /// will be used. The key will have it's creation date set to
- /// `ctime` or the current time if `None` is given.
- pub fn import_secret_cv25519<H, S, T>(private_key: &[u8],
- hash: H, sym: S, ctime: T)
- -> Result<Self> where H: Into<Option<HashAlgorithm>>,
- S: Into<Option<SymmetricAlgorithm>>,
- T: Into<Option<SystemTime>>
+ pub(crate) fn derive_cv25519_public_key(private_key: &Protected) -> Result<[u8; 32]>
{
let secret = Privkey::load_x25519(private_key)?;
- let public = secret.pubkey()?.get_x25519_key()?;
- let mut secret = secret.get_x25519_key()?;
-
- // OpenPGP stores the secret in reverse order.
- secret.reverse();
- use crate::crypto::ecdh;
- Self::with_secret(
- ctime.into().unwrap_or_else(crate::now),
- PublicKeyAlgorithm::ECDH,
- mpi::PublicKey::ECDH {
- curve: Curve::Cv25519,
- hash: hash.into().unwrap_or_else(
- || ecdh::default_ecdh_kdf_hash(&Curve::Cv25519)),
- sym: sym.into().unwrap_or_else(
- || ecdh::default_ecdh_kek_cipher(&Curve::Cv25519)),
- q: MPI::new_compressed_point(&public),
- },
- mpi::SecretKeyMaterial::ECDH {
- scalar: secret.into(),
- }.into())
+ Ok(<[u8; 32]>::try_from(&secret.pubkey()?.get_x25519_key()?[..])?)
}
/// Creates a new OpenPGP secret key packet for an existing Ed25519 key.
diff --git a/openpgp/src/crypto/backend/cng/asymmetric.rs b/openpgp/src/crypto/backend/cng/asymmetric.rs
index d0a5fd9b..1eb110af 100644
--- a/openpgp/src/crypto/backend/cng/asymmetric.rs
+++ b/openpgp/src/crypto/backend/cng/asymmetric.rs
@@ -13,7 +13,7 @@ use crate::crypto::SessionKey;
use crate::crypto::{pad, pad_at_least, pad_truncating};
use crate::packet::key::{Key4, SecretParts};
use crate::packet::{key, Key};
-use crate::types::{PublicKeyAlgorithm, SymmetricAlgorithm};
+use crate::types::PublicKeyAlgorithm;
use crate::types::{Curve, HashAlgorithm};
use num_bigint_dig::{traits::ModInverse, BigInt, BigUint};
@@ -684,22 +684,7 @@ impl<R> Key4<SecretParts, R>
where
R: key::KeyRole,
{
- /// Creates a new OpenPGP secret key packet for an existing X25519 key.
- ///
- /// The ECDH key will use hash algorithm `hash` and symmetric
- /// algorithm `sym`. If one or both are `None` secure defaults
- /// will be used. The key will have its creation date set to
- /// `ctime` or the current time if `None` is given.
- pub fn import_secret_cv25519<H, S, T>(
- private_key: &[u8],
- hash: H,
- sym: S,
- ctime: T,
- ) -> Result<Self>
- where
- H: Into<Option<HashAlgorithm>>,
- S: Into<Option<SymmetricAlgorithm>>,
- T: Into<Option<SystemTime>>,
+ pub(crate) fn derive_cv25519_public_key(private_key: &Protected) -> Result<[u8; 32]>
{
use cng::asymmetric::{AsymmetricAlgorithm, AsymmetricAlgorithmId, Ecdh, Private};
use cng::asymmetric::{AsymmetricKey, Export};
@@ -712,33 +697,7 @@ where
&provider,
private_key
)?;
- let blob = key.export()?;
-
- // Mark MPI as compressed point with 0x40 prefix. See
- // https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-07#section-13.2.
- let mut public = [0u8; 1 + CURVE25519_SIZE];
- public[0] = 0x40;
- public[1..].copy_from_slice(blob.x());
-
- // Reverse the scalar. See
- // https://lists.gnupg.org/pipermail/gnupg-devel/2018-February/033437.html.
- let mut private = blob.d().to_vec();
- private.reverse();
-
- use crate::crypto::ecdh;
- Self::with_secret(
- ctime.into().unwrap_or_else(crate::now),
- PublicKeyAlgorithm::ECDH,
- mpi::PublicKey::ECDH {
- curve: Curve::Cv25519,
- hash: hash.into().unwrap_or_else(
- || ecdh::default_ecdh_kdf_hash(&Curve::Cv25519)),
- sym: sym.into().unwrap_or_else(
- || ecdh::default_ecdh_kek_cipher(&Curve::Cv25519)),
- q: mpi::MPI::new(&public),
- },
- mpi::SecretKeyMaterial::ECDH { scalar: private.into() }.into()
- )
+ Ok(<[u8; 32]>::try_from(&key.export()?.x()[..])?)
}
/// Creates a new OpenPGP secret key packet for an existing Ed25519 key.
diff --git a/openpgp/src/crypto/backend/nettle/asymmetric.rs b/openpgp/src/crypto/backend/nettle/asymmetric.rs
index 0d908c55..54fa31d2 100644
--- a/openpgp/src/crypto/backend/nettle/asymmetric.rs
+++ b/openpgp/src/crypto/backend/nettle/asymmetric.rs
@@ -319,45 +319,16 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
use std::time::SystemTime;
use crate::crypto::mem::Protected;
use crate::packet::key::{Key4, SecretParts};
-use crate::types::{PublicKeyAlgorithm, SymmetricAlgorithm};
+use crate::types::PublicKeyAlgorithm;
impl<R> Key4<SecretParts, R>
where R: key::KeyRole,
{
-
- /// Creates a new OpenPGP secret key packet for an existing X25519 key.
- ///
- /// The ECDH key will use hash algorithm `hash` and symmetric
- /// algorithm `sym`. If one or both are `None` secure defaults
- /// will be used. The key will have it's creation date set to
- /// `ctime` or the current time if `None` is given.
- pub fn import_secret_cv25519<H, S, T>(private_key: &[u8],
- hash: H, sym: S, ctime: T)
- -> Result<Self> where H: Into<Option<HashAlgorithm>>,
- S: Into<Option<SymmetricAlgorithm>>,
- T: Into<Option<SystemTime>>
+ pub(crate) fn derive_cv25519_public_key(private_key: &Protected) -> Result<[u8; 32]>
{
- let mut public_key = [0; curve25519::CURVE25519_SIZE];
- curve25519::mul_g(&mut public_key, private_key).unwrap();
-
- let mut private_key = Vec::from(private_key);
- private_key.reverse();
-
- use crate::crypto::ecdh;
- Self::with_secret(
- ctime.into().unwrap_or_else(crate::now),
- PublicKeyAlgorithm::ECDH,
- mpi::PublicKey::ECDH {
- curve: Curve::Cv25519,
- hash: hash.into().unwrap_or_else(
- || ecdh::default_ecdh_kdf_hash(&Curve::Cv25519)),
- sym: sym.into().unwrap_or_else(
- || ecdh::default_ecdh_kek_cipher(&Curve::Cv25519)),
- q: MPI::new_compressed_point(&public_key),
- },
- mpi::SecretKeyMaterial::ECDH {
- scalar: private_key.into(),
- }.into())
+ let mut public_key = [0; ed25519::ED25519_KEY_SIZE];
+ curve25519::mul_g(&mut public_key, private_key)?;
+ Ok(public_key)
}
/// Creates a new OpenPGP secret key packet for an existing Ed25519 key.
diff --git a/openpgp/src/crypto/backend/openssl/asymmetric.rs b/openpgp/src/crypto/backend/openssl/asymmetric.rs
index 07d0c7f4..1d586585 100644
--- a/openpgp/src/crypto/backend/openssl/asymmetric.rs
+++ b/openpgp/src/crypto/backend/openssl/asymmetric.rs
@@ -7,7 +7,6 @@ use crate::crypto::mem::Protected;
use crate::crypto::SessionKey;
use crate::packet::key::{Key4, SecretParts};
use crate::packet::{key, Key};
-use crate::types::SymmetricAlgorithm;
use crate::types::{Curve, HashAlgorithm, PublicKeyAlgorithm};
use std::convert::{TryFrom, TryInto};
use std::time::SystemTime;
@@ -391,48 +390,11 @@ impl<R> Key4<SecretParts, R>
where
R: key::KeyRole,
{
- /// Creates a new OpenPGP secret key packet for an existing X25519 key.
- ///
- /// The ECDH key will use hash algorithm `hash` and symmetric
- /// algorithm `sym`. If one or both are `None` secure defaults
- /// will be used. The key will have it's creation date set to
- /// `ctime` or the current time if `None` is given.
- pub fn import_secret_cv25519<H, S, T>(
- private_key: &[u8],
- hash: H,
- sym: S,
- ctime: T,
- ) -> Result<Self>
- where
- H: Into<Option<HashAlgorithm>>,
- S: Into<Option<SymmetricAlgorithm>>,
- T: Into<Option<SystemTime>>,
+ pub(crate) fn derive_cv25519_public_key(private_key: &Protected) -> Result<[u8; 32]>
{
let key = PKey::private_key_from_raw_bytes(private_key, openssl::pkey::Id::X25519)?;
- let public_key = key.raw_public_key()?;
-
- let mut private_key: Protected = key.raw_private_key().map(|key| key.into())?;
- private_key.reverse();
-
- use crate::crypto::ecdh;
- Self::with_secret(
- ctime.into().unwrap_or_else(crate::now),
- PublicKeyAlgorithm::ECDH,
- mpi::PublicKey::ECDH {
- curve: Curve::Cv25519,
- hash: hash
- .into()
- .unwrap_or_else(|| ecdh::default_ecdh_kdf_hash(&Curve::Cv25519)),
- sym: sym
- .into()
- .unwrap_or_else(|| ecdh::default_ecdh_kek_cipher(&Curve::Cv25519)),
- q: MPI::new_compressed_point(&public_key),
- },
- mpi::SecretKeyMaterial::ECDH {
- scalar: private_key.into(),
- }
- .into(),
- )
+ let public = key.raw_public_key()?;
+ Ok(<[u8; 32]>::try_from(&public[..])?)
}
/// Creates a new OpenPGP secret key packet for an existing Ed25519 key.
diff --git a/openpgp/src/crypto/backend/rust/asymmetric.rs b/openpgp/src/crypto/backend/rust/asymmetric.rs
index 1ee32fc2..4090fdbb 100644
--- a/openpgp/src/crypto/backend/rust/asymmetric.rs
+++ b/openpgp/src/crypto/backend/rust/asymmetric.rs
@@ -19,7 +19,7 @@ use crate::crypto::SessionKey;
use crate::crypto::pad_truncating;
use crate::packet::{key, Key};
use crate::packet::key::{Key4, SecretParts};
-use crate::types::{Curve, HashAlgorithm, PublicKeyAlgorithm, SymmetricAlgorithm};
+use crate::types::{Curve, HashAlgorithm, PublicKeyAlgorithm};
const CURVE25519_SIZE: usize = 32;
@@ -345,42 +345,12 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
impl<R> Key4<SecretParts, R>
where R: key::KeyRole,
{
-
- /// Creates a new OpenPGP secret key packet for an existing X25519 key.
- ///
- /// The ECDH key will use hash algorithm `hash` and symmetric
- /// algorithm `sym`. If one or both are `None` secure defaults
- /// will be used. The key will have it's creation date set to
- /// `ctime` or the current time if `None` is given.
- pub fn import_secret_cv25519<H, S, T>(private_key: &[u8],
- hash: H, sym: S, ctime: T)
- -> Result<Self> where H: Into<Option<HashAlgorithm>>,
- S: Into<Option<SymmetricAlgorithm>>,
- T: Into<Option<SystemTime>>
+ pub(crate) fn derive_cv25519_public_key(private_key: &Protected) -> Result<[u8; 32]>
{
use x25519_dalek::{PublicKey, StaticSecret};
- let secret = StaticSecret::from(<[u8; 32]>::try_from(private_key)?);
- let public_key = PublicKey::from(&secret);
-
- let mut private_key = Vec::from(private_key);
- private_key.reverse();
-
- use crate::crypto::ecdh;
- Self::with_secret(
- ctime.into().unwrap_or_else(crate::now),
- PublicKeyAlgorithm::ECDH,
- mpi::PublicKey::ECDH {
- curve: Curve::Cv25519,
- hash: hash.into().unwrap_or_else(
- || ecdh::default_ecdh_kdf_hash(&Curve::Cv25519)),
- sym: sym.into().unwrap_or_else(
- || ecdh::default_ecdh_kek_cipher(&Curve::Cv25519)),
- q: MPI::new_compressed_point(&*public_key.as_bytes()),
- },
- mpi::SecretKeyMaterial::ECDH {
- scalar: private_key.into(),
- }.into())
+ let secret = StaticSecret::from(<[u8; 32]>::try_from(&private_key[..])?);
+ Ok(*PublicKey::from(&secret).as_bytes())
}
/// Creates a new OpenPGP secret key packet for an existing Ed25519 key.
diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs
index 148061d8..a6079f40 100644
--- a/openpgp/src/packet/key.rs
+++ b/openpgp/src/packet/key.rs
@@ -91,7 +91,7 @@ use quickcheck::{Arbitrary, Gen};
use crate::Error;
use crate::cert::prelude::*;
-use crate::crypto::{self, mem, mpi, hash::{Hash, Digest}};
+use crate::crypto::{self, mem::{self, Protected}, mpi, hash::{Hash, Digest}};
use crate::packet;
use crate::packet::prelude::*;
use crate::PublicKeyAlgorithm;
@@ -1053,6 +1053,41 @@ impl<R> Key4<SecretParts, R>
r: std::marker::PhantomData,
})
}
+
+ /// Creates a new OpenPGP secret key packet for an existing X25519 key.
+ ///
+ /// The ECDH key will use hash algorithm `hash` and symmetric
+ /// algorithm `sym`. If one or both are `None` secure defaults
+ /// will be used. The key will have it's creation date set to
+ /// `ctime` or the current time if `None` is given.
+ pub fn import_secret_cv25519<H, S, T>(private_key: &[u8],
+ hash: H, sym: S, ctime: T)
+ -> Result<Self> where H: Into<Option<HashAlgorithm>>,
+ S: Into<Option<SymmetricAlgorithm>>,
+ T: Into<Option<std::time::SystemTime>>
+ {
+ let mut private_key = Protected::from(private_key);
+
+ let public_key = Self::derive_cv25519_public_key(&private_key)?;
+
+ private_key.reverse();
+
+ use crate::crypto::ecdh;
+ Self::with_secret(
+ ctime.into().unwrap_or_else(crate::now),
+ PublicKeyAlgorithm::ECDH,
+ mpi::PublicKey::ECDH {
+ curve: Curve::Cv25519,
+ hash: hash.into().unwrap_or_else(
+ || ecdh::default_ecdh_kdf_hash(&Curve::Cv25519)),
+ sym: sym.into().unwrap_or_else(
+ || ecdh::default_ecdh_kek_cipher(&Curve::Cv25519)),
+ q: mpi::MPI::new_compressed_point(&public_key),
+ },
+ mpi::SecretKeyMaterial::ECDH {
+ scalar: private_key.into(),
+ }.into())
+ }
}
impl<P, R> Key4<P, R>