Example #1
0
        public static byte[] GetJsonEncoded(Context context, IJType message, long receiverId, byte[] attechment = null)
        {
            byte[] aesBinKey = context.Contacts
                               .Where(u => u.PublicId == receiverId)
                               .Select(u => u.SendAesKey)
                               .SingleOrDefault();

            AESPassword key = new AESPassword(aesBinKey);

            MemoryStream stream = new MemoryStream();

            BinaryEncoder.SendInt(stream, (int)message.GetJsonType());

            string json = JsonConvert.SerializeObject(message);

            TextEncoder.SendString(stream, json);

            if (attechment == null)
            {
                BinaryEncoder.SendInt(stream, 0);
            }
            else
            {
                BinaryEncoder.SendInt(stream, 1);
                BinaryEncoder.SendBytes(stream, attechment);
            }

            byte[] notEncrypted = stream.ToArray();
            return(key.Encrypt(notEncrypted));
        }
Example #2
0
        public void TrustContact(int contactId)
        {
            Pull();
            Log("Sending TRUST_CONTACT command.");
            TextEncoder.SendCommand(stream, ConnectionCommand.TRUST_CONTACT);

            TextEncoder.SendInt(stream, contactId);
            using (Context context = new Context(config))
            {
                var contact = context.Contacts
                              .Where(u => u.PublicId == contactId)
                              .SingleOrDefault();
                contact.Trusted = 1;
                context.SaveChanges();

                if (contact.SendAesKey == null)
                {
                    AESPassword password = AESPassword.GenerateAESPassword();
                    JAESKey     key      = new JAESKey(contactId, password);
                    PushOperations.SendIJType(context, key, UserId, UserId);

                    X509Certificate2 cert = X509Certificate2Utils.ImportFromPem(
                        context.Contacts
                        .Where(u => u.PublicId == contactId)
                        .Select(u => u.PublicCertificate)
                        .SingleOrDefault());
                    BinaryEncoder.SendBytes(stream, RSAEncoder.Encrypt(password.Password, cert));

                    context.SaveChanges();
                }
            }
            Push();
        }
Example #3
0
        public static byte[] EncryptAndSign(byte[] data, X509Certificate2 receiverCert, X509Certificate2 myCert)
        {
            RSA publicKey = receiverCert.GetRSAPublicKey();

            MemoryStream stream = new MemoryStream();

            byte[] encrypted = publicKey.Encrypt(data, encryptionPadding);
            byte[] signiture = Sign(data, myCert);

            BinaryEncoder.SendBytes(stream, signiture);
            BinaryEncoder.SendBytes(stream, encrypted);

            stream.Flush();
            return(stream.GetBuffer());
        }
Example #4
0
        public static HandshakeReturnCapsula Login(Logger logger, Stream stream, X509Certificate2 cert, string password, string userName = null, int?clientId = null)
        {
            ClientHandshake clientHandshake = new ClientHandshake()
            {
                PemCertificate = X509Certificate2Utils.ExportToPem(cert),
                UserName       = userName,
                ClientId       = clientId,
                ServerPassword = password
            };

            if (userName != null && userName.Length > DataConstants.USER_NAME_MAX_LENGHT)
            {
                throw new Exception("Username is too long.");
            }

            TextEncoder.SendJson(stream, clientHandshake);

            byte[] encrypted = BinaryEncoder.ReceiveBytes(stream);
            byte[] decrypted = RSAEncoder.Decrypt(encrypted, cert);
            BinaryEncoder.SendBytes(stream, decrypted);

            ServerHandshake serverHandshake = TextEncoder.ReadJson <ServerHandshake>(stream);

            logger.Log("Handshake", "Handshake", serverHandshake.Errors, false);

            if (!serverHandshake.Succeeded)
            {
                throw new Exception($"Handshake failed\n{serverHandshake.Errors}");
            }

            return(new HandshakeReturnCapsula()
            {
                UserId = serverHandshake.UserId,
                UserName = serverHandshake.UserName,
                ClientId = serverHandshake.ClientId,
                SelfAesPassword = serverHandshake.SelfAesKey == null ? null : new AESPassword(RSAEncoder.DecryptAndVerify(serverHandshake.SelfAesKey, cert, cert))
            });
        }
