summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-05-12 15:17:10 +0200
committerJustus Winter <justus@sequoia-pgp.org>2023-05-22 12:00:10 +0200
commit3646644294ed07a5731168ec4a0a9361e39e6793 (patch)
tree2dc5f29040cc71bac1dba754d30462adb755e930
parent3e84692aa4cbf047ca8fb16ca424deed8d9c3769 (diff)
openpgp: Introduce a common public facade for public key operations.
-rw-r--r--openpgp/src/crypto/asymmetric.rs38
-rw-r--r--openpgp/src/crypto/backend/botan/asymmetric.rs40
-rw-r--r--openpgp/src/crypto/backend/cng/asymmetric.rs41
-rw-r--r--openpgp/src/crypto/backend/nettle/asymmetric.rs40
-rw-r--r--openpgp/src/crypto/backend/openssl/asymmetric.rs40
-rw-r--r--openpgp/src/crypto/backend/rust/asymmetric.rs33
-rw-r--r--openpgp/src/packet/key.rs17
7 files changed, 135 insertions, 114 deletions
diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs
index 8f401a17..936f292c 100644
--- a/openpgp/src/crypto/asymmetric.rs
+++ b/openpgp/src/crypto/asymmetric.rs
@@ -209,3 +209,41 @@ impl From<KeyPair> for Key<key::SecretParts, key::UnspecifiedRole> {
key.add_secret(secret.into()).0
}
}
+
+impl Signer for KeyPair {
+ fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
+ KeyPair::public(self)
+ }
+
+ fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
+ -> Result<mpi::Signature>
+ {
+ self.secret().map(|secret| {
+ #[allow(clippy::match_single_binding)]
+ match (self.public().pk_algo(), self.public().mpis(), secret) {
+ (_algo, _public, secret) =>
+ self.sign_backend(secret, hash_algo, digest),
+ }
+ })
+ }
+}
+
+impl Decryptor for KeyPair {
+ fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
+ KeyPair::public(self)
+ }
+
+ fn decrypt(&mut self,
+ ciphertext: &mpi::Ciphertext,
+ plaintext_len: Option<usize>)
+ -> Result<SessionKey>
+ {
+ self.secret().map(|secret| {
+ #[allow(clippy::match_single_binding)]
+ match (self.public().mpis(), secret, ciphertext) {
+ (_public, secret, _ciphertext) =>
+ self.decrypt_backend(secret, ciphertext, plaintext_len),
+ }
+ })
+ }
+}
diff --git a/openpgp/src/crypto/backend/botan/asymmetric.rs b/openpgp/src/crypto/backend/botan/asymmetric.rs
index 265b83f7..ba2f0c96 100644
--- a/openpgp/src/crypto/backend/botan/asymmetric.rs
+++ b/openpgp/src/crypto/backend/botan/asymmetric.rs
@@ -16,7 +16,7 @@ use crate::{
Error,
Result,
crypto::{
- asymmetric::{KeyPair, Decryptor, Signer},
+ asymmetric::KeyPair,
backend::interface::Asymmetric,
mem::Protected,
mpi::{self, MPI, ProtectedMPI, PublicKey},
@@ -133,21 +133,19 @@ impl TryFrom<botan::MPI> for MPI {
}
}
-impl Signer for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
- -> Result<mpi::Signature>
+impl KeyPair {
+ pub(crate) fn sign_backend(&self,
+ secret: &mpi::SecretKeyMaterial,
+ hash_algo: HashAlgorithm,
+ digest: &[u8])
+ -> Result<mpi::Signature>
{
use crate::PublicKeyAlgorithm::*;
let mut rng = RandomNumberGenerator::new_userspace()?;
- self.secret().map(|secret| {
- #[allow(deprecated)]
- match (self.public().pk_algo(), self.public().mpis(), secret)
+ #[allow(deprecated)]
+ match (self.public().pk_algo(), self.public().mpis(), secret)
{
(RSASign,
PublicKey::RSA { e, .. },
@@ -235,16 +233,12 @@ impl Signer for KeyPair {
"unsupported combination of algorithm {:?}, key {:?}, \
and secret key {:?}",
pk_algo, self.public(), self.secret())).into()),
- }})
+ }
}
}
-impl Decryptor for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- fn decrypt(&mut self, ciphertext: &mpi::Ciphertext,
+impl KeyPair {
+ pub(crate) fn decrypt_backend(&self, secret: &mpi::SecretKeyMaterial, ciphertext: &mpi::Ciphertext,
_plaintext_len: Option<usize>)
-> Result<SessionKey>
{
@@ -253,9 +247,7 @@ impl Decryptor for KeyPair {
Error::MalformedMessage(e.to_string()).into()
}
- self.secret().map(
- |secret| Ok(match (self.public().mpis(), secret, ciphertext)
- {
+ Ok(match (self.public().mpis(), secret, ciphertext) {
(PublicKey::RSA { e, .. },
mpi::SecretKeyMaterial::RSA { p, q, .. },
mpi::Ciphertext::RSA { c }) => {
@@ -294,14 +286,14 @@ impl Decryptor for KeyPair {
"unsupported combination of key pair {:?}/{:?} \
and ciphertext {:?}",
public, secret, ciphertext)).into()),
- }))
+ })
}
}
impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
/// Encrypts the given data with this key.
- pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
+ pub(crate) fn encrypt_backend(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
use crate::PublicKeyAlgorithm::*;
#[allow(deprecated)]
@@ -371,7 +363,7 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
}
/// Verifies the given signature.
- pub fn verify(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
+ pub(crate) fn verify_backend(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
digest: &[u8]) -> Result<()>
{
use crate::crypto::mpi::Signature;
diff --git a/openpgp/src/crypto/backend/cng/asymmetric.rs b/openpgp/src/crypto/backend/cng/asymmetric.rs
index de49587d..e47f3911 100644
--- a/openpgp/src/crypto/backend/cng/asymmetric.rs
+++ b/openpgp/src/crypto/backend/cng/asymmetric.rs
@@ -6,7 +6,7 @@ use std::convert::TryInto;
use crate::{Error, Result};
-use crate::crypto::asymmetric::{Decryptor, KeyPair, Signer};
+use crate::crypto::asymmetric::KeyPair;
use crate::crypto::backend::interface::Asymmetric;
use crate::crypto::mem::Protected;
use crate::crypto::mpi;
@@ -131,12 +131,13 @@ impl Asymmetric for super::Backend {
}
}
-impl Signer for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8]) -> Result<mpi::Signature> {
+impl KeyPair {
+ pub(crate) fn sign_backend(&self,
+ secret: &mpi::SecretKeyMaterial,
+ hash_algo: HashAlgorithm,
+ digest: &[u8])
+ -> Result<mpi::Signature>
+ {
use cng::asymmetric::{AsymmetricAlgorithm, AsymmetricAlgorithmId};
use cng::asymmetric::{AsymmetricKey, Private, Rsa};
use cng::asymmetric::signature::{Signer, SignaturePadding};
@@ -145,8 +146,7 @@ impl Signer for KeyPair {
use cng::asymmetric::ecc::NamedCurve;
#[allow(deprecated)]
- self.secret().map(|secret| {
- Ok(match (self.public().pk_algo(), self.public().mpis(), secret) {
+ Ok(match (self.public().pk_algo(), self.public().mpis(), secret) {
(PublicKeyAlgorithm::RSAEncryptSign,
&mpi::PublicKey::RSA { ref e, ref n },
&mpi::SecretKeyMaterial::RSA { ref p, ref q, ref d, .. }) |
@@ -403,27 +403,20 @@ impl Signer for KeyPair {
"unsupported combination of algorithm {:?}, key {:?}, \
and secret key {:?}",
pk_algo, self.public(), self.secret())))?,
- })
})
}
}
-impl Decryptor for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- /// Creates a signature over the `digest` produced by `hash_algo`.
- fn decrypt(
- &mut self,
+impl KeyPair {
+ pub(crate) fn decrypt_backend(
+ &self,
+ secret: &mpi::SecretKeyMaterial,
ciphertext: &mpi::Ciphertext,
plaintext_len: Option<usize>,
) -> Result<SessionKey> {
use crate::PublicKeyAlgorithm::*;
- self.secret().map(
- |secret| Ok(match (self.public().mpis(), secret, ciphertext)
- {
+ Ok(match (self.public().mpis(), secret, ciphertext) {
(mpi::PublicKey::RSA { ref e, ref n },
mpi::SecretKeyMaterial::RSA { ref p, ref q, ref d, .. },
mpi::Ciphertext::RSA { ref c }) => {
@@ -471,13 +464,13 @@ impl Decryptor for KeyPair {
"unsupported combination of key pair {:?}/{:?} \
and ciphertext {:?}",
public, secret, ciphertext)).into()),
- }))
+ })
}
}
impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
/// Encrypts the given data with this key.
- pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
+ pub(crate) fn encrypt_backend(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
use cng::asymmetric::{AsymmetricAlgorithm, AsymmetricAlgorithmId};
use cng::asymmetric::{AsymmetricKey, Public, Rsa};
use cng::key_blob::RsaKeyPublicPayload;
@@ -536,7 +529,7 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
}
/// Verifies the given signature.
- pub fn verify(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
+ pub(crate) fn verify_backend(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
digest: &[u8]) -> Result<()> {
use cng::asymmetric::{AsymmetricAlgorithm, AsymmetricAlgorithmId};
use cng::asymmetric::{AsymmetricKey, Public, Rsa};
diff --git a/openpgp/src/crypto/backend/nettle/asymmetric.rs b/openpgp/src/crypto/backend/nettle/asymmetric.rs
index debb8a5b..e18fa249 100644
--- a/openpgp/src/crypto/backend/nettle/asymmetric.rs
+++ b/openpgp/src/crypto/backend/nettle/asymmetric.rs
@@ -9,7 +9,7 @@ use nettle::{curve25519, ecc, ecdh, ecdsa, ed25519, dsa, rsa, random::Yarrow};
use crate::{Error, Result};
use crate::packet::{key, Key};
-use crate::crypto::asymmetric::{KeyPair, Decryptor, Signer};
+use crate::crypto::asymmetric::KeyPair;
use crate::crypto::backend::interface::Asymmetric;
use crate::crypto::mpi::{self, MPI, PublicKey};
use crate::crypto::SessionKey;
@@ -74,21 +74,19 @@ impl Asymmetric for super::Backend {
}
}
-impl Signer for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
- -> Result<mpi::Signature>
+impl KeyPair {
+ pub(crate) fn sign_backend(&self,
+ secret: &mpi::SecretKeyMaterial,
+ hash_algo: HashAlgorithm,
+ digest: &[u8])
+ -> Result<mpi::Signature>
{
use crate::PublicKeyAlgorithm::*;
let mut rng = Yarrow::default();
- self.secret().map(|secret| {
- #[allow(deprecated)]
- match (self.public().pk_algo(), self.public().mpis(), secret)
+ #[allow(deprecated)]
+ match (self.public().pk_algo(), self.public().mpis(), secret)
{
(RSASign,
&PublicKey::RSA { ref e, ref n },
@@ -189,24 +187,18 @@ impl Signer for KeyPair {
"unsupported combination of algorithm {:?}, key {:?}, \
and secret key {:?}",
pk_algo, self.public(), self.secret())).into()),
- }})
+ }
}
}
-impl Decryptor for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- fn decrypt(&mut self, ciphertext: &mpi::Ciphertext,
+impl KeyPair {
+ pub(crate) fn decrypt_backend(&self, secret: &mpi::SecretKeyMaterial, ciphertext: &mpi::Ciphertext,
plaintext_len: Option<usize>)
-> Result<SessionKey>
{
use crate::PublicKeyAlgorithm::*;
- self.secret().map(
- |secret| Ok(match (self.public().mpis(), secret, ciphertext)
- {
+ Ok(match (self.public().mpis(), secret, ciphertext) {
(PublicKey::RSA{ ref e, ref n },
mpi::SecretKeyMaterial::RSA{ ref p, ref q, ref d, .. },
mpi::Ciphertext::RSA{ ref c }) => {
@@ -242,14 +234,14 @@ impl Decryptor for KeyPair {
"unsupported combination of key pair {:?}/{:?} \
and ciphertext {:?}",
public, secret, ciphertext)).into()),
- }))
+ })
}
}
impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
/// Encrypts the given data with this key.
- pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
+ pub(crate) fn encrypt_backend(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
use crate::PublicKeyAlgorithm::*;
#[allow(deprecated)]
@@ -298,7 +290,7 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
}
/// Verifies the given signature.
- pub fn verify(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
+ pub(crate) fn verify_backend(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
digest: &[u8]) -> Result<()>
{
use crate::crypto::mpi::Signature;
diff --git a/openpgp/src/crypto/backend/openssl/asymmetric.rs b/openpgp/src/crypto/backend/openssl/asymmetric.rs
index d45443fd..77ee9ff5 100644
--- a/openpgp/src/crypto/backend/openssl/asymmetric.rs
+++ b/openpgp/src/crypto/backend/openssl/asymmetric.rs
@@ -1,6 +1,6 @@
use crate::{Error, Result};
-use crate::crypto::asymmetric::{Decryptor, KeyPair, Signer};
+use crate::crypto::asymmetric::KeyPair;
use crate::crypto::backend::interface::Asymmetric;
use crate::crypto::mpi;
use crate::crypto::mpi::{ProtectedMPI, MPI};
@@ -136,16 +136,16 @@ impl TryFrom<&Curve> for Nid {
}
}
-impl Signer for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8]) -> Result<mpi::Signature> {
+impl KeyPair {
+ pub(crate) fn sign_backend(&self,
+ secret: &mpi::SecretKeyMaterial,
+ hash_algo: HashAlgorithm,
+ digest: &[u8])
+ -> Result<mpi::Signature>
+ {
use crate::PublicKeyAlgorithm::*;
#[allow(deprecated)]
- self.secret().map(
- |secret| match (self.public().pk_algo(), self.public().mpis(), secret) {
+ match (self.public().pk_algo(), self.public().mpis(), secret) {
(
RSAEncryptSign,
mpi::PublicKey::RSA { e, n },
@@ -254,25 +254,20 @@ impl Signer for KeyPair {
self.secret()
))
.into()),
- },
- )
+ }
}
}
-impl Decryptor for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- fn decrypt(
- &mut self,
+impl KeyPair {
+ pub(crate) fn decrypt_backend(
+ &self,
+ secret: &mpi::SecretKeyMaterial,
ciphertext: &mpi::Ciphertext,
_plaintext_len: Option<usize>,
) -> Result<SessionKey> {
use crate::crypto::mpi::PublicKey;
- self.secret().map(|secret| {
- Ok(match (self.public().mpis(), secret, ciphertext) {
+ Ok(match (self.public().mpis(), secret, ciphertext) {
(
PublicKey::RSA { ref e, ref n },
mpi::SecretKeyMaterial::RSA {
@@ -307,14 +302,13 @@ impl Decryptor for KeyPair {
))
.into())
}
- })
})
}
}
impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
/// Encrypts the given data with this key.
- pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
+ pub(crate) fn encrypt_backend(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
use PublicKeyAlgorithm::*;
#[allow(deprecated)]
match self.pk_algo() {
@@ -361,7 +355,7 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
}
/// Verifies the given signature.
- pub fn verify(
+ pub(crate) fn verify_backend(
&self,
sig: &mpi::Signature,
hash_algo: HashAlgorithm,
diff --git a/openpgp/src/crypto/backend/rust/asymmetric.rs b/openpgp/src/crypto/backend/rust/asymmetric.rs
index d52b66b9..9654e788 100644
--- a/openpgp/src/crypto/backend/rust/asymmetric.rs
+++ b/openpgp/src/crypto/backend/rust/asymmetric.rs
@@ -13,7 +13,7 @@ use rsa::traits::{PrivateKeyParts, PublicKeyParts};
use rsa::{Pkcs1v15Encrypt, RsaPublicKey, RsaPrivateKey, Pkcs1v15Sign};
use crate::{Error, Result};
-use crate::crypto::asymmetric::{KeyPair, Decryptor, Signer};
+use crate::crypto::asymmetric::KeyPair;
use crate::crypto::backend::interface::Asymmetric;
use crate::crypto::mem::Protected;
use crate::crypto::mpi::{self, MPI, ProtectedMPI};
@@ -149,17 +149,16 @@ fn rsa_private_key(e: &MPI, n: &MPI, p: &ProtectedMPI, q: &ProtectedMPI, d: &Pro
Ok(RsaPrivateKey::from_components(n, e, d, vec![p, q])?)
}
-impl Signer for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
+impl KeyPair {
+ pub(crate) fn sign_backend(&self,
+ secret: &mpi::SecretKeyMaterial,
+ hash_algo: HashAlgorithm,
+ digest: &[u8])
-> Result<mpi::Signature>
{
use crate::PublicKeyAlgorithm::*;
#[allow(deprecated)]
- self.secret().map(|secret| match (self.public().pk_algo(), self.public().mpis(), secret) {
+ match (self.public().pk_algo(), self.public().mpis(), secret) {
(RSAEncryptSign,
mpi::PublicKey::RSA { e, n },
mpi::SecretKeyMaterial::RSA { p, q, d, .. }) |
@@ -267,21 +266,17 @@ impl Signer for KeyPair {
self.secret()
)).into())
}
- })
+ }
}
}
-impl Decryptor for KeyPair {
- fn public(&self) -> &Key<key::PublicParts, key::UnspecifiedRole> {
- KeyPair::public(self)
- }
-
- fn decrypt(&mut self, ciphertext: &mpi::Ciphertext,
+impl KeyPair {
+ pub(crate) fn decrypt_backend(&self, secret: &mpi::SecretKeyMaterial, ciphertext: &mpi::Ciphertext,
_plaintext_len: Option<usize>)
-> Result<SessionKey>
{
use crate::PublicKeyAlgorithm::*;
- self.secret().map(|secret| match (self.public().mpis(), secret, ciphertext) {
+ match (self.public().mpis(), secret, ciphertext) {
(mpi::PublicKey::RSA { e, n },
mpi::SecretKeyMaterial::RSA { p, q, d, .. },
mpi::Ciphertext::RSA { c }) => {
@@ -305,14 +300,14 @@ impl Decryptor for KeyPair {
"unsupported combination of key pair {:?}/{:?} \
and ciphertext {:?}",
public, secret, ciphertext)).into()),
- })
+ }
}
}
impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
/// Encrypts the given data with this key.
- pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
+ pub(crate) fn encrypt_backend(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
use PublicKeyAlgorithm::*;
#[allow(deprecated)]
match self.pk_algo() {
@@ -350,7 +345,7 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
}
/// Verifies the given signature.
- pub fn verify(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
+ pub(crate) fn verify_backend(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
digest: &[u8]) -> Result<()>
{
fn bad(e: impl ToString) -> anyhow::Error {
diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs
index 4f9b496a..c1d9545c 100644
--- a/openpgp/src/packet/key.rs
+++ b/openpgp/src/packet/key.rs
@@ -102,6 +102,7 @@ use crate::types::{Curve, Timestamp};
use crate::crypto::S2K;
use crate::Result;
use crate::crypto::Password;
+use crate::crypto::SessionKey;
use crate::KeyID;
use crate::Fingerprint;
use crate::KeyHandle;
@@ -734,6 +735,22 @@ pub(crate) type UnspecifiedSecondary = Key<UnspecifiedParts, SubordinateRole>;
#[allow(dead_code)]
pub(crate) type UnspecifiedKey = Key<UnspecifiedParts, UnspecifiedRole>;
+/// Cryptographic operations using the key material.
+impl<P, R> Key<P, R>
+ where P: key::KeyParts,
+ R: key::KeyRole,
+{
+ /// Encrypts the given data with this key.
+ pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
+ self.encrypt_backend(data)
+ }
+
+ /// Verifies the given signature.
+ pub fn verify(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
+ digest: &[u8]) -> Result<()> {
+ self.verify_backend(sig, hash_algo, digest)
+ }
+}
/// Holds a public key, public subkey, private key or private subkey
/// packet.