Note: You are currently viewing documentation for Moodle 2.9. Up-to-date documentation for the latest stable version of Moodle may be available here: MNet keys.
Public Key Encryption
Public-key encryption is a tricky subject. It's a tricky subject because it's easy to understand 'just enough' to use it, but can be hard to understand it enough to develop real trust in what the process tells you.
But like many things, good things take time/money/brainpower (pick one). As a central pillar of mnet[*], the main concepts of public key encryption are well worth understanding.
When you enable Mnet your Moodle generates a public/private keypair. The two keys (public and private) are strongly related, but their functions are very different.
- The private key is the secret, your moodle server keeps this to itself. It's unlikely that this is even shown to the administrator, (since they don't need to know it), but it's hidden behind the scenes and is very important.
- The public key can be given out freely. You can see your Moodle's public key when you click "Networking" -> "Settings" in the Site Administration block on the main page.
How it works
- Using your private key and cryptography mathematics, you can read a byte string (eg a text message), and output a signature for that byte string. Even though they don't have your private key, anyone who has your public key can process the combination of message, signature, and public key to confirm that it was your private key that generated the signature. If anyone has tampered with the message or the signature (or indeed made up the message&signature entirely) the signature check will fail and you will know that the message is untrustworthy. If the check passes, you know beyond a shadow of a doubt that whoever generated the signature is in possession of the private key.
- Signing a message is so that the remote end knows the message is from you. You need a private key to generate a signature, but you only the corrosponding public key to verify that the signature is genuine - this is how you know the message is genuine, only someone with the private key could have generated a valid signature.
- Using your public key and different cryptography mathematics, anyone with your public key can transform a byte string such that it can only be decrypted by your private key. Anyone else in possession of the transformed text (particularly people along an insecure transmission path) will be unable to read it. If you have encrypted a message then you know for certain that anyone that can decrypt that message is in possession of the private key.
- Encrypting a message is so that only the designated destination can read it. You only need a public key to encrypt a message, but once you've done this, only the corresponding private key can decrypt it. This is how you know that only the destination can read the message - nobody else has their private key to decrypt it.
How this applies to MNET
When you tell two nodes to connect to one another (MoodleA and MoodleB), they exchange public keys, and you click the button on each node to say "yes, trust that this public key came unmodified from the remote node"
- On MoodleA
- MoodleA signs the XML-RPC Request it's sending (using its private key).
- MoodleA then encrypts the result (message+signature) using its record of MoodleB's public key.
- In transit
- (encrypted(message+signature)) is sent from MoodleA to MoodleB via the internet (ie an insecure medium).
- On Moodle B
- MoodleB decrypts the message using its private key,
- Using its record of MoodleA's public key, MoodleB checks the signature of the message, if it checks out, it processes the request.
- Moodle B responds with an encrypted(signed(result))
Through the magic of public key encryption, MoodleB knows for sure that the xmlrpc request came from MoodleA, and nobody between the two moodles knows what was said.
The above description makes one small simplification; public-key encryption is more computationally intensive than symmetric key encryption. For this reason instead of encrypting the entire xmlrpc request using the MoodleB's public key, MoodleA encrypts the request using symmetric key encryption, and uses MoodleB's public key to encrypt the symetric key, and sends this along with the symmetrically-encrypted request. A related stage is introduced at the MoodleB: decrypt the symetric key using its private key then use the symmetric key to decrypt the xmlrpc request.
The Big Picture
The below picture shows the relevant layers in an mnet message, the original xmlrpc request is in purple, wrapped up with the signature in the yellow xml envelope. This yellow envelope is then encrypted by a symmetric key, and wrapped up in another envelope along with the public-key-encrypted symmetric key.
MNET uses a subset of XML-ENC, specifically it uses RC4 encryption for the encrypted data, using a randomly generated, single-use 128bit key. The key is then encrypted using the remote server's public RSA-v1.5, using PKCS1 encoding. MNET does not support anything other than the RC4/RSA encryptions. In the XML file that is sent, the encrypted key must appear in the file after the encrypted data, else MNET will not understand the request.
 The whole shebang is only as secure as the original exchange of public keys. If someone is conducting a man-in-the-middle attack at the time you exchange public keys you've lost the whole shooting match, you'll actually end up with the public key the attacker wants you to see, and never know that the attacker is reading and re-encrypting every message MoodleA & MoodleB exchange.
[*] Central pillar of many other things too.