Example #5
0
        public static ConnectionInfo Run(Stream stream, Action <string> log, ServerConfig config)
        {
            ClientHandshake  clientHandshake   = TextEncoder.ReadJson <ClientHandshake>(stream);
            X509Certificate2 clientCertificate = X509Certificate2Utils.ImportFromPem(clientHandshake.PemCertificate);

            log($"Logging user sent username {clientHandshake.UserName}\n Certificate:\n {clientHandshake.PemCertificate}");

            ServerHandshake errorHandshake = new ServerHandshake()
            {
                Errors    = "",
                NewUser   = false,
                Succeeded = false,
                UserId    = -1,
                UserName  = ""
            };

            if (config.Password != null && !config.Password.Equals(clientHandshake.ServerPassword))
            {
                errorHandshake.Errors = "Server password is wrong.";
                TextEncoder.SendJson(stream, errorHandshake);
                throw new Exception(errorHandshake.Errors);
            }

            log("Generating random bytes");
            byte[] randomBytes = LUtils.GenerateRandomBytes(TcpConstants.HANDSHAKE_LENGHT);

            log("Sending encrypted bytes");
            BinaryEncoder.SendBytes(stream, RSAEncoder.Encrypt(randomBytes, clientCertificate));

            byte[] received = BinaryEncoder.ReceiveBytes(stream);
            if (!randomBytes.SequenceEqual(received))
            {
                log("Client's certificate verification failed.");
                errorHandshake.Errors = "Client's certificate verification failed.";
                TextEncoder.SendJson(stream, errorHandshake);
                throw new Exception(errorHandshake.Errors);
            }

            log("Certificate verification succeeded.");

            Users   user;
            String  message;
            Clients client;

            byte[] aesKey  = null;
            bool   newUser = false;

            using (Context context = new Context(config))
            {
                byte[] hash = SHA256Utils.ComputeByteSha256Hash(clientCertificate);
                user = context.Users.SingleOrDefault(u => u.PublicCertificateSha256.SequenceEqual(hash));

                if (user == null)
                {
                    log("User doesn't exist yet. I'll try to create him.");
                    newUser = true;

                    log("Checking the uniquity of username.");
                    String userName = clientHandshake.UserName;
                    if (context.Users.SingleOrDefault(u => u.UserName.Equals(userName)) != null)
                    {
                        errorHandshake.Errors = "Username isn't unique.";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }
                    else if (userName.Length > 45)
                    {
                        errorHandshake.Errors = "Username is too long (max. 45 chars)";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }
                    else if (userName.Length < 4)
                    {
                        errorHandshake.Errors = "Username is too short (min. 4 chars)";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }
                    else if (!Validators.ValidateRegexUserName(userName))
                    {
                        errorHandshake.Errors = "Username must match this regex ^[a-zA-Z][-a-zA-Z0-9_]+$ (Vaguely can't contain special chars and spaces)";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }

                    log("Creating user.");
                    user = new Users()
                    {
                        PublicCertificate       = clientHandshake.PemCertificate,
                        PublicCertificateSha256 = hash,
                        UserName = clientHandshake.UserName
                    };

                    context.Users.Add(user);
                    context.SaveChanges();

                    message = "User successfully created.";
                    log("User successfully created.");
                }
                else
                {
                    message = "User exists.";
                    log("User exists.");
                }

                client = new Clients()
                {
                    UserId = user.Id
                };

                if (clientHandshake.ClientId == null)
                {
                    log($"Loading self-aes key.");
                    aesKey = context.UsersKeys
                             .Where(u => u.RecepientId == user.Id)
                             .Where(u => u.SenderId == user.Id)
                             .Select(u => u.AesKey)
                             .SingleOrDefault();

                    context.Add(client);
                    context.SaveChanges();

                    log($"Added client with Id {client.Id}.");
                }
                else
                {
                    client.Id = (int)clientHandshake.ClientId;
                    if (context.Clients.Where(u => u.Id == client.Id).Single().UserId != user.Id)
                    {
                        errorHandshake.Errors = "This client id isn't owned by this user.";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }

                    log($"Client with Id {client.Id} has logged in.");
                }
            }

            ServerHandshake toSend = new ServerHandshake()
            {
                Errors     = message,
                NewUser    = newUser,
                Succeeded  = true,
                UserId     = user.Id,
                UserName   = user.UserName,
                ClientId   = client.Id,
                SelfAesKey = aesKey
            };

            TextEncoder.SendJson(stream, toSend);

            ConnectionInfo ret = new ConnectionInfo(user, clientCertificate, client.Id);

            log($"Handshake successeded. User {ret.UserName} with id {ret.UserId} has logged in. Client has id {client.Id}.");
            return(ret);
        }
