W
W
wutiarn2014-03-01 17:25:44
Python
wutiarn, 2014-03-01 17:25:44

How to implement websocket traffic encryption between angular application and python server without ssl?

Good afternoon. I am currently developing an application which consists of an angularjs application and a tornado (python) server. All this communicates with each other via websocket (all statics are completely separated. All interaction is only through a socket).
And now it's time to cut the authorization. And there was a pretty serious security problem. The fact is that this project was washed down and forgotten from the category. Those. stuffed the whole thing on the Raspberry Pi, put it away and forgot for 3 (or even more) years. Accordingly, no one will buy ssl.
Using a self-signed certificate is not an option because in this case, browsers will issue warnings, which is absolutely unacceptable. Naturally, it remains to cut all the security yourself.
The most important place in my protocol is given, of course, to authorization. It was decided to do it based on this article. In my case, it looks like this to me:
1. The page with the application is loaded from the statics server and initialized
2. A connection to the server is created
3. As soon as the connection is confirmed by the server, the user is shown an authorization form in which he, in fact, logs in
4. Then the information entered is sent to the angular service and the fun begins there
5. A message with the user login is sent to the server (the protocol is similar to JSONRPC with some differences)
6. The server looks for this login in the database and, if it finds it, generates a random number. This number is then AES encrypted with the hash of the user's password from the database.
7. The client (angular service), having received this response, decrypts the encrypted number (if, of course, the correct password is entered) and enters it into its field.
8. The client now encrypts the password with this number and then sends the result to the server.
9. The server decrypts the message, hashes the received password and compares it with the hash from the database. If everything matches, then it sends a confirmation to the client.
10. After that, the server marks this client (or rather the connection) as authorized and uses this number as a key to encrypt / decrypt all subsequent messages in this connection.
11. The client, having received confirmation, displays to the user all the beauties of the interface. From now on, it also encrypts all messages using that same number.
That, in fact, is all. This seems like the perfect fit to me. But I'm left with a whole bunch of questions. I will state them in order:
As far as I understand, in AES everything must be a multiple of 16. Ie. and the length of the key and the length of the encrypted message. Otherwise, it's just not possible. Well, here I swindled some solution, but it seems too crutch to me:

from Crypto.Cipher import AES
import base64

BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]

class AESCipher:
    def __init__( self, key ):
        self.key = key

    def encrypt( self, raw ):
        raw = pad(raw)
        cipher = AES.new(self.key, AES.MODE_ECB)
        return base64.b64encode(cipher.encrypt( raw ))

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        cipher = AES.new(self.key, AES.MODE_ECB)
        return unpad(cipher.decrypt(enc).decode())

Even if we assume that this will work (well, in fact it can already successfully encrypt / decrypt messages of its own production), then how to drag all this to the client side? Let's assume that I was able to push all this disgrace through my protocol to the client side. But how to decipher it is not clear.
Initially, I planned to use the Chris'a Veness'a library mentioned in the article on Habré on the client side . But she added even more perplexity to my unstable state. The usage example says:
var password = 'L0ck it up saf3';
 var plaintext = 'pssst ... đon’t tell anyøne!';
 var ciphertext = Aes.Ctr.encrypt(plaintext, password, 256);
 var origtext = Aes.Ctr.decrypt(ciphertext, password, 256);

That is, when encrypting, both the key and a certain number of bits are indicated. Yes Yes. It is the "number of bits", because I do not understand why this is needed. I have always firmly believed that 128, 256 in the context of encryption is nothing more than the length of the key. But the key is specified manually. It turns out that it is simply concatenated a certain number of times until the desired length is obtained? Or do I really not understand anything?
By the way, Wikipedia says :
Block size 128 bits, key 128/192/256 bits
. But why then did PyCrypto accept a 16-bit key?
In general, I hope the concept of all this is clear. Can someone explain to me how to implement the plan written above?
Ps Some technical details:
* Python 3.2
* Raspbian (Debian)
* Angular 1.2.13
Pps The ideal option is to find an AES library for the third python similar to a library similar to Chris'a Veness'a library .
Ppp....S: Libraries from here did not start on the configuration described above. If you have any ideas how to adapt them - I will be very grateful.
UPD: Continued here: PyCrypto + CryptoJS

Answer the question

In order to leave comments, you need to log in

2 answer(s)
P
pomeo, 2014-03-01
@pomeo

$12 for 3 years, ridiculous money https://www.gogetssl.com/domain-validation/comodo-...

A
Andrew, 2014-03-01
@OLS

The implementation you mentioned takes as the second parameter a character string - the password , not the key .
And turning the password into a key is not very correct: it takes the first either 128, or 192, or 256 bits from the UTF-8 representation of the password and uses it as a key after some transformation over them. For good, of course, you need to use the hash of the entire password as a key, and the author himself mentions this.
That's why the author has a number as the third parameter, which can take only one of three values ​​- 128, 192 or 256.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question