fix crypto

s
This commit is contained in:
John Smith
2023-06-24 21:23:48 -04:00
parent b1df2c9d2d
commit c8fdded5a7
5 changed files with 85 additions and 62 deletions

View File

@@ -66,7 +66,11 @@ impl Envelope {
}
}
pub fn from_signed_data(crypto: Crypto, data: &[u8]) -> VeilidAPIResult<Envelope> {
pub fn from_signed_data(
crypto: Crypto,
data: &[u8],
network_key: &Option<SharedSecret>,
) -> VeilidAPIResult<Envelope> {
// Ensure we are at least the length of the envelope
// Silent drop here, as we use zero length packets as part of the protocol for hole punching
if data.len() < MIN_ENVELOPE_SIZE {
@@ -135,9 +139,22 @@ impl Envelope {
let recipient_id_slice: [u8; PUBLIC_KEY_LENGTH] = data[0x4A..0x6A]
.try_into()
.map_err(VeilidAPIError::internal)?;
let nonce: Nonce = Nonce::new(nonce_slice);
let sender_id = PublicKey::new(sender_id_slice);
let recipient_id = PublicKey::new(recipient_id_slice);
let mut nonce: Nonce = Nonce::new(nonce_slice);
let mut sender_id = PublicKey::new(sender_id_slice);
let mut recipient_id = PublicKey::new(recipient_id_slice);
// Apply network key (not the best, but it will keep networks from colliding without much overhead)
if let Some(nk) = network_key.as_ref() {
for n in 0..NONCE_LENGTH {
nonce.bytes[n] ^= nk.bytes[n];
}
for n in 0..CRYPTO_KEY_LENGTH {
sender_id.bytes[n] ^= nk.bytes[n];
}
for n in 0..CRYPTO_KEY_LENGTH {
recipient_id.bytes[n] ^= nk.bytes[n];
}
}
// Ensure sender_id and recipient_id are not the same
if sender_id == recipient_id {
@@ -175,13 +192,20 @@ impl Envelope {
crypto: Crypto,
data: &[u8],
node_id_secret: &SecretKey,
network_key: &Option<SharedSecret>,
) -> VeilidAPIResult<Vec<u8>> {
// Get DH secret
let vcrypto = crypto
.get(self.crypto_kind)
.expect("need to ensure only valid crypto kinds here");
let dh_secret = vcrypto.cached_dh(&self.sender_id, node_id_secret)?;
let mut dh_secret = vcrypto.cached_dh(&self.sender_id, node_id_secret)?;
// Apply network key
if let Some(nk) = network_key.as_ref() {
for n in 0..CRYPTO_KEY_LENGTH {
dh_secret.bytes[n] ^= nk.bytes[n];
}
}
// Decrypt message without authentication
let body = vcrypto.crypt_no_auth_aligned_8(
&data[0x6A..data.len() - 64],
@@ -197,6 +221,7 @@ impl Envelope {
crypto: Crypto,
body: &[u8],
node_id_secret: &SecretKey,
network_key: &Option<SharedSecret>,
) -> VeilidAPIResult<Vec<u8>> {
// Ensure body isn't too long
let envelope_size: usize = body.len() + MIN_ENVELOPE_SIZE;
@@ -207,7 +232,7 @@ impl Envelope {
let vcrypto = crypto
.get(self.crypto_kind)
.expect("need to ensure only valid crypto kinds here");
let dh_secret = vcrypto.cached_dh(&self.recipient_id, node_id_secret)?;
let mut dh_secret = vcrypto.cached_dh(&self.recipient_id, node_id_secret)?;
// Write envelope body
let mut data = vec![0u8; envelope_size];
@@ -229,6 +254,22 @@ impl Envelope {
// Write recipient node id
data[0x4A..0x6A].copy_from_slice(&self.recipient_id.bytes);
// Apply network key (not the best, but it will keep networks from colliding without much overhead)
if let Some(nk) = network_key.as_ref() {
for n in 0..SECRET_KEY_LENGTH {
dh_secret.bytes[n] ^= nk.bytes[n];
}
for n in 0..NONCE_LENGTH {
data[0x12 + n] ^= nk.bytes[n];
}
for n in 0..CRYPTO_KEY_LENGTH {
data[0x2A + n] ^= nk.bytes[n];
}
for n in 0..CRYPTO_KEY_LENGTH {
data[0x4A + n] ^= nk.bytes[n];
}
}
// Encrypt and authenticate message
let encrypted_body = vcrypto.crypt_no_auth_unaligned(body, &self.nonce.bytes, &dh_secret);

View File

@@ -3,8 +3,16 @@ use super::*;
pub async fn test_envelope_round_trip(
envelope_version: EnvelopeVersion,
vcrypto: CryptoSystemVersion,
network_key: Option<SharedSecret>,
) {
info!("--- test envelope round trip ---");
if network_key.is_some() {
info!(
"--- test envelope round trip {} w/network key ---",
vcrypto.kind()
);
} else {
info!("--- test envelope round trip {} ---", vcrypto.kind());
}
// Create envelope
let ts = Timestamp::from(0x12345678ABCDEF69u64);
@@ -25,15 +33,15 @@ pub async fn test_envelope_round_trip(
// Serialize to bytes
let enc_data = envelope
.to_encrypted_data(vcrypto.crypto(), body, &sender_secret)
.to_encrypted_data(vcrypto.crypto(), body, &sender_secret, &network_key)
.expect("failed to encrypt data");
// Deserialize from bytes
let envelope2 = Envelope::from_signed_data(vcrypto.crypto(), &enc_data)
let envelope2 = Envelope::from_signed_data(vcrypto.crypto(), &enc_data, &network_key)
.expect("failed to deserialize envelope from data");
let body2 = envelope2
.decrypt_body(vcrypto.crypto(), &enc_data, &recipient_secret)
.decrypt_body(vcrypto.crypto(), &enc_data, &recipient_secret, &network_key)
.expect("failed to decrypt envelope body");
// Compare envelope and body
@@ -45,13 +53,13 @@ pub async fn test_envelope_round_trip(
let mut mod_enc_data = enc_data.clone();
mod_enc_data[enc_data_len - 1] ^= 0x80u8;
assert!(
Envelope::from_signed_data(vcrypto.crypto(), &mod_enc_data).is_err(),
Envelope::from_signed_data(vcrypto.crypto(), &mod_enc_data, &network_key).is_err(),
"should have failed to decode envelope with modified signature"
);
let mut mod_enc_data2 = enc_data.clone();
mod_enc_data2[enc_data_len - 65] ^= 0x80u8;
assert!(
Envelope::from_signed_data(vcrypto.crypto(), &mod_enc_data2).is_err(),
Envelope::from_signed_data(vcrypto.crypto(), &mod_enc_data2, &network_key).is_err(),
"should have failed to decode envelope with modified data"
);
}
@@ -97,7 +105,9 @@ pub async fn test_all() {
for v in VALID_CRYPTO_KINDS {
let vcrypto = crypto.get(v).unwrap();
test_envelope_round_trip(ev, vcrypto.clone()).await;
test_envelope_round_trip(ev, vcrypto.clone(), None).await;
test_envelope_round_trip(ev, vcrypto.clone(), Some(vcrypto.random_shared_secret()))
.await;
test_receipt_round_trip(ev, vcrypto).await;
}
}