Question

So assume you have two clients, C1 and C2, each client has a GUID associated with it.

How do you, when you receive a message on C2 that supposedly comes from C1 (by checking the GUID and seeing that it matches the GUID of C1), but since the message is not guaranteed to have come from C1 (C3 might just have sent the message, sending the GUID of C1 in the message header) there has to be some verification that the message actually came from C1.

I've been looking into using asymmetric encryption (RSA) to have C1 send a message that consists of [C1.GUID; RSAEncrypt(C2.PUBLIC_KEY, C1.GUID); MESSAGE], and then let C2 basically do a check like this (python pseudo code):

message.GUID == RSADecrypt(C2.PRIVATE_KEY, message.ENCRYPTED_GUID)

Is this a viable approach? Or is there some other clever/more obvious way to verify the sender of a message?

Was it helpful?

Solution

Assymmetric Algorithms have been invented for such purposes, that's the way digital signatures work.

However, your approach has some problems. Anyone with the public key of the recipient could fake the signature. Also, the signature does not change at all! Anyone intercepting the messages can fake being a valid sender. The purpose of assymetric encryption is to defeat these problems with key exchanges, there's the concept of the digital signature, which is basically an assymetrically encrypted hash of the message you are tossing around.

For RSA, you need to do a bit more in order to create a digital signature from the basic algorithm, see wikipedia for more details: http://en.wikipedia.org/wiki/RSA#Signing_messages

I'd just use a digital signature algorithm from a library. First google search turns up with this for Python:

http://www.example-code.com/python/pythonrsa.asp

http://www.chilkatsoft.com/dsa-python.asp

OTHER TIPS

The problem with this method is that any machine could then capture the guid and rsa-encrypted-guid and pass them just the same. You haven't really created any unique challenge/response criteria that can only be divined by the receiving client. What you would need would be something that is completely unique and can't be gotten simply by looking at passed parameters. Maybe something like:

[ClientName; RSA-ENCRYPTED(GUID+Timestamp); MESSAGE]

In this method, the RSA encryption would be done using Client2's public key so that only Client2's private key could unlock it. Using the ClientName, Client2 could retrieve the expected GUID from a datasource, and then match the returned GUID against the one in the encryption. I incorporated the usage of a timestamp as a salt so that the encrypted string comes out differently each time. It's considered very weak to use a timestamp as a randomization for a salt, but it gets the point across. Other more secure/random algorithms could be implemented.

Anyone spying messages between a client and the server will be able to forge new messages, has client's GUID never change, nor RSA-ENCRYPTED-GUID.

Consider switching to this message model : [GUID; ENCRYPTED_CONTENT_CHECKSUM; CONTENT].

Checksum(message.CONTENT) == 
    RSADescrypt(C1.PUBLIC_KEY, message.ENCRYPTED_CONTENT_CHECKSUM)

Still, anyone spying messages can resend previously sent messages.

Public and private keys are the way to go. I will assume you don't care about encrypting the data, but you do care that the data is "authorized".

Lets say you have 3 computers

Comp1 Comp2 Comp3

Lets also say you want Comp1 to send a message to Comp3. you don't care if the message was intercepted, but you do care that it was not forged.

Comp1 will digitally sign the message with its private key

Comp2 will intercept the message from Comp1 to Comp3, but can't change the message without invalidating the signature

Comp2 will forward the message onto Comp3

Comp3 will use Comp1's public key to decrypt the signature and use the hash in the signature to validate the contents.

Now if you want to encrypt the data, you need to add an extra step

Comp1 will digitally sign the message with its private key

Comp1 will generate an random encryption key(typically AES) and encrypt the message.

Comp1 will take that encryption key and encrypt it with Comp3's public key

Comp2 will intercept the message, but cannot read it without Comp3's private key

Comp2 will forward the message onto Comp3

Comp3 will use it's private key to decrypt the AES key

Comp3 will decrypt the entire message using the AES key

Comp3 will validate the message by decrypting the signature with Comp1's public key.

Signature contains a hash of the message, if the hash and the message's hash match, then the data is intact.

You can include the GUIDs in the payload to use as a lookup to decide which public keys to use.

P.S. You will want to use the built in methods to sign a message. Let the Framework do the hashing/etc

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top