diff options
Diffstat (limited to 'openpgp/src/crypto/backend/rust/ecdh.rs')
-rw-r--r-- | openpgp/src/crypto/backend/rust/ecdh.rs | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/openpgp/src/crypto/backend/rust/ecdh.rs b/openpgp/src/crypto/backend/rust/ecdh.rs index eed2f827..77fd7d23 100644 --- a/openpgp/src/crypto/backend/rust/ecdh.rs +++ b/openpgp/src/crypto/backend/rust/ecdh.rs @@ -104,6 +104,28 @@ pub fn encrypt<R>(recipient: &Key<key::PublicParts, R>, (VB, shared) }, + Curve::NistP521 => { + use p521::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; + + // Decode the recipient's public key. + let recipient_key = PublicKey::from_sec1_bytes(q.value())?; + + // Generate a keypair and perform Diffie-Hellman. + let secret = EphemeralSecret::random( + &mut p521::elliptic_curve::rand_core::OsRng); + let public = EncodedPoint::from(PublicKey::from(&secret)); + let shared = secret.diffie_hellman(&recipient_key); + + // Encode our public key. + let VB = MPI::new(public.as_bytes()); + + // Encode the shared secret. + let shared: &[u8] = shared.raw_secret_bytes(); + let shared = Protected::from(shared); + + (VB, shared) + }, + _ => return Err(Error::UnsupportedEllipticCurve(curve.clone()).into()), }; @@ -175,6 +197,22 @@ pub fn decrypt<R>(recipient: &Key<key::PublicParts, R>, Vec::from(secret.raw_secret_bytes().as_slice()).into() }, + Curve::NistP521 => { + use p521::{SecretKey, PublicKey}; + const NISTP521_SIZE: usize = 66; + + // Get the public part V of the ephemeral key. + let V = PublicKey::from_sec1_bytes(e.value())?; + + let scalar: [u8; NISTP521_SIZE] = + scalar.value_padded(NISTP521_SIZE).as_ref().try_into()?; + let scalar = GA::try_from_slice(&scalar)?; + let r = SecretKey::from_bytes(&scalar)?; + + let secret = diffie_hellman(r.to_nonzero_scalar(), V.as_affine()); + Vec::from(secret.raw_secret_bytes().as_slice()).into() + }, + _ => { return Err(Error::UnsupportedEllipticCurve(curve.clone()).into()); }, |