Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/ece/src/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 13 kB image not shown  

Quelle  lib.rs

  Sprache: Rust
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#![warn(rust_2018_idioms)]

mod aes128gcm;
mod aesgcm;
mod common;
pub mod crypto;
mod error;
pub mod legacy;

pub use crate::{
    crypto::{Cryptographer, EcKeyComponents, LocalKeyPair, RemotePublicKey},
    error::*,
};

use crate::{
    aes128gcm::ECE_AES128GCM_PAD_SIZE,
    common::{WebPushParams, ECE_WEBPUSH_AUTH_SECRET_LENGTH},
};

/// Generate a local ECE key pair and authentication secret.
///
pub fn generate_keypair_and_auth_secret(
) -> Result<(Box<dyn LocalKeyPair>, [u8; ECE_WEBPUSH_AUTH_SECRET_LENGTH])> {
    let cryptographer = crypto::holder::get_cryptographer();
    let local_key_pair = cryptographer.generate_ephemeral_keypair()?;
    let mut auth_secret = [0u8; ECE_WEBPUSH_AUTH_SECRET_LENGTH];
    cryptographer.random_bytes(&mut auth_secret)?;
    Ok((local_key_pair, auth_secret))
}

/// Encrypt a block using the AES128GCM encryption scheme.
///
/// * `remote_pub` : The public key of the remote message recipient
/// * `remote_auth` : The authentication secret of the remote message recipient
/// * `data` : The data to encrypt
///
/// For the equivalent function using legacy AESGCM encryption scheme
/// use [`legacy::encrypt_aesgcm`](crate::legacy::encrypt_aesgcm).
///
pub fn encrypt(remote_pub: &[u8], remote_auth: &[u8], data: &[u8]) -> Result<Vec<u8>> {
    let cryptographer = crypto::holder::get_cryptographer();
    let remote_key = cryptographer.import_public_key(remote_pub)?;
    let local_key_pair = cryptographer.generate_ephemeral_keypair()?;
    let params = WebPushParams::new_for_plaintext(data, ECE_AES128GCM_PAD_SIZE);
    aes128gcm::encrypt(&*local_key_pair, &*remote_key, remote_auth, data, params)
}

/// Decrypt a block using the AES128GCM encryption scheme.
///
/// * `components` : The public and private key components of the local message recipient
/// * `auth` : The authentication secret of the remote message recipient
/// * `data` : The encrypted data block
///
/// For the equivalent function using legacy AESGCM encryption scheme
/// use [`legacy::decrypt_aesgcm`](crate::legacy::decrypt_aesgcm).
///
pub fn decrypt(components: &EcKeyComponents, auth: &[u8], data: &[u8]) -> Result<Vec<u8>> {
    let cryptographer = crypto::holder::get_cryptographer();
    let priv_key = cryptographer.import_key_pair(components).unwrap();
    aes128gcm::decrypt(&*priv_key, auth, data)
}

/// Generate a pair of keys; useful for writing tests.
///
#[cfg(all(test, feature = "backend-openssl"))]
fn generate_keys() -> Result<(Box<dyn LocalKeyPair>, Box<dyn LocalKeyPair>)> {
    let cryptographer = crypto::holder::get_cryptographer();
    let local_key = cryptographer.generate_ephemeral_keypair()?;
    let remote_key = cryptographer.generate_ephemeral_keypair()?;
    Ok((local_key, remote_key))
}

#[cfg(all(test, feature = "backend-openssl"))]
mod aes128gcm_tests {
    use super::common::ECE_TAG_LENGTH;
    use super::*;

