Skip to content
Permalink
Browse files

Update README.md

  • Loading branch information
john committed Apr 24, 2017
1 parent c57df8e commit d68d596252b10ce60aec84ba5efcaadd72c6c5e8
Showing with 78 additions and 1 deletion.
  1. +78 −1 README.md
@@ -1 +1,78 @@
# cse4707-secure-messaging
# Project 04: Building a secure messaging system

In this project, I've extended the set of features for the secure login website to include messaging.

The website is being hosted on [cmpsec.johnbojorquez.com](https://cmpsec.johnbojorquez.com).

The website supports single-recipient messages between users. All messages are sent over an SSL connection between the client and the server. Messages are also encrypted before they are stored in the database.

## Database schema

To create the application's database, messages table, users table, and initial users we can run
```
php app\database\init.php
```
in the application directory.

The database initialization script in this project will create a `messages` table. The scheme of the `messages` table is as follows:

| Field | Type | Null | Key | Default | Extra |
|-------------|-----------------|------|-----|---------|----------------|
| id | int(10) unsigned| NO | PRI | NULL | auto_increment |
| message | text | NO | | NULL | none |
| sender_id | int(10) unsigned| NO | MUL | NULL | none |
| receiver_id | int(10) unsigned| NO | MUL | NULL | none |
| enc_keys | varchar(64) | NO | | NULL | none |
| keys_iv | varchar(24) | NO | | NULL | none |
| message_iv | varchar(24) | NO | | NULL | none |

This project makes use of the MVC design pattern and new messages are inserted into the database as follows:

```php
$m = new SecureMessage;
$m->message = "Hello, world!";
$m->sender_id = 1;
$m->receiver_id = 2;
$m->save();
```

It's important to notice that the `SecureMessage::save()` method will encrypt the message prior to inserting into
the `messages` table;

The `SecureMessage` class also supports several static methods for retrieving users from the `users` table in the form of a `User` object.

## Protecting the contents of the `messages` table

The goal of this project is to devise a strategy for securely storing messages on the server. This is done by encrypting the messages before storing them in the `messages` table. I have adopted the following strategy. When a user submits a message to be "sent" to another user, two 16-byte keys are generated:
```php
$integrity_key = openssl_random_pseudo_bytes(16);
$encryption_key = openssl_random_pseudo_bytes(16);
```
A 64-byte keyed hash is generated using the SHA256 hashing algorithm:
```php
$message_hash = hash_hmac(Config::hash_algo, $this->message, $integrity_key);
```
This hash is stored in the database to protect the integrity of the message. That is, any unauthorized changes
to the message itself can be easily detected. Next, we generate a random 16-byte IV and encrypt the message and its hash using the AES-128-CBC encryption algorithm.
```php
$message_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(Config::encr_algo));
$ciphertext = openssl_encrypt($this->message . $message_hash, Config::encr_algo, $encryption_key, 0, $message_iv);
```
Lastly, the keys are encrypted using a secret 16-byte key stored on the server.
```php
$keys_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length(Config::encr_algo));
$enc_keys = openssl_encrypt($integrity_key . $encryption_key, Config::encr_algo, Config::secret_key, 0, $keys_iv);
```

To retrieve a message from the database, its keys are decrypted using the system key. Then the message itself is decrypted using its own key.


## Detecting changes to the contents of a message

When retrieving entries from the `messages` table, the hash is recomputed by hashing the message content using the integrity key, the produced hash is then compared with the hash that is stored in the database. If the hashes differ, the message has been altered and is thus discarded.

## Protection against man-in-the-middle attacks

To ensure that the communication between the client and the server is protected, apache has been configured to used HTTPS (with the SSL protocol) for all communication. Using HTTPS requires the exchange of an SSL certificate. For the purpose of this project, a self-signed certificate was generated and stored on the server. This will ensure that all communication between the user's browser and the server is securely encrypted using public key encryption.

The downside of using a self-signed certificate is that the HTTPS connection, although encrypted, does not appear as a secure connection to the user's browser. This is because the certificate is not signed by a trusted authority. Although this still prevents against man-in-the-middle attacks with exchanging sensitive user-related information after the SSL handshake, this still opens the possibility of a man-in-the-middle attack during the handshake. There is no way for the user's browser to prevent attackers from providing their own certificate and tricking the user into giving the attacker their account login information. The solution to this problem is to purchase a signed certificate from a trusted authority.

0 comments on commit d68d596

Please sign in to comment.
You can’t perform that action at this time.