Some changes to add encrypted chat in nearest future

This commit is contained in:
vysheng 2013-11-02 14:14:30 +04:00
parent c9c1641b70
commit 5b8a4fdc60
3 changed files with 161 additions and 11 deletions

View File

@ -942,7 +942,7 @@ void print_service_message (struct message *M) {
push_color (COLOR_MAGENTA);
if (msg_num_mode) {
printf ("%d ", M->id);
printf ("%lld ", M->id);
}
print_date (M->date);
pop_color ();
@ -1002,7 +1002,7 @@ void print_message (struct message *M) {
if (M->out) {
push_color (COLOR_GREEN);
if (msg_num_mode) {
printf ("%d ", M->id);
printf ("%lld ", M->id);
}
print_date (M->date);
pop_color ();
@ -1017,7 +1017,7 @@ void print_message (struct message *M) {
} else {
push_color (COLOR_BLUE);
if (msg_num_mode) {
printf ("%d ", M->id);
printf ("%lld ", M->id);
}
print_date (M->date);
pop_color ();
@ -1033,7 +1033,7 @@ void print_message (struct message *M) {
} else {
push_color (COLOR_MAGENTA);
if (msg_num_mode) {
printf ("%d ", M->id);
printf ("%lld ", M->id);
}
print_date (M->date);
pop_color ();

View File

@ -23,6 +23,12 @@
#include "telegram.h"
#include "tree.h"
#include "loop.h"
#include <openssl/rand.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
#define sha1 SHA1
int verbosity;
peer_t *Peers[MAX_USER_NUM];
@ -553,7 +559,100 @@ void fetch_geo_message (struct message *M) {
}
}
#define id_cmp(a,b) ((a)->id - (b)->id)
int *decr_ptr;
int *decr_end;
int decrypt_encrypted_message (struct secret_chat *E) {
int *msg_key = decr_ptr;
decr_ptr += 4;
assert (decr_ptr < decr_end);
static unsigned char sha1a_buffer[20];
static unsigned char sha1b_buffer[20];
static unsigned char sha1c_buffer[20];
static unsigned char sha1d_buffer[20];
static unsigned char buf[64];
memcpy (buf, msg_key, 16);
memcpy (buf + 16, E->key, 32);
sha1 (buf, 48, sha1a_buffer);
memcpy (buf, E->key + 8, 16);
memcpy (buf + 16, msg_key, 16);
memcpy (buf + 32, E->key + 12, 16);
sha1 (buf, 48, sha1b_buffer);
memcpy (buf, E->key + 16, 32);
memcpy (buf + 32, msg_key, 16);
sha1 (buf, 48, sha1c_buffer);
memcpy (buf, msg_key, 16);
memcpy (buf + 16, E->key + 24, 32);
sha1 (buf, 48, sha1d_buffer);
static unsigned char iv[32];
memcpy (iv, sha1a_buffer + 0, 8);
memcpy (iv + 8, sha1b_buffer + 8, 12);
memcpy (iv + 20, sha1c_buffer + 4, 12);
static unsigned char key[32];
memcpy (key, sha1a_buffer + 8, 12);
memcpy (key + 12, sha1b_buffer + 0, 8);
memcpy (key + 20, sha1c_buffer + 16, 4);
memcpy (key + 24, sha1d_buffer + 0, 8);
AES_KEY aes_key;
AES_set_decrypt_key (key, 256, &aes_key);
AES_ige_encrypt ((void *)decr_ptr, (void *)decr_ptr, 4 * (decr_end - decr_ptr), &aes_key, iv, 0);
sha1 ((void *)decr_ptr, 4 * (decr_end - decr_ptr), sha1a_buffer);
if (memcmp (sha1a_buffer, msg_key, 16)) {
logprintf ("Sha1 mismatch\n");
return -1;
}
return 0;
}
void fetch_encrypted_message (struct message *M) {
memset (M, 0, sizeof (*M));
unsigned x = fetch_int ();
assert (x == CODE_encrypted_message || x == CODE_encrypted_message_service);
peer_id_t chat = MK_ENCR_CHAT (fetch_int ());
M->id = fetch_long ();
peer_t *P = user_chat_get (chat);
if (!P) {
logprintf ("Encrypted message to unknown chat. Dropping\n");
}
M->date = fetch_int ();
int len = prefetch_strlen ();
assert (!(len & 15));
decr_ptr = (void *)fetch_str (len);
decr_end = in_ptr;
if (P && decrypt_encrypted_message (&P->encr_chat) >= 0) {
in_ptr = decr_ptr;
unsigned x = fetch_int ();
if (x == CODE_decrypted_message_layer) {
int layer = fetch_int ();
assert (layer >= 0);
x = fetch_int ();
}
assert (x == CODE_decrypted_message);
assert (M->id = fetch_long ());
int l = prefetch_strlen ();
fetch_str (l); // random_bytes
M->from_id = MK_USER (fetch_int ());
M->date = fetch_int ();
M->message = fetch_str_dup ();
}
}
static int id_cmp (struct message *M1, struct message *M2) {
if (M1->id < M2->id) { return -1; }
else if (M1->id > M2->id) { return 1; }
else { return 0; }
}
#define peer_cmp(a,b) (cmp_peer_id (a->id, b->id))
DEFINE_TREE(peer,peer_t *,peer_cmp,0)
@ -752,6 +851,26 @@ struct message *fetch_alloc_geo_message (void) {
}
}
struct message *fetch_alloc_encrypted_message (void) {
struct message *M = malloc (sizeof (*M));
fetch_encrypted_message (M);
struct message *M1 = tree_lookup_message (message_tree, M);
messages_allocated ++;
if (M1) {
message_del_use (M1);
free_message (M1);
memcpy (M1, M, sizeof (*M));
free (M);
message_add_use (M1);
messages_allocated --;
return M1;
} else {
message_add_use (M);
message_tree = tree_insert_message (message_tree, M, lrand48 ());
return M;
}
}
struct message *fetch_alloc_message_short (void) {
struct message *M = malloc (sizeof (*M));
fetch_message_short (M);
@ -776,7 +895,7 @@ struct message *fetch_alloc_message_short_chat (void) {
struct message *M = malloc (sizeof (*M));
fetch_message_short_chat (M);
if (verbosity >= 2) {
logprintf ("Read message with id %d\n", M->id);
logprintf ("Read message with id %lld\n", M->id);
}
struct message *M1 = tree_lookup_message (message_tree, M);
messages_allocated ++;
@ -854,13 +973,13 @@ peer_t *user_chat_get (peer_id_t id) {
return tree_lookup_peer (peer_tree, &U);
}
struct message *message_get (int id) {
struct message *message_get (long long id) {
struct message M;
M.id = id;
return tree_lookup_message (message_tree, &M);
}
void update_message_id (struct message *M, int id) {
void update_message_id (struct message *M, long long id) {
message_tree = tree_delete_message (message_tree, M);
M->id = id;
message_tree = tree_insert_message (message_tree, M, lrand48 ());

View File

@ -111,6 +111,26 @@ struct chat {
int admin_id;
};
enum secret_chat_state {
sc_none,
sc_sent_request,
sc_ok,
sc_bad
};
struct secret_chat {
peer_id_t id;
int flags;
char *print_name;
struct file_location photo_big;
struct file_location photo_small;
struct photo photo;
enum secret_chat_state state;
int key[64];
long long key_fingerprint;
};
typedef union peer {
struct {
peer_id_t id;
@ -122,6 +142,7 @@ typedef union peer {
};
struct user user;
struct chat chat;
struct secret_chat encr_chat;
} peer_t;
struct video {
@ -170,7 +191,7 @@ struct message_media {
struct message {
struct message *next_use, *prev_use;
int id;
long long id;
int flags;
peer_id_t fwd_from_id;
int fwd_date;
@ -208,8 +229,8 @@ void free_chat (struct chat *U);
int print_stat (char *s, int len);
peer_t *user_chat_get (peer_id_t id);
struct message *message_get (int id);
void update_message_id (struct message *M, int id);
struct message *message_get (long long id);
void update_message_id (struct message *M, long long id);
void message_insert (struct message *M);
void free_photo (struct photo *P);
void fetch_photo (struct photo *P);
@ -217,13 +238,18 @@ void fetch_photo (struct photo *P);
#define PEER_USER 1
#define PEER_CHAT 2
#define PEER_GEO_CHAT 3
#define PEER_ENCR_CHAT 4
#define PEER_UNKNOWN 0
#define MK_USER(id) set_peer_id (PEER_USER,id)
#define MK_CHAT(id) set_peer_id (PEER_CHAT,id)
#define MK_GEO_CHAT(id) set_peer_id (PEER_GEO_CHAT,id)
#define MK_ENCR_CHAT(id) set_peer_id (PEER_ENCR_CHAT,id)
static inline int get_peer_type (peer_id_t id) {
if (id.id > 1000000000) {
return PEER_ENCR_CHAT;
}
if (id.id > 0) {
return PEER_USER;
}
@ -244,6 +270,8 @@ static inline int get_peer_id (peer_id_t id) {
return -id.id;
case PEER_GEO_CHAT:
return -id.id - 1000000000;
case PEER_ENCR_CHAT:
return id.id - 1000000000;
default:
return 0;
}
@ -261,6 +289,9 @@ static inline peer_id_t set_peer_id (int type, int id) {
case PEER_GEO_CHAT:
ID.id = -id - 1000000000;
return ID;
case PEER_ENCR_CHAT:
ID.id = id + 1000000000;
return ID;
default:
assert (0);
return ID;