Example #6
0
        public void TrustContact(int contactId)
        {
            ThrowExceptionIfNotConnected();

            Pull();
            lock (mutex)
            {
                Log("Sending TRUST_CONTACT command.");
                BinaryEncoder.SendCommand(stream, ConnectionCommand.TRUST_CONTACT);

                BinaryEncoder.SendInt(stream, contactId);
                using (Context context = new Context(config))
                {
                    var contact = new UContact(context.Contacts
                                               .Where(u => u.PublicId == contactId)
                                               .SingleOrDefault())
                    {
                        Trusted = true
                    };


                    if (contact.SendAesKey == null)
                    {
                        Log("Sending new key.");
                        BinaryEncoder.SendInt(stream, 1);
                        AESPassword password = AESPassword.GenerateAESPassword();

                        contact.SendAesKey = password.Password;
                        X509Certificate2 recepientCert = X509Certificate2Utils.ImportFromPem(
                            context.Contacts
                            .Where(u => u.PublicId == contactId)
                            .Select(u => u.PublicCertificate)
                            .SingleOrDefault());

                        byte[] toSend = RSAEncoder.EncryptAndSign(password.Password, recepientCert, MyCertificate);
                        BinaryEncoder.SendBytes(stream, toSend);
                    }
                    else
                    {
                        Log("No new key will be sended.");
                        BinaryEncoder.SendInt(stream, 0);
                    }

                    if (contactId != this.UserId)
                    {
                        PushOperations.SendJsonCapsula(context, contact.GetSelfUpdate(), UserId, UserId);
                    }
                    else
                    {
                        var me = context.Contacts
                                 .Where(u => u.PublicId == UserId)
                                 .Single();
                        me.SendAesKey    = contact.SendAesKey;
                        me.ReceiveAesKey = contact.ReceiveAesKey;
                    }

                    context.SaveChanges();
                }
                Log("Trustification has been done.");
            }
            Push();
        }