    #[allow(clippy::too_many_arguments)]
    fn try_encrypt(
        private_key: &str,
        public_key: &str,
        remote_pub_key: &str,
        auth_secret: &str,
        salt: &str,
        pad_length: usize,
        rs: u32,
        plaintext: &str,
    ) -> Result<String> {
        let cryptographer = crypto::holder::get_cryptographer();
        let private_key = hex::decode(private_key).unwrap();
        let public_key = hex::decode(public_key).unwrap();
        let ec_key = EcKeyComponents::new(private_key, public_key);
        let local_key_pair = cryptographer.import_key_pair(&ec_key)?;
        let remote_pub_key = hex::decode(remote_pub_key).unwrap();
        let remote_pub_key = cryptographer.import_public_key(&remote_pub_key).unwrap();
        let auth_secret = hex::decode(auth_secret).unwrap();
        let salt = Some(hex::decode(salt).unwrap());
        let plaintext = plaintext.as_bytes();
        let params = WebPushParams {
            rs,
            pad_length,
            salt,
        };
        let ciphertext = aes128gcm::encrypt(
            &*local_key_pair,
            &*remote_pub_key,
            &auth_secret,
            plaintext,
            params,
        )?;
        Ok(hex::encode(ciphertext))
    }

    fn try_decrypt(
        private_key: &str,
        public_key: &str,
        auth_secret: &str,
        payload: &str,
    ) -> Result<String> {
        let private_key = hex::decode(private_key).unwrap();
        let public_key = hex::decode(public_key).unwrap();
        let ec_key = EcKeyComponents::new(private_key, public_key);
        let plaintext = decrypt(
            &ec_key,
            &hex::decode(auth_secret).unwrap(),
            &hex::decode(payload).unwrap(),
        )?;
        Ok(String::from_utf8(plaintext).unwrap())
    }

    #[test]
    fn test_keygen() {
        let cryptographer = crypto::holder::get_cryptographer();
        cryptographer.generate_ephemeral_keypair().unwrap();
    }

    #[test]
    fn test_e2e_through_public_api() {
        let (remote_key, auth_secret) = generate_keypair_and_auth_secret().unwrap();
        let plaintext = b"When I grow up, I want to be a watermelon";
        let ciphertext =
            encrypt(&remote_key.pub_as_raw().unwrap(), &auth_secret, plaintext).unwrap();
        let decrypted = decrypt(
            &remote_key.raw_components().unwrap(),
            &auth_secret,
            &ciphertext,
        )
        .unwrap();
        assert_eq!(decrypted, plaintext.to_vec());
    }

    #[test]
    fn test_e2e_large_plaintext() {
        let (remote_key, auth_secret) = generate_keypair_and_auth_secret().unwrap();
        let plaintext = [05000];
        let ciphertext =
            encrypt(&remote_key.pub_as_raw().unwrap(), &auth_secret, &plaintext).unwrap();
        let decrypted = decrypt(
            &remote_key.raw_components().unwrap(),
            &auth_secret,
            &ciphertext,
        )
        .unwrap();
        assert_eq!(decrypted, plaintext.to_vec());
    }

