summaryrefslogtreecommitdiffstats
path: root/openpgp/src/packet/key.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/packet/key.rs')
-rw-r--r--openpgp/src/packet/key.rs136
1 files changed, 135 insertions, 1 deletions
diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs
index 89a02ad4..d37b6d93 100644
--- a/openpgp/src/packet/key.rs
+++ b/openpgp/src/packet/key.rs
@@ -748,11 +748,71 @@ impl<P, R> Key<P, R>
{
/// Encrypts the given data with this key.
pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
+ use crate::crypto::ecdh::aes_key_wrap;
+ use crate::crypto::backend::{Backend, interface::{Asymmetric, Kdf}};
use PublicKeyAlgorithm::*;
#[allow(deprecated, non_snake_case)]
+ #[allow(clippy::erasing_op, clippy::identity_op)]
match self.pk_algo() {
- RSASign | DSA | ECDSA | EdDSA =>
+ X25519 =>
+ if let mpi::PublicKey::X25519 { u: U } = self.mpis()
+ {
+ // Generate an ephemeral key pair {v, V=vG}
+ let (v, V) = Backend::x25519_generate_key()?;
+
+ // Compute the shared point S = vU;
+ let S = Backend::x25519_shared_point(&v, U)?;
+
+ // Compute the wrap key.
+ let wrap_algo = SymmetricAlgorithm::AES128;
+ let mut ikm: SessionKey = vec![0; 32 + 32 + 32].into();
+ ikm[0 * 32..1 * 32].copy_from_slice(&V[..]);
+ ikm[1 * 32..2 * 32].copy_from_slice(&U[..]);
+ ikm[2 * 32..3 * 32].copy_from_slice(&S[..]);
+ let mut kek = vec![0; wrap_algo.key_size()?].into();
+ Backend::hkdf_sha256(&ikm, None, b"OpenPGP X25519", &mut kek)?;
+
+ let esk = aes_key_wrap(wrap_algo, kek.as_protected(),
+ data.as_protected())?;
+ Ok(mpi::Ciphertext::X25519 {
+ e: Box::new(V),
+ key: esk.into(),
+ })
+ } else {
+ Err(Error::MalformedPacket(format!(
+ "Key: Expected X25519 public key, got {:?}", self.mpis())).into())
+ },
+
+ X448 =>
+ if let mpi::PublicKey::X448 { u: U } = self.mpis()
+ {
+ let (v, V) = Backend::x448_generate_key()?;
+
+ // Compute the shared point S = vU;
+ let S = Backend::x448_shared_point(&v, U)?;
+
+ // Compute the wrap key.
+ let wrap_algo = SymmetricAlgorithm::AES256;
+ let mut ikm: SessionKey = vec![0; 56 + 56 + 56].into();
+ ikm[0 * 56..1 * 56].copy_from_slice(&V[..]);
+ ikm[1 * 56..2 * 56].copy_from_slice(&U[..]);
+ ikm[2 * 56..3 * 56].copy_from_slice(&S[..]);
+ let mut kek = vec![0; wrap_algo.key_size()?].into();
+ Backend::hkdf_sha256(&ikm, None, b"OpenPGP X448", &mut kek)?;
+
+ let esk = aes_key_wrap(wrap_algo, kek.as_protected(),
+ data.as_protected())?;
+ Ok(mpi::Ciphertext::X448 {
+ e: Box::new(V),
+ key: esk.into(),
+ })
+ } else {
+ Err(Error::MalformedPacket(format!(
+ "Key: Expected X448 public key, got {:?}", self.mpis())).into())
+ },
+
+ RSASign | DSA | ECDSA | EdDSA | Ed25519 | Ed448 =>
Err(Error::InvalidOperation(
format!("{} is not an encryption algorithm", self.pk_algo())
).into()),
@@ -775,6 +835,12 @@ impl<P, R> Key<P, R>
}
let ok = match (self.mpis(), sig) {
+ (PublicKey::Ed25519 { a }, Signature::Ed25519 { s }) =>
+ Backend::ed25519_verify(a, digest, s)?,
+
+ (PublicKey::Ed448 { a }, Signature::Ed448 { s }) =>
+ Backend::ed448_verify(a, digest, s)?,
+
(PublicKey::EdDSA { curve, q }, Signature::EdDSA { r, s }) =>
match curve {
Curve::Ed25519 => {
@@ -1325,6 +1391,74 @@ impl<R> Key4<SecretParts, R>
public_mpis,
private_mpis.into())
}
+
+ /// Generates a new X25519 key.
+ pub fn generate_x25519() -> Result<Self> {
+ use crate::crypto::backend::{Backend, interface::Asymmetric};
+
+ let (private, public) = Backend::x25519_generate_key()?;
+
+ Self::with_secret(
+ crate::now(),
+ PublicKeyAlgorithm::X25519,
+ mpi::PublicKey::X25519 {
+ u: public,
+ },
+ mpi::SecretKeyMaterial::X25519 {
+ x: private,
+ }.into())
+ }
+
+ /// Generates a new X448 key.
+ pub fn generate_x448() -> Result<Self> {
+ use crate::crypto::backend::{Backend, interface::Asymmetric};
+
+ let (private, public) = Backend::x448_generate_key()?;
+
+ Self::with_secret(
+ crate::now(),
+ PublicKeyAlgorithm::X448,
+ mpi::PublicKey::X448 {
+ u: Box::new(public),
+ },
+ mpi::SecretKeyMaterial::X448 {
+ x: private,
+ }.into())
+ }
+
+ /// Generates a new Ed25519 key.
+ pub fn generate_ed25519() -> Result<Self> {
+ use crate::crypto::backend::{Backend, interface::Asymmetric};
+
+ let (private, public) = Backend::ed25519_generate_key()?;
+
+ Self::with_secret(
+ crate::now(),
+ PublicKeyAlgorithm::Ed25519,
+ mpi::PublicKey::Ed25519 {
+ a: public,
+ },
+ mpi::SecretKeyMaterial::Ed25519 {
+ x: private,
+ }.into())
+ }
+
+ /// Generates a new Ed448 key.
+ pub fn generate_ed448() -> Result<Self> {
+ use crate::crypto::backend::{Backend, interface::Asymmetric};
+
+ let (private, public) = Backend::ed448_generate_key()?;
+
+ Self::with_secret(
+ crate::now(),
+ PublicKeyAlgorithm::Ed448,
+ mpi::PublicKey::Ed448 {
+ a: Box::new(public),
+ },
+ mpi::SecretKeyMaterial::Ed448 {
+ x: private,
+ }.into())
+ }
}
impl<P, R> Key4<P, R>