Example #7
0
        public void Push()
        {
            ThrowExceptionIfNotConnected();
            lock (mutex)
            {
                Log("Sending PUSH command.");
                BinaryEncoder.SendCommand(stream, ConnectionCommand.PUSH);
                using (Context context = new Context(config))
                {
                    List <long> selfMessages = new List <long>();
                    var         toSend       = context.ToSendMessages.ToList();

                    PushCapsula capsula = new PushCapsula();

                    foreach (var message in toSend)
                    {
                        if (message.RecepientId == UserId)
                        {
                            selfMessages.Add((long)message.BlobMessagesId);
                        }
                        capsula.PushMessages.Add(new PushMessage()
                        {
                            RecepientId = (int)message.RecepientId,
                            Priority    = (int)message.Priority
                        });
                    }
                    capsula.MessageToDeleteIds = context.BlobMessages
                                                 .Where(u => u.DoDelete == 1)
                                                 .Select(u => (long)u.PublicId).ToList();

#if (DEBUG)
                    Log($"Sending capsula with {toSend.Count} messages. {capsula.MessageToDeleteIds.Count} will be deleted.");
#endif
                    TextEncoder.SendJson(stream, capsula);
#if (DEBUG)
                    Log($"Sending message blobs.");
#endif
                    foreach (var message in toSend)
                    {
                        BinaryEncoder.SendBytes(stream, message.Blob);
                    }
#if (DEBUG)
                    Log($"Receiving PushResponse");
#endif
                    PushResponse response        = TextEncoder.ReadJson <PushResponse>(stream);
                    var          selfMessagesZip = selfMessages.Zip(response.MessageIds, (u, v) =>
                                                                    new { PrivateId = u, PublicId = v });

                    foreach (var message in selfMessagesZip)
                    {
                        context.BlobMessages.Where(u => u.Id == message.PrivateId)
                        .SingleOrDefault().PublicId = message.PublicId;
                    }
#if (DEBUG)
                    Log("Saving new public ids.");
#endif
                    context.SaveChanges();
#if (DEBUG)
                    Log("Cleaning queue.");
#endif
                    context.Database.ExecuteSqlCommand("delete from TO_SEND_MESSAGES;");
                    context.Database.ExecuteSqlCommand("delete from BLOB_MESSAGES where DO_DELETE=1 and PUBLIC_ID<>null;;");
                    context.SaveChanges();
                }

                Log("Push have been done.");
            }
        }
Example #8
0
        public static UserCapsula Run(Stream stream, Action <string> log, ServerConfig config)
        {
            ClientHandshake  clientHandshake   = TextEncoder.ReadClientHandshake(stream);
            X509Certificate2 clientCertificate = X509Certificate2Utils.ImportFromPem(clientHandshake.PemCertificate);

            log($"Logging user sent username {clientHandshake.UserName}\n Certificate:\n {clientHandshake.PemCertificate}");

            log("Generating random bytes");
            byte[] randomBytes = LUtils.GenerateRandomBytes(TcpConstants.HANDSHAKE_LENGHT);

            log("Sending encrypted bytes");
            BinaryEncoder.SendBytes(stream, RSAEncoder.Encrypt(randomBytes, clientCertificate));

            ServerHandshake errorHandshake = new ServerHandshake()
            {
                Errors    = "",
                NewUser   = false,
                Succeeded = false,
                UserId    = -1,
                UserName  = ""
            };

            byte[] received = BinaryEncoder.ReceiveBytes(stream);
            if (!randomBytes.SequenceEqual(received))
            {
                log("Sending error to client.");
                errorHandshake.Errors = "Client's certificate verification failed.";
                TextEncoder.SendJson(stream, errorHandshake);
                throw new Exception(errorHandshake.Errors);
            }

            log("Certificate verification succeeded.");

            Users   user;
            String  message;
            Clients client;
            bool    newUser = false;

            using (Context context = new Context(config))
            {
                SHA1   sha  = new SHA1CryptoServiceProvider();
                byte[] hash = sha.ComputeHash(clientCertificate.RawData);
                user = context.Users.SingleOrDefault(u => u.PublicCertificateSha1.SequenceEqual(hash));

                if (user == null)
                {
                    log("User doesn't exist yet. I'll try to create him.");
                    newUser = true;

                    log("Checking the uniquity of username.");
                    String userName = clientHandshake.UserName;
                    if (context.Users.SingleOrDefault(u => u.UserName.Equals(userName)) != null)
                    {
                        log("Username isn't unique.");
                        errorHandshake.Errors = "Username isn't unique.";
                        TextEncoder.SendJson(stream, errorHandshake);
                        throw new Exception(errorHandshake.Errors);
                    }

                    log("Creating user.");
                    user = new Users()
                    {
                        PublicCertificate     = clientHandshake.PemCertificate,
                        PublicCertificateSha1 = hash,
                        UserName = clientHandshake.UserName
                    };

                    context.Users.Add(user);
                    context.SaveChanges();

                    message = "User successfully created.";
                    log("User successfully created.");
                }
                else
                {
                    message = "User exists.";
                    log("User exists.");
                }

                client = new Clients()
                {
                    UserId = user.Id
                };

                if (clientHandshake.ClientId == null)
                {
                    context.Add(client);
                    context.SaveChanges();

                    log($"Added client with Id {client.Id}.");
                }
                else
                {
                    log($"Client with Id {client.Id} has logged in.");
                }
            }

            ServerHandshake toSend = new ServerHandshake()
            {
                Errors    = message,
                NewUser   = newUser,
                Succeeded = true,
                UserId    = user.Id,
                UserName  = user.UserName,
                ClientId  = client.Id
            };

            TextEncoder.SendJson(stream, toSend);

            UserCapsula ret = new UserCapsula(user, clientCertificate);

            log($"Handshake successeded. User {ret.UserName} with id {ret.UserId} has logged in");
            return(ret);
        }
