MTProto 2.0 session management, DH key exchange, and message framing for Rust.
[dependencies]
ferogram-mtproto = "0.3.0"
ferogram-tl-types = { version = "0.3.0", features = ["tl-mtproto"] }- 3-step DH key exchange (
req_pq_multi→req_DH_params→set_client_DH_params) - Encrypted sessions: AES-IGE pack/unpack, msg_key derivation, salt management
- Message framing: salt, session_id, message_id, sequence numbers
msg_containerandgzip_packedunwrapping- Error recovery:
bad_msg_notification,bad_server_salt,msg_resend_req - Acknowledgements via
MsgsAck - Temporary key binding for PFS (
bind_temp_keymodule, v0.3.0)
Manages the live MTProto session after key exchange.
use ferogram_mtproto::EncryptedSession;
let session = EncryptedSession::new(auth_key, first_salt, time_offset);
let wire_bytes = session.pack(&my_request)?;
let wire_bytes = session.pack_serializable(&raw_obj)?;
let msg = session.unpack(&mut raw_bytes)?;use ferogram_mtproto::authentication as auth;
let (req1, state1) = auth::step1()?;
// send req1, receive res_pq
let (req2, state2) = auth::step2(state1, res_pq)?;
// send req2, receive server_DH_params
let (req3, state3) = auth::step3(state2, dh_params)?;
// send req3, receive dh_answer
let done = auth::finish(state3, dh_answer)?;
// done.auth_key [u8; 256]
// done.first_salt i64
// done.time_offset i32pub struct Message {
pub msg_id: i64,
pub seq_no: i32,
pub salt: i64,
pub body: Vec<u8>, // raw TL bytes
}Used only before an auth key exists, for the initial DH handshake messages.
use ferogram_mtproto::Session;
let mut plain = Session::new();
let framed = plain.pack_plain(&my_handshake_request)?;Every outgoing MTProto message:
server_salt 8 bytes
session_id 8 bytes
message_id 8 bytes (Unix time * 2^32, monotonically increasing)
seq_no 4 bytes
message_length 4 bytes
payload N bytes
padding 12-1024 random bytes (total % 16 == 0)
Prefixed by a 32-byte msg_key after encryption.
msg_key is SHA-256 of (auth_key[88..120] || plaintext) for client-to-server, and (auth_key[96..128] || plaintext) for server-to-client.
Implements PFS temporary key binding. Used by ferogram when connecting to auxiliary DCs.
use ferogram_mtproto::{serialize_bind_temp_auth_key, encrypt_bind_inner, gen_msg_id};
let wire = serialize_bind_temp_auth_key(
&perm_auth_key,
&temp_auth_key,
nonce,
expires_at,
msg_id,
seq_no,
)?;Public re-exports: EncryptedSession, SeenMsgIds, new_seen_msg_ids, gen_msg_id, serialize_bind_temp_auth_key, encrypt_bind_inner.
ferogram
└ ferogram-mtproto <-- here
├ ferogram-tl-types (tl-mtproto feature)
└ ferogram-crypto
MIT or Apache-2.0, at your option. See LICENSE-MIT and LICENSE-APACHE.
Ankit Chaubey - github.com/ankit-chaubey