summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2021-09-20 15:19:55 +0200
committerJustus Winter <justus@sequoia-pgp.org>2021-10-05 11:46:38 +0200
commit4eb79a5dd7c1bc39ba568828f4510c5893088f74 (patch)
treedaa901c8507c4f803df66a3719a6b0dea9c63888
parent341fdd29a9863e793c560e2a7207989c4f61d772 (diff)
openpgp: Implement ECDH and ECDSA over NistP256 with RustCrypto.
-rw-r--r--Cargo.lock180
-rw-r--r--openpgp/Cargo.toml6
-rw-r--r--openpgp/src/crypto/backend/rust.rs8
-rw-r--r--openpgp/src/crypto/backend/rust/asymmetric.rs118
-rw-r--r--openpgp/src/crypto/backend/rust/ecdh.rs40
5 files changed, 337 insertions, 15 deletions
diff --git a/Cargo.lock b/Cargo.lock
index efcea173..aff06b84 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -204,6 +204,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
+name = "bitvec"
+version = "0.20.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7774144344a4faa177370406a7ff5f1da24303817368584c6206c8303eb07848"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
+[[package]]
name = "blake2b_simd"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -456,6 +468,7 @@ checksum = "f54d78e30b388d4815220c8dd03fea5656b6c6d32adb59e89061552a102f8da1"
dependencies = [
"glob",
"libc",
+ "libloading",
]
[[package]]
@@ -480,7 +493,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73d4de4f7724e5fe70addfb2bd37c2abd2f95084a429d7773b0b9645499b4272"
dependencies = [
- "crypto-mac",
+ "crypto-mac 0.10.0",
"dbl",
]
@@ -496,6 +509,12 @@ dependencies = [
]
[[package]]
+name = "const-oid"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "279bc8fc53f788a75c7804af68237d1fce02cde1e275a886a4b320604dc2aeda"
+
+[[package]]
name = "constant_time_eq"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -640,6 +659,16 @@ dependencies = [
]
[[package]]
+name = "crypto-mac"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
+dependencies = [
+ "generic-array 0.14.4",
+ "subtle",
+]
+
+[[package]]
name = "csv"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -703,6 +732,16 @@ dependencies = [
]
[[package]]
+name = "der"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eeb9d92785d1facb50567852ce75d0858630630e7eabea59cf7eb7474051087"
+dependencies = [
+ "const-oid",
+ "typenum",
+]
+
+[[package]]
name = "des"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -801,6 +840,18 @@ dependencies = [
]
[[package]]
+name = "ecdsa"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34d33b390ab82f2e1481e331dbd0530895640179d2128ef9a79cc690b78d1eba"
+dependencies = [
+ "der",
+ "elliptic-curve",
+ "hmac",
+ "signature",
+]
+
+[[package]]
name = "ed25519"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -829,6 +880,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
+name = "elliptic-curve"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c13e9b0c3c4170dcc2a12783746c4205d98e18957f57854251eea3f9750fe005"
+dependencies = [
+ "bitvec",
+ "ff",
+ "generic-array 0.14.4",
+ "group",
+ "pkcs8",
+ "rand_core 0.6.2",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "ena"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -884,6 +951,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
+name = "ff"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72a4d941a5b7c2a75222e2d44fcdf634a67133d9db31e177ae5ff6ecda852bfe"
+dependencies = [
+ "bitvec",
+ "rand_core 0.6.2",
+ "subtle",
+]
+
+[[package]]
name = "filetime"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -971,6 +1049,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
+name = "funty"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
+
+[[package]]
name = "futures"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1116,6 +1200,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
+name = "group"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61b3c1e8b4f1ca07e6605ea1be903a5f6956aec5c8a67fd44d56076631675ed8"
+dependencies = [
+ "ff",
+ "rand_core 0.6.2",
+ "subtle",
+]
+
+[[package]]
name = "h2"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1169,6 +1264,16 @@ dependencies = [
]
[[package]]
+name = "hmac"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
+dependencies = [
+ "crypto-mac 0.11.1",
+ "digest 0.9.0",
+]
+
+[[package]]
name = "http"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1375,6 +1480,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
[[package]]
+name = "libloading"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a"
+dependencies = [
+ "cfg-if 1.0.0",
+ "winapi 0.3.9",
+]
+
+[[package]]
name = "libm"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1554,9 +1669,9 @@ dependencies = [
[[package]]
name = "nettle-sys"
-version = "2.0.6"
+version = "2.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355944b1ac94b95a54a75788d9befba1ad4630189cbd5531ba3385f5c2678edd"
+checksum = "b95aff9e61c8d8132e41dceae74c6e526edcac8d120072c87a300b9ab7e75226"
dependencies = [
"bindgen",
"pkg-config",
@@ -1713,6 +1828,17 @@ dependencies = [
]
[[package]]
+name = "p256"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f05f5287453297c4c16af5e2b04df8fd2a3008d70f252729650bc6d7ace5844"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "sha2 0.9.3",
+]
+
+[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1799,6 +1925,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
+name = "pkcs8"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9c2f795bc591cb3384cb64082a578b89207ac92bb89c9d98c1ea2ace7cd8110"
+dependencies = [
+ "der",
+ "spki",
+]
+
+[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1885,6 +2021,12 @@ dependencies = [
]
[[package]]
+name = "radium"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "643f8f41a8ebc4c5dc4515c82bb8abd397b527fc20fd681b7c011c2aee5d44fb"
+
+[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2326,6 +2468,7 @@ dependencies = [
"digest 0.9.0",
"dyn-clone",
"eax",
+ "ecdsa",
"ed25519-dalek",
"flate2",
"generic-array 0.14.4",
@@ -2339,8 +2482,10 @@ dependencies = [
"memsec",
"nettle",
"num-bigint-dig",
+ "p256",
"quickcheck",
"rand 0.7.3",
+ "rand_core 0.6.2",
"regex",
"regex-syntax",
"ripemd160",
@@ -2513,9 +2658,13 @@ dependencies = [
[[package]]
name = "signature"
-version = "1.3.0"
+version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68"
+checksum = "c19772be3c4dd2ceaacf03cb41d5885f2a02c4d8804884918e3a258480803335"
+dependencies = [
+ "digest 0.9.0",
+ "rand_core 0.6.2",
+]
[[package]]
name = "simple_asn1"
@@ -2564,6 +2713,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
+name = "spki"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dae7e047abc519c96350e9484a96c6bf1492348af912fd3446dd2dc323f6268"
+dependencies = [
+ "der",
+]
+
+[[package]]
name = "string_cache"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2611,6 +2769,12 @@ dependencies = [
]
[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
+[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3063,6 +3227,12 @@ dependencies = [
]
[[package]]
+name = "wyz"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
+
+[[package]]
name = "x25519-dalek"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/openpgp/Cargo.toml b/openpgp/Cargo.toml
index cd285ebe..4f7389d3 100644
--- a/openpgp/Cargo.toml
+++ b/openpgp/Cargo.toml
@@ -55,12 +55,15 @@ cipher = { version = "0.2.5", optional = true, features = ["std"] }
des = { version = "0.6.0", optional = true }
digest = { version = "0.9.0", optional = true }
eax = { version = "0.3.0", optional = true }
+ecdsa = { version = "0.11", optional = true, features = ["hazmat", "arithmetic"] } # XXX
ed25519-dalek = { version = "1", default-features = false, features = ["rand", "u64_backend"], optional = true }
generic-array = { version = "0.14.4", optional = true }
idea = { version = "0.3.0", optional = true }
md-5 = { version = "0.9.1", optional = true }
num-bigint-dig = { version = "0.6", default-features = false, optional = true }
+p256 = { version = "0.8", optional = true, features = ["ecdh", "ecdsa"] }
rand = { version = "0.7.3", optional = true }
+rand_core = { version = "0.6", optional = true }
ripemd160 = { version = "0.9.1", optional = true }
rsa = { version = "0.3.0", optional = true }
sha-1 = { version = "0.9.2", optional = true }
@@ -92,7 +95,8 @@ crypto-nettle = ["nettle"]
crypto-rust = [
"aes", "block-modes", "block-padding", "blowfish", "cast5", "cipher", "des",
"digest", "eax", "ed25519-dalek", "generic-array", "idea", "md-5", "num-bigint-dig", "rand",
- "ripemd160", "rsa", "sha-1", "sha2", "twofish", "typenum", "x25519-dalek"
+ "ripemd160", "rsa", "sha-1", "sha2", "twofish", "typenum", "x25519-dalek", "p256",
+ "rand_core", "rand_core/getrandom", "ecdsa"
]
crypto-cng = ["eax", "winapi", "win-crypto-ng", "ed25519-dalek", "num-bigint-dig"]
diff --git a/openpgp/src/crypto/backend/rust.rs b/openpgp/src/crypto/backend/rust.rs
index a661c14e..cf08f26d 100644
--- a/openpgp/src/crypto/backend/rust.rs
+++ b/openpgp/src/crypto/backend/rust.rs
@@ -27,9 +27,9 @@ impl PublicKeyAlgorithm {
use PublicKeyAlgorithm::*;
#[allow(deprecated)]
match &self {
- RSAEncryptSign | RSAEncrypt | RSASign | ECDH | EdDSA
+ RSAEncryptSign | RSAEncrypt | RSASign | ECDH | EdDSA | ECDSA
=> true,
- DSA | ECDSA
+ DSA
=> false,
ElGamalEncrypt | ElGamalEncryptSign | Private(_) | Unknown(_)
=> false,
@@ -41,7 +41,9 @@ impl Curve {
pub(crate) fn is_supported_by_backend(&self) -> bool {
use self::Curve::*;
match &self {
- NistP256 | NistP384 | NistP521
+ NistP256
+ => true,
+ NistP384 | NistP521
=> false,
Ed25519 | Cv25519
=> true,
diff --git a/openpgp/src/crypto/backend/rust/asymmetric.rs b/openpgp/src/crypto/backend/rust/asymmetric.rs
index b09f6214..22c86cee 100644
--- a/openpgp/src/crypto/backend/rust/asymmetric.rs
+++ b/openpgp/src/crypto/backend/rust/asymmetric.rs
@@ -16,6 +16,7 @@ use crate::crypto::asymmetric::{KeyPair, Decryptor, Signer};
use crate::crypto::mem::Protected;
use crate::crypto::mpi::{self, MPI, ProtectedMPI};
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};
@@ -88,9 +89,42 @@ impl Signer for KeyPair {
},
(PublicKeyAlgorithm::ECDSA,
- mpi::PublicKey::ECDSA { .. },
- mpi::SecretKeyMaterial::ECDSA { .. }) => {
- Err(Error::UnsupportedPublicKeyAlgorithm(PublicKeyAlgorithm::ECDSA).into())
+ mpi::PublicKey::ECDSA { curve, .. },
+ mpi::SecretKeyMaterial::ECDSA { scalar }) => match curve
+ {
+ Curve::NistP256 => {
+ use p256::{
+ elliptic_curve::{
+ generic_array::GenericArray as GA,
+ },
+ Scalar,
+ };
+ use ecdsa::{
+ hazmat::SignPrimitive,
+ };
+
+ const LEN: usize = 32;
+ let key = Scalar::from_bytes_reduced(
+ GA::from_slice(&scalar.value_padded(LEN)));
+ let dig = Scalar::from_bytes_reduced(
+ GA::from_slice(&pad_truncating(digest, LEN)));
+
+ let sig = loop {
+ let mut k: Protected = vec![0; LEN].into();
+ crate::crypto::random(&mut k);
+ let k = Scalar::from_bytes_reduced(
+ GA::from_slice(&k));
+ if let Ok(s) = key.try_sign_prehashed(&k, &dig) {
+ break s;
+ }
+ };
+
+ Ok(mpi::Signature::ECDSA {
+ r: MPI::new(&sig.r().to_bytes()),
+ s: MPI::new(&sig.s().to_bytes()),
+ })
+ },
+ _ => Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
},
(EdDSA,
@@ -212,6 +246,9 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
pub fn verify(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
digest: &[u8]) -> Result<()>
{
+ fn bad(e: impl ToString) -> anyhow::Error {
+ Error::BadSignature(e.to_string()).into()
+ }
match (self.mpis(), sig) {
(mpi::PublicKey::RSA { e, n }, mpi::Signature::RSA { s }) => {
let key = rsa_public_key(e, n)?;
@@ -223,9 +260,40 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
mpi::Signature::DSA { .. }) => {
Err(Error::UnsupportedPublicKeyAlgorithm(PublicKeyAlgorithm::DSA).into())
},
- (mpi::PublicKey::ECDSA { .. },
- mpi::Signature::ECDSA { .. }) => {
- Err(Error::UnsupportedPublicKeyAlgorithm(PublicKeyAlgorithm::ECDSA).into())
+ (mpi::PublicKey::ECDSA { curve, q },
+ mpi::Signature::ECDSA { r, s }) => match curve
+ {
+ Curve::NistP256 => {
+ use p256::{
+ AffinePoint,
+ ecdsa::Signature,
+ elliptic_curve::{
+ generic_array::GenericArray as GA,
+ sec1::FromEncodedPoint,
+ },
+ Scalar,
+ };
+ use ecdsa::{
+ EncodedPoint,
+ hazmat::VerifyPrimitive,
+ };
+ const LEN: usize = 32;
+
+ let key = AffinePoint::from_encoded_point(
+ &EncodedPoint::from_bytes(q.value())?)
+ .ok_or_else(|| Error::InvalidKey(
+ "Point is not on the curve".into()))?;
+ let sig = Signature::from_scalars(
+ Scalar::from_bytes_reduced(
+ GA::from_slice(&r.value_padded(LEN).map_err(bad)?)),
+ Scalar::from_bytes_reduced(
+ GA::from_slice(&s.value_padded(LEN).map_err(bad)?)))
+ .map_err(bad)?;
+ let dig = Scalar::from_bytes_reduced(
+ GA::from_slice(&pad_truncating(digest, LEN)));
+ key.verify_prehashed(&dig, &sig).map_err(bad)
+ },
+ _ => Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
},
(mpi::PublicKey::EdDSA { curve, q },
mpi::Signature::EdDSA { r, s }) => match curve {
@@ -463,6 +531,44 @@ impl<R> Key4<SecretParts, R>
(PublicKeyAlgorithm::ECDH, public_mpis, private_mpis.into())
}
+ (Curve::NistP256, true) => {
+ use p256::{EncodedPoint, SecretKey};
+
+ let secret = SecretKey::random(
+ &mut p256::elliptic_curve::rand_core::OsRng);
+ let public = EncodedPoint::from(secret.public_key());
+
+ let public_mpis = mpi::PublicKey::ECDSA {
+ curve,
+ q: MPI::new(public.as_bytes()),
+ };
+ let private_mpis = mpi::SecretKeyMaterial::ECDSA {
+ scalar: Vec::from(secret.to_bytes().as_slice()).into(),
+ };
+
+ (PublicKeyAlgorithm::ECDSA, public_mpis, private_mpis.into())
+ },
+
+ (Curve::NistP256, false) => {
+ use p256::{EncodedPoint, SecretKey};
+
+ let secret = SecretKey::random(
+ &mut p256::elliptic_curve::rand_core::OsRng);
+ let public = EncodedPoint::from(secret.public_key());
+
+ let public_mpis = mpi::PublicKey::ECDH {
+ curve,
+ q: MPI::new(public.as_bytes()),
+ hash: HashAlgorithm::SHA256,
+ sym: SymmetricAlgorithm::AES256,
+ };
+ let private_mpis = mpi::SecretKeyMaterial::ECDH {
+ scalar: Vec::from(secret.to_bytes().as_slice()).into(),
+ };
+
+ (PublicKeyAlgorithm::ECDH, public_mpis, private_mpis.into())
+ },
+
_ => {
return Err(Error::UnsupportedEllipticCurve(curve).into());
}
diff --git a/openpgp/src/crypto/backend/rust/ecdh.rs b/openpgp/src/crypto/backend/rust/ecdh.rs
index 519782f4..757bd90b 100644
--- a/openpgp/src/crypto/backend/rust/ecdh.rs
+++ b/openpgp/src/crypto/backend/rust/ecdh.rs
@@ -52,6 +52,27 @@ pub fn encrypt<R>(recipient: &Key<key::PublicParts, R>,
(VB, shared)
},
+ Curve::NistP256 => {
+ use p256::{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 p256::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.as_bytes();
+ let shared = Protected::from(shared);
+
+ (VB, shared)
+ },
_ =>
return Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
};
@@ -90,6 +111,25 @@ pub fn decrypt<R>(recipient: &Key<key::PublicParts, R>,
let secret = r.diffie_hellman(&V);
Vec::from(secret.to_bytes()).into()
},
+ Curve::NistP256 => {
+ use p256::{
+ SecretKey,
+ PublicKey,
+ elliptic_curve::ecdh::diffie_hellman,
+ };
+
+ const NISTP256_SIZE: usize = 32;
+
+ // Get the public part V of the ephemeral key.
+ let V = dbg!(PublicKey::from_sec1_bytes(e.value()))?;
+
+ let scalar: [u8; NISTP256_SIZE] =
+ scalar.value_padded(NISTP256_SIZE).as_ref().try_into()?;
+ let r = SecretKey::from_bytes(scalar)?;
+
+ let secret = diffie_hellman(r.secret_scalar(), V.as_affine());
+ Vec::from(secret.as_bytes().as_slice()).into()
+ },
_ => {
return Err(Error::UnsupportedEllipticCurve(curve.clone()).into());
},