Example #9
0
        private void Push()
        {
#if (DEBUG)
            Log("Pushing started.");
#endif
            ClientPullCapsula clientPullCapsula = TextEncoder.ReadJson <ClientPullCapsula>(stream);

            using (Context context = new Context(config))
            {
                ServerPullCapsula capsula = new ServerPullCapsula();

                List <byte[]> messagesBlobsToSend = new List <byte[]>();
                List <byte[]> aesBlobsToSend      = new List <byte[]>();

                var messagesIdsUploaded = context.ClientsMessagesDownloaded
                                          .Where(u => u.ClientsId == connectionInfo.ClientId)
                                          .Select(u => u.BlobMessagesId);

                List <PullMessage> pullMessages = new List <PullMessage>();
                foreach (var message in
                         from messages in context.BlobMessages
                         orderby messages.Priority descending, messages.Id ascending                 //Message order must be respected
                         where messages.RecepientId == connectionInfo.UserId                         //Messages of connected user
                         where !messagesIdsUploaded.Contains(messages.Id)                            //New messages

                         join keys in context.UsersKeys on messages.RecepientId equals keys.SenderId //Keys sended by connected user
                         where keys.Trusted == true                                                  //Only trusted
                         where messages.SenderId == keys.RecepientId                                 //Trusted information just only about sending user
                         select new { messages.SenderId, messages.Content, messages.Id }
                         )
                {
                    pullMessages.Add(new PullMessage()
                    {
                        PublicId = message.Id,
                        SenderId = message.SenderId
                    });
                    messagesBlobsToSend.Add(message.Content);
                    context.ClientsMessagesDownloaded.Add(new ClientsMessagesDownloaded()
                    {
                        BlobMessagesId = message.Id,
                        ClientsId      = connectionInfo.ClientId
                    });
                }
                capsula.Messages = pullMessages;
#if (DEBUG)
                Log($"{messagesBlobsToSend.Count} messageBlobs will be pushed.");
#endif
                capsula.AesKeysUserIds = new List <long>();
                foreach (var user in
                         from userKeys in context.UsersKeys
                         where userKeys.RecepientId == connectionInfo.UserId
                         where clientPullCapsula.AesKeysUserIds.Contains(userKeys.SenderId)
                         select new { userKeys.SenderId, userKeys.AesKey })
                {
                    capsula.AesKeysUserIds.Add(user.SenderId);
                    aesBlobsToSend.Add(user.AesKey);
                }
#if (DEBUG)
                Log($"{capsula.AesKeysUserIds.Count} AES keys will be pushed.");
                Log($"Sending PullCapsula.");
#endif
                TextEncoder.SendJson(stream, capsula);
#if (DEBUG)
                Log($"Sending AES keys.");
#endif
                foreach (byte[] data in aesBlobsToSend)
                {
                    BinaryEncoder.SendBytes(stream, data);
                }
#if (DEBUG)
                Log($"Sending Messages content.");
#endif
                foreach (byte[] data in messagesBlobsToSend)
                {
                    BinaryEncoder.SendBytes(stream, data);
                }
                stream.Flush();
                context.SaveChanges();
            }
#if (DEBUG)
            Log("Pushing completed.");
#endif
        }