    #[test]
    fn test_e2e_with_different_record_sizes_and_padding() {
        let (local_key, remote_key) = generate_keys().unwrap();
        let plaintext = b"When I grow up, I want to be a watermelon";
        let mut auth_secret = vec![0u8; 16];
        let cryptographer = crypto::holder::get_cryptographer();
        cryptographer.random_bytes(&mut auth_secret).unwrap();
        let remote_public = cryptographer
            .import_public_key(&remote_key.pub_as_raw().unwrap())
            .unwrap();
        let plen = plaintext.len();
        // Try a variety of different record sizes. The numbers here aren't particularly deeply
        // considered, just a selection of numbers that might be interesting. (Although they did
        // trigger a bunch of interesting edge-cases during development, which is re-assuring).
        for plaintext_rs in &[2378, plen - 1, plen, plen + 110248192{
            let rs = (*plaintext_rs + ECE_TAG_LENGTH) as u32;
            // Try a variety of padding lengths. Again, not deeply considered numbers.
            for pad_length in &[012837127128] {
                let pad_length = *pad_length;
                let params = WebPushParams {
                    rs,
                    pad_length,
                    ..WebPushParams::default()
                };
                let ciphertext = aes128gcm::encrypt(
                    &*local_key,
                    &*remote_public,
                    &auth_secret,
                    plaintext,
                    params,
                )
                .unwrap();
                let decrypted =
                    aes128gcm::decrypt(&*remote_key, &auth_secret, &ciphertext).unwrap();
                assert_eq!(decrypted, plaintext.to_vec());
            }
        }
    }

    #[test]
    fn test_conv_fn() -> Result<()> {
        let (local_key, auth) = generate_keypair_and_auth_secret()?;
        let plaintext = b"Mary had a little lamb, with some nice mint jelly";
        let encoded = encrypt(&local_key.pub_as_raw()?, &auth, plaintext).unwrap();
        let decoded = decrypt(&local_key.raw_components()?, &auth, &encoded)?;
        assert_eq!(decoded, plaintext.to_vec());
        Ok(())
    }

    #[test]
    fn try_encrypt_ietf_rfc() {
        let ciphertext = try_encrypt(
            "c9f58f89813e9f8e872e71f42aa64e1757c9254dcc62b72ddc010bb4043ea11c",
            "04fe33f4ab0dea71914db55823f73b54948f41306d920732dbb9a59a53286482200e597a7b7bc260ba1c227998580992e93973002f3012a28ae8f06bbb78e5ec0f",
            "042571b2becdfde360551aaf1ed0f4cd366c11cebe555f89bcb7b186a53339173168ece2ebe018597bd30479b86e3c8f8eced577ca59187e9246990db682008b0e",
            "05305932a1c7eabe13b6cec9fda48882",
            "0c6bfaadad67958803092d454676f397",
            0,
            4096,
            "When I grow up, I want to be a watermelon",
        ).unwrap();
        assert_eq!(ciphertext, "0c6bfaadad67958803092d454676f397000010004104fe33f4ab0dea71914db55823f73b54948f41306d920732dbb9a59a53286482200e597a7b7bc260ba1c227998580992e93973002f3012a28ae8f06bbb78e5ec0ff297de5b429bba7153d3a4ae0caa091fd425f3b4b5414add8ab37a19c1bbb05cf5cb5b2a2e0562d558635641ec52812c6c8ff42e95ccb86be7cd");
    }

    #[test]
    fn test_decrypt_ietf_rfc() {
        let plaintext = try_decrypt(
            "ab5757a70dd4a53e553a6bbf71ffefea2874ec07a6b379e3c48f895a02dc33de",
            "042571b2becdfde360551aaf1ed0f4cd366c11cebe555f89bcb7b186a53339173168ece2ebe018597bd30479b86e3c8f8eced577ca59187e9246990db682008b0e",
            "05305932a1c7eabe13b6cec9fda48882",
            "0c6bfaadad67958803092d454676f397000010004104fe33f4ab0dea71914db55823f73b54948f41306d920732dbb9a59a53286482200e597a7b7bc260ba1c227998580992e93973002f3012a28ae8f06bbb78e5ec0ff297de5b429bba7153d3a4ae0caa091fd425f3b4b5414add8ab37a19c1bbb05cf5cb5b2a2e0562d558635641ec52812c6c8ff42e95ccb86be7cd"
        ).unwrap();
        assert_eq!(plaintext, "When I grow up, I want to be a watermelon");
    }

    #[test]
    fn test_decrypt_rs_18_pad_0() {
        let plaintext = try_decrypt(
            "27433fab8970b3cb5284b61183efb46286562cd2a7330d8cae960911a5571d0c",
            "04515d4326355652399da24b2be9241e633b5cf14faf0cf3a6fd60317b954c0a2f4848548004b27b0cf7480bc810c6bec03a8fb79c8ea00fc8b05e00f8834563ef",
            "d65a04df95f2db5e604839f717dcde79",
            "7caebdbc20938ee340a946f1bd4f68f100000012410437cfdb5223d9f95eaa02f6ed940ff22eaf05b3622e949dc3ce9f335e6ef9b26aeaacca0f74080a8b364592f2ccc6d5eddd43004b70b91887d144d9fa93f16c3bc7ea68f4fd547a94eca84b16e138a6080177"
        ).unwrap();
        assert_eq!(plaintext, "1");
    }

    #[test]
    fn test_decrypt_missing_header_block() {
        let err = try_decrypt(
            "1be83f38332ef09681faf3f307b1ff2e10cab78cc7cdab683ac0ee92ac3f6ee1",
            "04dba991ca215343f36bdd3e857cafde3d18bf57f1835b2833bad414f0884162051ac96a0b24490037d07cf528e4e18e100a1a64eb744748544bf1e220dabacf2c",
            "3471bb98481e02533bf39542bcf3dba4",
            "45b74d2b69be9b074de3b35aa87e7c15611d",
        )
        .unwrap_err();
        match err {
            Error::HeaderTooShort => {}
            _ => panic!("Unexpected error {:?}", err),
        };
    }

    #[test]
    fn test_decrypt_truncated_sender_key() {
        let err = try_decrypt(
            "ce88e8e0b3057a4752eb4c8fa931eb621c302da5ad03b81af459cf6735560cae",
            "04a325d99084c40de0ce722a042c448d94a32691721ca79e3cf745e78c69886194b02cea19224176795a9d4dbbb2073af2ccd6fa6f0a4c7c4968556be502a3ba81",
            "5c31e0d96d9a139899ac0969d359f740",
            "de5b696b87f1a15cb6adebdd79d6f99e000000120100b6bc1826c37c9f73dd6b4859c2b505181952",
        )
        .unwrap_err();
        match err {
            Error::InvalidKeyLength => {}
            _ => panic!("Unexpected error {:?}", err),
        };
    }

    #[test]
    fn test_decrypt_truncated_auth_secret() {
        let err = try_decrypt(
            "60c7636a517de7039a0ac2d0e3064400794c78e7e049398129a227cee0f9a801",
            "04fdd04128a85c05896d7f81fe118bdcb887b9f3c1ff4183adc4c824d128607300e986b2dfb5a610e5af43e408a00730584f93e3dfddfc44737d5f08fb2d6f8916",
            "355a38cd6d9bef15990e2d3308dbd600",
            "8115f4988b8c392a7bacb43c8f1ac5650000001241041994483c541e9bc39a6af03ff713aa7745c284e138a42a2435b797b20c4b698cf5118b4f8555317c190eabebfab749c164d3f6bdebe0d441719131a357d8890a13c4dbd4b16ff3dd5a83f7c91ad6e040ac42730a7f0b3cd3245e9f8d6ff31c751d410cfd"
        ).unwrap_err();
        match err {
            Error::OpenSSLError(_) => {}
            _ => panic!("Unexpected error {:?}", err),
        };
    }

    #[test]
    fn test_decrypt_early_final_record() {
        let err = try_decrypt(
            "5dda1d918bc407ba3cda12cb8014d49aa7e0269002820304466bc80034ca9240",
            "04c95c6520dad11e8f6a1bf8031a40c2a4ee1045c1903be06a1dfa7f829cceb2de02481ae6bd0476121b12c5532d0b231788077efa0683a5bfe0d62339b251cb35",
            "40c241fde4269ee1e6d725592d982718",
            "dbe215507d1ad3d2eaeabeae6e874d8f0000001241047bc4343f34a8348cdc4e462ffc7c40aa6a8c61a739c4c41d45125505f70e9fc5f9efa86852dd488dcf8e8ea2cafb75e07abd5ee7c9d5c038bafef079571b0bda294411ce98c76dd031c0e580577a4980a375e45ed30429be0e2ee9da7e6df8696d01b8ec"
        ).unwrap_err();
        match err {
            Error::DecryptPadding => {}
            _ => panic!("Unexpected error {:?}", err),
        };
    }
}

Messung V0.5 in Prozent
C=90 H=98 G=94

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.