mls_rs_crypto_openssl/
ec_signer.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// Copyright by contributors to this project.
3// SPDX-License-Identifier: (Apache-2.0 OR MIT)
4
5use std::ops::Deref;
6
7use mls_rs_core::crypto::{CipherSuite, SignaturePublicKey, SignatureSecretKey};
8use mls_rs_crypto_traits::Curve;
9use openssl::hash::MessageDigest;
10
11#[cfg(feature = "x509")]
12use openssl::pkey::{PKey, Private, Public};
13
14use thiserror::Error;
15
16use crate::ec::{
17    curve_from_private_key, curve_from_public_key, generate_keypair, private_key_bytes_to_public,
18    private_key_from_bytes, private_key_from_der, private_key_to_bytes, pub_key_from_uncompressed,
19    pub_key_to_uncompressed, public_key_from_der, EcError,
20};
21
22#[derive(Debug, Error)]
23pub enum EcSignerError {
24    #[error(transparent)]
25    OpensslError(#[from] openssl::error::ErrorStack),
26    #[error(transparent)]
27    EcError(#[from] EcError),
28    #[error("invalid signature")]
29    InvalidSignature,
30}
31
32#[derive(Clone, Debug, Copy, PartialEq, Eq)]
33pub struct EcSigner(Curve);
34
35impl Deref for EcSigner {
36    type Target = Curve;
37
38    fn deref(&self) -> &Self::Target {
39        &self.0
40    }
41}
42
43impl EcSigner {
44    pub fn new(cipher_suite: CipherSuite) -> Option<Self> {
45        Curve::from_ciphersuite(cipher_suite, true).map(Self)
46    }
47
48    pub fn signature_key_generate(
49        &self,
50    ) -> Result<(SignatureSecretKey, SignaturePublicKey), EcSignerError> {
51        let key_pair = generate_keypair(self.0)?;
52        Ok((key_pair.secret.into(), key_pair.public.into()))
53    }
54
55    pub fn signature_key_import_der_public(
56        &self,
57        der_data: &[u8],
58    ) -> Result<SignaturePublicKey, EcError> {
59        let key = public_key_from_der(der_data)?;
60
61        curve_from_public_key(&key)
62            .filter(|&c| c == self.0)
63            .ok_or(EcError::InvalidKeyBytes)?;
64
65        Ok(pub_key_to_uncompressed(&key)?.into())
66    }
67
68    pub fn signature_key_import_der_private(
69        &self,
70        der_data: &[u8],
71    ) -> Result<SignatureSecretKey, EcError> {
72        let key = private_key_from_der(der_data)?;
73
74        curve_from_private_key(&key)
75            .filter(|&c| c == self.0)
76            .ok_or(EcError::InvalidKeyBytes)?;
77
78        Ok(private_key_to_bytes(&key)?.into())
79    }
80
81    pub fn signature_key_derive_public(
82        &self,
83        secret_key: &SignatureSecretKey,
84    ) -> Result<SignaturePublicKey, EcSignerError> {
85        Ok(private_key_bytes_to_public(secret_key, self.0)?.into())
86    }
87
88    #[cfg(feature = "x509")]
89    pub(crate) fn pkey_from_secret_key(
90        &self,
91        key: &SignatureSecretKey,
92    ) -> Result<PKey<Private>, EcSignerError> {
93        private_key_from_bytes(key, self.0, true).map_err(Into::into)
94    }
95
96    #[cfg(feature = "x509")]
97    pub(crate) fn pkey_from_public_key(
98        &self,
99        key: &SignaturePublicKey,
100    ) -> Result<PKey<Public>, EcSignerError> {
101        pub_key_from_uncompressed(key, self.0).map_err(Into::into)
102    }
103
104    pub fn sign(
105        &self,
106        secret_key: &SignatureSecretKey,
107        data: &[u8],
108    ) -> Result<Vec<u8>, EcSignerError> {
109        let secret_key = private_key_from_bytes(secret_key, self.0, false)?;
110
111        let mut signer = match self.message_digest() {
112            Some(md) => openssl::sign::Signer::new(md, &secret_key),
113            None => openssl::sign::Signer::new_without_digest(&secret_key),
114        }?;
115
116        Ok(signer.sign_oneshot_to_vec(data)?)
117    }
118
119    pub fn verify(
120        &self,
121        public_key: &SignaturePublicKey,
122        signature: &[u8],
123        data: &[u8],
124    ) -> Result<(), EcSignerError> {
125        let public_key = pub_key_from_uncompressed(public_key, self.0)?;
126
127        let mut verifier = match self.message_digest() {
128            Some(md) => openssl::sign::Verifier::new(md, &public_key),
129            None => openssl::sign::Verifier::new_without_digest(&public_key),
130        }?;
131
132        verifier
133            .verify_oneshot(signature, data)?
134            .then_some(())
135            .ok_or(EcSignerError::InvalidSignature)
136    }
137
138    pub(crate) fn message_digest(&self) -> Option<MessageDigest> {
139        match self.0 {
140            Curve::P256 => Some(MessageDigest::sha256()),
141            Curve::P384 => Some(MessageDigest::sha384()),
142            Curve::P521 => Some(MessageDigest::sha512()),
143            _ => None,
144        }
145    }
146}
147
148#[cfg(test)]
149mod test {
150    use mls_rs_crypto_traits::Curve;
151
152    use crate::{
153        ec::test_utils::{
154            get_test_public_keys, get_test_public_keys_der, get_test_secret_keys,
155            get_test_secret_keys_der, TestKeys,
156        },
157        ec_signer::EcSigner,
158    };
159
160    #[test]
161    fn import_der_public() {
162        let keys = get_test_public_keys();
163        let der_keys = get_test_public_keys_der();
164
165        let convert = |keys: &TestKeys, curve: Curve| {
166            EcSigner(curve)
167                .signature_key_import_der_public(&keys.get_key_from_curve(curve))
168                .unwrap()
169        };
170
171        let converted = TestKeys {
172            p256: convert(&der_keys, Curve::P256).to_vec(),
173            p384: convert(&der_keys, Curve::P384).to_vec(),
174            p521: convert(&der_keys, Curve::P521).to_vec(),
175            x25519: convert(&der_keys, Curve::X25519).to_vec(),
176            ed25519: convert(&der_keys, Curve::Ed25519).to_vec(),
177            x448: convert(&der_keys, Curve::X448).to_vec(),
178            ed448: convert(&der_keys, Curve::Ed448).to_vec(),
179        };
180
181        assert_eq!(keys, converted);
182    }
183
184    #[test]
185    fn import_der_private() {
186        let keys = get_test_secret_keys();
187        let der_keys = get_test_secret_keys_der();
188
189        let convert = |keys: &TestKeys, curve: Curve| {
190            EcSigner(curve)
191                .signature_key_import_der_private(&keys.get_key_from_curve(curve))
192                .unwrap()
193        };
194
195        let converted = TestKeys {
196            p256: convert(&der_keys, Curve::P256).to_vec(),
197            p384: convert(&der_keys, Curve::P384).to_vec(),
198            p521: convert(&der_keys, Curve::P521).to_vec(),
199            x25519: convert(&der_keys, Curve::X25519).to_vec(),
200            ed25519: convert(&der_keys, Curve::Ed25519).to_vec(),
201            x448: convert(&der_keys, Curve::X448).to_vec(),
202            ed448: convert(&der_keys, Curve::Ed448).to_vec(),
203        };
204
205        assert_eq!(keys, converted);
206    }
207}