Example #10
0
        private void Push()
        {
#if (DEBUG)
            Log("Pushing started.");
#endif
            using (Context context = new Context(config))
            {
                PullCapsula capsula = new PullCapsula();

                List <PullUser> pullUsers = new List <PullUser>();
                foreach (Users user in context.Users.Where(u => !userIdsUploaded.Contains(u.Id)))
                {
                    PullUser pullUser = new PullUser()
                    {
                        PublicCertificate = user.PublicCertificate,
                        UserId            = user.Id,
                        UserName          = user.UserName
                    };
                    pullUsers.Add(pullUser);
                    userIdsUploaded.Add(user.Id);
                }
                capsula.Users = pullUsers;
#if (DEBUG)
                Log($"{pullUsers.Count} users will be pushed.");
#endif

                capsula.TrustedUserIds = new List <long>();
                foreach (var userId in (
                             from userKeys in context.UsersKeys
                             where userKeys.Trusted == true && userKeys.SenderId == user.UserId
                             select new { userKeys.RecepientId }))
                {
                    capsula.TrustedUserIds.Add(userId.RecepientId);
                }
#if (DEBUG)
                Log($"{capsula.TrustedUserIds.Count} users is trusted by host.");
#endif

                List <byte[]> messagesBlobsToSend = new List <byte[]>();
                List <byte[]> aesBlobsToSend      = new List <byte[]>();

                List <PullMessage> pullMessages = new List <PullMessage>();
                foreach (var message in
                         from messages in context.BlobMessages
                         orderby messages.Id ascending                                               //Message order must be respected
                         where messages.RecepientId == user.UserId                                   //Messages of connected user
                         where !messagesIdsUploaded.Contains(messages.Id)                            //New messages

                         join keys in context.UsersKeys on messages.RecepientId equals keys.SenderId //Keys sended by connected user
                         where keys.Trusted == true                                                  //Only trusted
                         where messages.SenderId == keys.RecepientId                                 //Trusted information just only about sending user
                         select new { messages.SenderId, messages.Content, messages.Id }
                         )
                {
                    pullMessages.Add(new PullMessage()
                    {
                        PublicId = message.Id,
                        SenderId = message.SenderId
                    });
                    messagesBlobsToSend.Add(message.Content);
                    messagesIdsUploaded.Add(message.Id);
                }
                capsula.Messages = pullMessages;
#if (DEBUG)
                Log($"{messagesBlobsToSend.Count} messageBlobs will be pushed.");
#endif
                capsula.AesKeysUserIds = new List <long>();
                foreach (var user in
                         from userKeys in context.UsersKeys
                         where userKeys.RecepientId == user.UserId
                         where !aesKesUserIdsUploaded.Contains(userKeys.SenderId)
                         select new { userKeys.SenderId, userKeys.EncryptedAesKey })
                {
                    capsula.AesKeysUserIds.Add(user.SenderId);
                    aesKesUserIdsUploaded.Add(user.SenderId);
                    aesBlobsToSend.Add(user.EncryptedAesKey);
                }
#if (DEBUG)
                Log($"{capsula.AesKeysUserIds.Count} AES keys will be pushed.");
                Log($"Sending PullCapsula.");
#endif
                TextEncoder.SendJson(stream, capsula);
#if (DEBUG)
                Log($"Sending AES keys.");
#endif
                foreach (byte[] data in aesBlobsToSend)
                {
                    BinaryEncoder.SendBytes(stream, data);
                }
#if (DEBUG)
                Log($"Sending Messages content.");
#endif
                foreach (byte[] data in messagesBlobsToSend)
                {
                    BinaryEncoder.SendBytes(stream, data);
                }
            }
#if (DEBUG)
            Log("Pushing completed.");
#endif
        }