Security-By Design: Meet Near Perfect Message Security: Messaging Layer Security (MLS)

The use of SSL/TLS fixed the problem of transmitting data packets without encryption, and in not checking the trustworthiness of the…

ASecuritySite [here]

Security-By Design: Meet Near Perfect Message Security: Messaging Layer Security (MLS)

The use of SSL/TLS fixed the problem of transmitting data packets without encryption, and in not checking the trustworthiness of the servers that we connected to. But, this is closing the door after the horse has bolted. Thus the way we do our authentication for security tunnels is also often flawed, such as:

  • Supporting many legacy cryptography methods (such as the Diffie-Hellman key exchange method, the SHA-1 hashing method and 3DES symmetric key encryption).
  • Adding large RSA signatures and which authenticate just one side of the communication.
  • Easy to install a proxy on a machine and listen to the network traffic.
  • Easy to break the communications channel (such as with a WAF — Web Application Firewall) and inspect the traffic.

The best way to secure data is to encrypt it at its source. We typically define this as end-to-end encryption. And one of the newest open standards — Messaging Layer Security (MLS) — has just been published by the IETF [here]:

Key properties of MLS

The focus of MLS is to setup users which integrate into groups, and includes the key properties of:

  • Message Confidentiality. This is where messages can only be seen within a given group.
  • Message Integrity and Authentication. Each message is tagged to ensure both integrity of the message and for a check on the sender of the message.
  • Membership Authentication. This is where each user can determine the other users in the group.
  • Asynchronicity. With this, we can create keys without the need for users to be online.
  • Forward secrecy. Any compromise of a single key will not cause the previous keys to be breached.
  • Post-compromise security. A compromise of a node will not compromise future messages from a given group.
  • Scalability. This supports scaling of group sizes without affecting performance too much.

Messaging Layer Security (MLS)

Messaging Layer Security (MLS) was initially proposed in 2016 and integrates end-to-end encrypting of messages. It has been defined by the IETF MLS working group, which includes authors from Cisco, Google, Mozilla, Meta, Phoenix R&D, and the University of Oxford. Overall, it uses best-in-practice encryption methods to define the cryptographic suite. For the message privacy, we need symmetric key encryption, such as with AES and ChaCha20. In order to generate the symmetric key, we need a key exchange method (such as ECDH using P256 or P521 or X25519 using Curve 25519). Finally, we need a digital signature method to sign messages, such as Ed25519 (which uses Curve 25519), P256 (which uses ECDSA) or P521 (which also uses ECDSA).

The cryptographic suites supported by MLS include:

  • X25519_AES128GCM_SHA256_Ed25519. This integrates 128-bit (32 bytes) AES with GCM mode, and uses X25519 for key exchange, SHA256 for hashing and Ed25519 for digital signatures.
  • P256_AES128GCM_SHA256_P256. This integrates 128-bit (32 bytes) AES with GCM mode, and uses P256 (secp256r1) for key exchange, SHA256 for hashing and ECDSA (using P256) for digital signatures.
  • X25519_CHACHA20POLY1305_SHA256_Ed25519. This integrates 128-bit (32 bytes) ChaCha20 with Poly1305 for authentication, and uses X25519 for key exchange, SHA256 for hashing and Ed25519 for digital signatures.
  • P521_AES256GCM_SHA512_P521. This integrates 256-bit (64 bytes) AES with GCM mode, and uses P521 for key exchange, SHA256 for hashing and ECDSA (with P521) for digital signatures.

Coding

In this case, we will use PBKDF2 to generate an encryption key. We can use X25519_AES128GCM_SHA256_Ed25519, and which integrates 128-bit (32 bytes) AES with GCM mode. In the following, we will use a salt value of all zeros for the encryption key generation, a nonce value of all zeros, and additional data of “00”:

package main

import (

"fmt"
"encoding/hex"
mls "github.com/cisco/go-mls"
"golang.org/x/crypto/pbkdf2"
"crypto/sha256"
"os"
)

func unhex(h string) []byte {
b, err := hex.DecodeString(h)
if err != nil {
panic(err)
}
return b
}
func main() {

suite := mls.X25519_AES128GCM_SHA256_Ed25519
var key, nonce, aad, pt, ct []byte

msg:="hello"
passwd:="Test"
mode:="0"


argCount := len(os.Args[1:])

if (argCount>0) {msg= string(os.Args[1])}
if (argCount>1) {passwd= string(os.Args[2])}
if (argCount>2) {mode= string(os.Args[3])}

salt:=[]byte("000000000000")


nonce =unhex("000000000000000000000000")

key = pbkdf2.Key([]byte(passwd), salt, 10000, 16, sha256.New)


if (mode=="1") {
suite = mls.P256_AES128GCM_SHA256_P256
}
if (mode=="2") {
suite = mls.X25519_CHACHA20POLY1305_SHA256_Ed25519
key = pbkdf2.Key([]byte(passwd), salt, 10000, 32, sha256.New)
}
if (mode=="3") {
suite = mls.P521_AES256GCM_SHA512_P521
key = pbkdf2.Key([]byte(passwd), salt, 10000, 32, sha256.New)
}



pt=[]byte(msg)

aad = unhex("00")

aead, _ := suite.NewAEAD(key)

ct = aead.Seal(nil, nonce, pt, aad)
decrypted, _ := aead.Open(nil, nonce, ct, aad)

fmt.Printf("Message:\t%s\n", pt)
fmt.Printf("Password:\t%s\n", passwd)
fmt.Printf("Type:\t\t%s\n\n", suite.String())
fmt.Printf("Key:\t\t%x\n\n", key)
fmt.Printf("Encrypted:\t%x\n", ct)
fmt.Printf("Decrypted:\t%s\n", decrypted)

}

The code is here:

A sample run gives [here]:

Message: Testing 123
Password: qwerty
Type: X25519_AES128GCM_SHA256_Ed25519

Key: 002a6d5befd08b3927d71d408f2015b4

Encrypted: 11014d48300758146fe37e5894a13079bd23ae02aa15b8aaaffc19
Decrypted: Testing 123

and for ChaCha20 we see we have a larger key (256bits):

Message: Testing 123
Password: qwerty
Type: X25519_CHACHA20POLY1305_SHA256_Ed25519

Key: 002a6d5befd08b3927d71d408f2015b4da03599b2fa6e30a76ee3bb28a4136fd

Encrypted: d32b675b1b29968b4b9872acc1c3948e25b41b0950d7e4165e7cf5
Decrypted: Testing 123

Obviously, in a real-life case, we would be using random salt and nonce values, along with linking the AAD (Authentication Additional Data) to a session ID. It should be noticed that we use AEAD (Authenticated Encryption with Additional Data) for each of the symmetric key methods, as this locks the encryption to additional data (such as for a port number or a session number).

Conclusions

We live in a sticking plaster world of security, and where we have often just patched our security issues. This is not often security-by-design. With MLS, we have an open platform to build secure systems, that are secure-, authenticated- and trustworthy-by design.