зеркало из https://github.com/mozilla/rust-ece.git
Родитель
082a9cd9be
Коммит
174f2d250f
|
@ -30,6 +30,10 @@ jobs:
|
|||
Check Rust formatting:
|
||||
docker:
|
||||
- image: circleci/rust:latest
|
||||
auth:
|
||||
username: $DOCKER_USER
|
||||
password: $DOCKER_PASS
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
- run: rustup component add rustfmt
|
||||
|
@ -38,11 +42,18 @@ jobs:
|
|||
Rust tests - stable:
|
||||
docker:
|
||||
- image: circleci/rust:latest
|
||||
auth:
|
||||
username: $DOCKER_USER
|
||||
password: $DOCKER_PASS
|
||||
|
||||
steps:
|
||||
- rust-tests
|
||||
Rust tests - beta:
|
||||
docker:
|
||||
- image: circleci/rust:latest
|
||||
auth:
|
||||
username: $DOCKER_USER
|
||||
password: $DOCKER_PASS
|
||||
steps:
|
||||
- rust-tests:
|
||||
rust-version: "beta"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "ece"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>", "JR Conlin <src+git@jrconlin.com>"]
|
||||
license = "MPL-2.0"
|
||||
edition = "2021"
|
||||
|
@ -11,7 +11,7 @@ keywords = ["http-ece", "web-push"]
|
|||
[dependencies]
|
||||
byteorder = "1.3"
|
||||
thiserror = "1.0"
|
||||
base64 = "0.13"
|
||||
base64 = "0.21"
|
||||
hex = "0.4"
|
||||
hkdf = { version = "0.12", optional = true }
|
||||
lazy_static = { version = "1.4", optional = true }
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::{
|
|||
crypto::{self, Cryptographer, LocalKeyPair, RemotePublicKey},
|
||||
error::*,
|
||||
};
|
||||
use base64::Engine;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
|
||||
pub(crate) const ECE_AESGCM_PAD_SIZE: usize = 2;
|
||||
|
@ -75,12 +76,12 @@ impl AesGcmEncryptedBlock {
|
|||
pub fn headers(&self, vapid_public_key: Option<&[u8]>) -> Vec<(&'static str, String)> {
|
||||
let mut result = Vec::new();
|
||||
let mut rs = "".to_owned();
|
||||
let dh = base64::encode_config(&self.dh, base64::URL_SAFE_NO_PAD);
|
||||
let dh = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(&self.dh);
|
||||
let crypto_key = match vapid_public_key {
|
||||
Some(public_key) => format!(
|
||||
"dh={}; p256ecdsa={}",
|
||||
dh,
|
||||
base64::encode_config(public_key, base64::URL_SAFE_NO_PAD)
|
||||
base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(public_key)
|
||||
),
|
||||
None => format!("dh={}", dh),
|
||||
};
|
||||
|
@ -92,7 +93,7 @@ impl AesGcmEncryptedBlock {
|
|||
"Encryption",
|
||||
format!(
|
||||
"salt={}{}",
|
||||
base64::encode_config(&self.salt, base64::URL_SAFE_NO_PAD),
|
||||
base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(&self.salt),
|
||||
rs
|
||||
),
|
||||
));
|
||||
|
@ -101,7 +102,7 @@ impl AesGcmEncryptedBlock {
|
|||
|
||||
/// Encode the body as a String.
|
||||
pub fn body(&self) -> String {
|
||||
base64::encode_config(&self.ciphertext, base64::URL_SAFE_NO_PAD)
|
||||
base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(&self.ciphertext)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,16 +35,12 @@ pub trait LocalKeyPair: Send + Sync + 'static {
|
|||
feature = "serializable-keys",
|
||||
derive(serde::Serialize, serde::Deserialize)
|
||||
)]
|
||||
#[derive(Default)]
|
||||
pub enum EcCurve {
|
||||
#[default]
|
||||
P256,
|
||||
}
|
||||
|
||||
impl Default for EcCurve {
|
||||
fn default() -> Self {
|
||||
EcCurve::P256
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(
|
||||
feature = "serializable-keys",
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
crypto::{Cryptographer, EcKeyComponents, LocalKeyPair, RemotePublicKey},
|
||||
error::*,
|
||||
};
|
||||
use base64::Engine;
|
||||
use hkdf::Hkdf;
|
||||
use lazy_static::lazy_static;
|
||||
use openssl::{
|
||||
|
@ -64,7 +65,7 @@ impl fmt::Debug for OpenSSLLocalKeyPair {
|
|||
write!(
|
||||
f,
|
||||
"{:?}",
|
||||
base64::encode_config(&self.ec_key.private_key().to_vec(), base64::URL_SAFE)
|
||||
base64::engine::general_purpose::URL_SAFE.encode(self.ec_key.private_key().to_vec())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ pub fn decrypt_aesgcm(
|
|||
#[cfg(all(test, feature = "backend-openssl"))]
|
||||
mod aesgcm_tests {
|
||||
use super::*;
|
||||
use base64;
|
||||
use base64::Engine;
|
||||
use hex;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -205,16 +205,18 @@ mod aesgcm_tests {
|
|||
// The AesGcmEncryptedBlock is composed from the `Crypto-Key` & `Encryption` headers, and post body
|
||||
// The Block will attempt to decode the base64 strings for dh & salt, so no additional action needed.
|
||||
// Since the body is most likely not encoded, it is expected to be a raw buffer of [u8]
|
||||
let priv_key_raw = base64::decode_config(priv_key, base64::URL_SAFE_NO_PAD)?;
|
||||
let pub_key_raw = base64::decode_config(pub_key, base64::URL_SAFE_NO_PAD)?;
|
||||
let priv_key_raw = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(priv_key)?;
|
||||
let pub_key_raw = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(pub_key)?;
|
||||
let ec_key = EcKeyComponents::new(priv_key_raw, pub_key_raw);
|
||||
let auth_secret = base64::decode_config(auth_secret, base64::URL_SAFE_NO_PAD)?;
|
||||
let auth_secret = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(auth_secret)?;
|
||||
let plaintext = decrypt_aesgcm(&ec_key, &auth_secret, block)?;
|
||||
Ok(String::from_utf8(plaintext).unwrap())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
use base64::Engine;
|
||||
|
||||
// generated the content using pywebpush, which verified against the client.
|
||||
let auth_raw = "LsuUOBKVQRY6-l7_Ajo-Ag";
|
||||
let priv_key_raw = "yerDmA9uNFoaUnSt2TkWWLwPseG1qtzS2zdjUl8Z7tc";
|
||||
|
@ -225,13 +227,16 @@ mod aesgcm_tests {
|
|||
// Incoming Encryption: salt=
|
||||
let salt = "8qX1ZgkLD50LHgocZdPKZQ";
|
||||
// Incoming Body (this is normally raw bytes. It's encoded here for presentation)
|
||||
let ciphertext = base64::decode_config("8Vyes671P_VDf3G2e6MgY6IaaydgR-vODZZ7L0ZHbpCJNVaf_2omEms2tiPJiU22L3BoECKJixiOxihcsxWMjTgAcplbvfu1g6LWeP4j8dMAzJionWs7OOLif6jBKN6LGm4EUw9e26EBv9hNhi87-HaEGbfBMGcLvm1bql1F",
|
||||
base64::URL_SAFE_NO_PAD).unwrap();
|
||||
let ciphertext = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("8Vyes671P_VDf3G2e6MgY6IaaydgR-vODZZ7L0ZHbpCJNVaf_2omEms2tiPJiU22L3BoECKJixiOxihcsxWMjTgAcplbvfu1g6LWeP4j8dMAzJionWs7OOLif6jBKN6LGm4EUw9e26EBv9hNhi87-HaEGbfBMGcLvm1bql1F").unwrap();
|
||||
let plaintext = "Amidst the mists and coldest frosts I thrust my fists against the\nposts and still demand to see the ghosts.\n";
|
||||
|
||||
let block = AesGcmEncryptedBlock::new(
|
||||
&base64::decode_config(dh, base64::URL_SAFE_NO_PAD).unwrap(),
|
||||
&base64::decode_config(salt, base64::URL_SAFE_NO_PAD).unwrap(),
|
||||
&base64::engine::general_purpose::URL_SAFE_NO_PAD
|
||||
.decode(dh)
|
||||
.unwrap(),
|
||||
&base64::engine::general_purpose::URL_SAFE_NO_PAD
|
||||
.decode(salt)
|
||||
.unwrap(),
|
||||
4096,
|
||||
ciphertext,
|
||||
)
|
||||
|
@ -244,6 +249,8 @@ mod aesgcm_tests {
|
|||
|
||||
#[test]
|
||||
fn test_decode_padding() {
|
||||
use base64::Engine;
|
||||
|
||||
// generated the content using pywebpush, which verified against the client.
|
||||
let auth_raw = "LsuUOBKVQRY6-l7_Ajo-Ag";
|
||||
let priv_key_raw = "yerDmA9uNFoaUnSt2TkWWLwPseG1qtzS2zdjUl8Z7tc";
|
||||
|
@ -254,13 +261,16 @@ mod aesgcm_tests {
|
|||
// Incoming Encryption-Key: salt=
|
||||
let salt = "x2I2OZpSCoe-Cc5UW36Nng";
|
||||
// Incoming Body (this is normally raw bytes. It's encoded here for presentation)
|
||||
let ciphertext = base64::decode_config("Ua3-WW5kTbt11dBTiXBP6_hLBYhBNOtDFfue5QHMTd2DicL0wutDnt5z9pjRJ76w562egPq5qro95YLnsX0NWGmDQbsQ0Azds6jcBGsxHPt0p5GELAtR4AJj2OsB_LV7dTuGHN2SqsyXLARjTFN2wsF3xWhmuw",
|
||||
base64::URL_SAFE_NO_PAD).unwrap();
|
||||
let ciphertext = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode("Ua3-WW5kTbt11dBTiXBP6_hLBYhBNOtDFfue5QHMTd2DicL0wutDnt5z9pjRJ76w562egPq5qro95YLnsX0NWGmDQbsQ0Azds6jcBGsxHPt0p5GELAtR4AJj2OsB_LV7dTuGHN2SqsyXLARjTFN2wsF3xWhmuw").unwrap();
|
||||
let plaintext = "Tabs are the real indent";
|
||||
|
||||
let block = AesGcmEncryptedBlock::new(
|
||||
&base64::decode_config(dh, base64::URL_SAFE_NO_PAD).unwrap(),
|
||||
&base64::decode_config(salt, base64::URL_SAFE_NO_PAD).unwrap(),
|
||||
&base64::engine::general_purpose::URL_SAFE_NO_PAD
|
||||
.decode(dh)
|
||||
.unwrap(),
|
||||
&base64::engine::general_purpose::URL_SAFE_NO_PAD
|
||||
.decode(salt)
|
||||
.unwrap(),
|
||||
4096,
|
||||
ciphertext,
|
||||
)
|
||||
|
|
Загрузка…
Ссылка в новой задаче