Updated Crypto to use MTP-Crypto
This commit is contained in:
parent
f252724a43
commit
5625c5db5f
10 changed files with 558 additions and 453 deletions
|
|
@ -6,8 +6,8 @@ use iota_storage::util::chat_files::{self, MessageState, change_message_state};
|
|||
use iota_storage::util::chats_util::{self, get_user, mod_user};
|
||||
use iota_storage::util::communities_util::CommunitiesUtil;
|
||||
use iota_storage::util::config_util::CONFIG;
|
||||
use iota_util::crypto_helper;
|
||||
use iota_util::crypto_util::{DataFormat, SecurePayload};
|
||||
use iota_util::crypto_helper::{self, keyring_from_base64};
|
||||
use iota_util::crypto_util::{self};
|
||||
use iota_util::file_util::{get_children, has_file, load_file, save_file};
|
||||
use json::JsonValue;
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
|
|
@ -347,30 +347,41 @@ impl OmikronConnection {
|
|||
async fn handle_authentication(&self) {
|
||||
let conf = CONFIG.read().await;
|
||||
let iota_id = conf.get_iota_id();
|
||||
let public_key = conf.get_public_key();
|
||||
let private_key = conf.get_private_key();
|
||||
let keyring_b64 = conf.get_keyring();
|
||||
drop(conf);
|
||||
|
||||
if iota_id == 0 {
|
||||
log_t!("iota_register_new");
|
||||
|
||||
let (pub_k, _priv_k) = if let (Some(pk), Some(sk)) = (public_key, private_key) {
|
||||
(pk, sk)
|
||||
let pub_key_b64 = if let Some(kr) = keyring_b64 {
|
||||
if let Some(keyring) = keyring_from_base64(&kr) {
|
||||
let bundle = keyring.public_key_bundle();
|
||||
crypto_helper::public_key_bundle_to_base64(&bundle)
|
||||
} else {
|
||||
let keyring = crypto_helper::generate_keyring();
|
||||
let kb64 = crypto_helper::keyring_to_base64(&keyring);
|
||||
let bundle = keyring.public_key_bundle();
|
||||
let pk_b64 = crypto_helper::public_key_bundle_to_base64(&bundle);
|
||||
let mut conf_write = CONFIG.write().await;
|
||||
conf_write.change("keyring", JsonValue::from(kb64));
|
||||
conf_write.update();
|
||||
drop(conf_write);
|
||||
pk_b64
|
||||
}
|
||||
} else {
|
||||
let key_pair = crypto_helper::generate_keypair();
|
||||
let public_key_base64 = crypto_helper::public_key_to_base64(&key_pair.public);
|
||||
let private_key_base64 = crypto_helper::secret_key_to_base64(&key_pair.secret);
|
||||
|
||||
let keyring = crypto_helper::generate_keyring();
|
||||
let kb64 = crypto_helper::keyring_to_base64(&keyring);
|
||||
let bundle = keyring.public_key_bundle();
|
||||
let pk_b64 = crypto_helper::public_key_bundle_to_base64(&bundle);
|
||||
let mut conf_write = CONFIG.write().await;
|
||||
conf_write.change("public_key", JsonValue::from(public_key_base64.clone()));
|
||||
conf_write.change("private_key", JsonValue::from(private_key_base64.clone()));
|
||||
conf_write.change("keyring", JsonValue::from(kb64));
|
||||
conf_write.update();
|
||||
drop(conf_write);
|
||||
(public_key_base64, private_key_base64)
|
||||
pk_b64
|
||||
};
|
||||
|
||||
let register_msg = CommunicationValue::new(CommunicationType::RegisterIota)
|
||||
.add_typed_default(DataType::PublicKey, DataValue::Str(pub_k));
|
||||
.add_typed_default(DataType::PublicKey, DataValue::Str(pub_key_b64));
|
||||
|
||||
let msg_id = register_msg.get_id();
|
||||
|
||||
|
|
@ -522,8 +533,6 @@ impl OmikronConnection {
|
|||
}
|
||||
|
||||
if trusted {
|
||||
use iota_util::crypto_util::{DataFormat, SecurePayload};
|
||||
|
||||
let challenge = Uuid::new_v4().to_string();
|
||||
|
||||
self.app_challenges
|
||||
|
|
@ -535,31 +544,36 @@ impl OmikronConnection {
|
|||
.await
|
||||
.insert(sender_id, (user_id, app_identifier.clone()));
|
||||
|
||||
if let Some(pub_key) = iota_util::crypto_helper::load_public_key(&app_public_key) {
|
||||
if let Some(app_pub_bundle) =
|
||||
iota_util::crypto_helper::public_key_bundle_from_base64(&app_public_key)
|
||||
{
|
||||
let conf = CONFIG.read().await;
|
||||
let priv_k_str = conf.get_private_key().unwrap_or_default();
|
||||
let pub_k_str = conf.get_public_key().unwrap_or_default();
|
||||
let kr_str = conf.get_keyring().unwrap_or_default();
|
||||
drop(conf);
|
||||
|
||||
if let Some(priv_key) = iota_util::crypto_helper::load_secret_key(&priv_k_str) {
|
||||
let encrypted_challenge =
|
||||
SecurePayload::new(challenge.as_bytes(), DataFormat::Raw, priv_key)
|
||||
.unwrap()
|
||||
.encrypt_x448(pub_key)
|
||||
.unwrap()
|
||||
.export(DataFormat::Base64);
|
||||
if let Some(keyring) = keyring_from_base64(&kr_str) {
|
||||
if let Ok(encrypted_challenge) = crypto_util::encrypt_challenge(
|
||||
&challenge,
|
||||
&app_pub_bundle,
|
||||
) {
|
||||
let bundle = keyring.public_key_bundle();
|
||||
let pub_k_b64 = crypto_helper::public_key_bundle_to_base64(&bundle);
|
||||
|
||||
let res = CommunicationValue::new(CommunicationType::AppChallenge)
|
||||
.with_id(cv.get_id())
|
||||
.with_receiver(sender_id)
|
||||
.add_typed_default(DataType::PublicKey, DataValue::Str(pub_k_str))
|
||||
.add_typed_default(
|
||||
DataType::Challenge,
|
||||
DataValue::Str(encrypted_challenge),
|
||||
);
|
||||
let res = CommunicationValue::new(CommunicationType::AppChallenge)
|
||||
.with_id(cv.get_id())
|
||||
.with_receiver(sender_id)
|
||||
.add_typed_default(
|
||||
DataType::PublicKey,
|
||||
DataValue::Str(pub_k_b64),
|
||||
)
|
||||
.add_typed_default(
|
||||
DataType::Challenge,
|
||||
DataValue::Str(encrypted_challenge),
|
||||
);
|
||||
|
||||
self.send_message(&res).await;
|
||||
return;
|
||||
self.send_message(&res).await;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1686,17 +1700,17 @@ impl OmikronConnection {
|
|||
|
||||
async fn handle_challenge(&self, cv: &CommunicationValue) {
|
||||
let conf = CONFIG.read().await;
|
||||
let Some(private_key) = conf.get_private_key() else {
|
||||
let Some(kr_str) = conf.get_keyring() else {
|
||||
drop(conf);
|
||||
log_t!("omikron_challenge_decryption_failed");
|
||||
*self.auth_failure.write().await = Some(
|
||||
"Challenge decryption failed: no private key configured on this Iota.".to_string(),
|
||||
"Challenge decryption failed: no keyring configured on this Iota.".to_string(),
|
||||
);
|
||||
return;
|
||||
};
|
||||
drop(conf);
|
||||
|
||||
let Some(omikron_public_key) = cv.get_data(DataType::PublicKey).as_str() else {
|
||||
let Some(_omikron_pub_key_bundle) = cv.get_data(DataType::PublicKey).as_str() else {
|
||||
log_t!("omikron_challenge_decryption_failed");
|
||||
return;
|
||||
};
|
||||
|
|
@ -1705,23 +1719,14 @@ impl OmikronConnection {
|
|||
return;
|
||||
};
|
||||
|
||||
let Some(secret_key) = crypto_helper::load_secret_key(&private_key) else {
|
||||
log_t!("omikron_challenge_decryption_failed");
|
||||
return;
|
||||
};
|
||||
let Some(pub_key) = crypto_helper::load_public_key(omikron_public_key) else {
|
||||
let Some(keyring) = keyring_from_base64(&kr_str) else {
|
||||
log_t!("omikron_challenge_decryption_failed");
|
||||
return;
|
||||
};
|
||||
|
||||
let solved_challenge =
|
||||
SecurePayload::new(encrypted_challenge, DataFormat::Base64, secret_key)
|
||||
.ok()
|
||||
.and_then(|decrypted| decrypted.decrypt_x448(pub_key).ok());
|
||||
|
||||
if let Some(decrypted) = solved_challenge {
|
||||
let solved = decrypted.export(DataFormat::Raw);
|
||||
let solved_challenge = crypto_util::decrypt_challenge(encrypted_challenge, &keyring).ok();
|
||||
|
||||
if let Some(solved) = solved_challenge {
|
||||
let response = CommunicationValue::new(CommunicationType::ChallengeResponse)
|
||||
.with_id(cv.get_id())
|
||||
.add_typed_default(DataType::Challenge, DataValue::Str(solved));
|
||||
|
|
@ -1730,7 +1735,7 @@ impl OmikronConnection {
|
|||
} else {
|
||||
log_t!("omikron_challenge_decryption_failed");
|
||||
*self.auth_failure.write().await = Some(
|
||||
"Challenge decryption failed — your Iota private key may not match the registered key on the server."
|
||||
"Challenge decryption failed — your Iota keyring may not match the registered keys on the server."
|
||||
.to_string(),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
use base64::{Engine as _, engine::general_purpose::STANDARD};
|
||||
use hex;
|
||||
use iota_logger::{PrintType, log, log_cv, log_t};
|
||||
use iota_state::{RELOAD, SHUTDOWN};
|
||||
use iota_storage::users::user_manager::{add_user, save_users};
|
||||
use iota_storage::users::user_profile::UserProfile;
|
||||
use iota_util::crypto_helper::public_key_to_base64;
|
||||
use iota_util::crypto_helper::{self, hex_hash, public_key_bundle_to_base64};
|
||||
use iota_util::file_util::save_file;
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use rand_core::{OsRng, RngCore};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::time::Duration;
|
||||
use x448::{PublicKey, Secret};
|
||||
|
||||
use crate::omikron_connection::OMIKRON_CONNECTION;
|
||||
|
||||
|
|
@ -41,16 +38,11 @@ pub async fn create_user(username: &str) -> (Option<UserProfile>, Option<String>
|
|||
return (None, None);
|
||||
}
|
||||
};
|
||||
let mut buffer = [0u8; 56];
|
||||
let mut rng = OsRng;
|
||||
rng.fill_bytes(&mut buffer);
|
||||
let private_key = Secret::from_bytes(&buffer).unwrap();
|
||||
let public_key = PublicKey::from(&private_key);
|
||||
let keyring = crypto_helper::generate_keyring();
|
||||
let pub_key_bundle = keyring.public_key_bundle();
|
||||
let keyring_b64 = crypto_helper::keyring_to_base64(&keyring);
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&STANDARD.encode(&private_key.as_bytes()).as_bytes());
|
||||
let result = hasher.finalize();
|
||||
let private_key_hash = hex::encode(result);
|
||||
let private_key_hash = hex_hash(&keyring_b64);
|
||||
|
||||
let mut bytes = [0u8; 192];
|
||||
OsRng.fill_bytes(&mut bytes);
|
||||
|
|
@ -60,7 +52,7 @@ pub async fn create_user(username: &str) -> (Option<UserProfile>, Option<String>
|
|||
user_id as i64,
|
||||
username.to_string(),
|
||||
None,
|
||||
STANDARD.encode(&public_key.as_bytes()),
|
||||
public_key_bundle_to_base64(&pub_key_bundle),
|
||||
private_key_hash,
|
||||
reset_token.clone(),
|
||||
);
|
||||
|
|
@ -70,7 +62,7 @@ pub async fn create_user(username: &str) -> (Option<UserProfile>, Option<String>
|
|||
.add_typed_default(DataType::Username, DataValue::Str(username.to_string()))
|
||||
.add_typed_default(
|
||||
DataType::PublicKey,
|
||||
DataValue::Str(public_key_to_base64(&public_key)),
|
||||
DataValue::Str(public_key_bundle_to_base64(&pub_key_bundle)),
|
||||
)
|
||||
.add_typed_default(DataType::IotaId, DataValue::SignedNumber(user_id as i128))
|
||||
.add_typed_default(DataType::ResetToken, DataValue::Str(reset_token));
|
||||
|
|
@ -94,13 +86,13 @@ pub async fn create_user(username: &str) -> (Option<UserProfile>, Option<String>
|
|||
save_file(
|
||||
"",
|
||||
&format!("{}.tu", username),
|
||||
&format!("{}::{}", user_id, STANDARD.encode(&private_key.as_bytes())),
|
||||
&format!("{}::{}", user_id, keyring_b64),
|
||||
);
|
||||
|
||||
add_user(user_profile.clone());
|
||||
save_users();
|
||||
(
|
||||
Some(user_profile),
|
||||
Some(STANDARD.encode(&private_key.as_bytes())),
|
||||
Some(keyring_b64),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue