Messaging Layer Security (MLS) with Signing in GoMessaging 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, and integrates message confidentiality, message integrity and authentication, membership authentication, asynchronicity, forward secrecy, post-compromise security, and scalability. A final draft from the IETF for MLS was published on 29 Mar 2023 [here]. In this case, we will use ECDSA_SECP256R1_SHA256, ECDSA_SECP521R1_SHA512 or Ed25519. |
Outline
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.
In this case, we will implement signatures of:
- ECDSA_SECP256R1_SHA256. This is an ECDSA signature with a secp256r1 (P256) curve and using a SHA-256 hash.
- ECDSA_SECP521R1_SHA512. This is an ECDSA signature with a secp521r1 (P521) curve and using a SHA-512 hash.
- Ed25519. This is Ed25519 signature.
Coding
There are two ways we can generate the private key, either with a seed value (which will produce a well-defined private key and using scheme.Derive(seed)) or a random value (with scheme.Generate()).
To install the required Golang library, we need:
go get github.com/cisco/go-mls
The following is some sample code:
package main import ( "fmt" "encoding/hex" mls "github.com/cisco/go-mls" "os" ) func unhex(h string) []byte { b, err := hex.DecodeString(h) if err != nil { panic(err) } return b } func main() { scheme := mls.ECDSA_SECP256R1_SHA256 message:="Hello" seed1:="Goodbye" mode:="0" argCount := len(os.Args[1:]) if (argCount>0) {message= string(os.Args[1])} if (argCount>1) {seed1= string(os.Args[2])} if (argCount>2) {mode= string(os.Args[3])} msg := []byte(message) seed := []byte(seed1) if (mode=="1") { scheme = mls.ECDSA_SECP521R1_SHA512 } if (mode=="2") { scheme = mls.Ed25519 } // priv, _ := scheme.Generate() priv, _ := scheme.Derive(seed) signature, _ := scheme.Sign(&priv, msg) verified := scheme.Verify(&priv.PublicKey, msg, signature) fmt.Printf("Message:\t%s\n", msg) fmt.Printf("Seed:\t%s\n", seed) fmt.Printf("Method:\t%s\n\n", scheme.String()) fmt.Printf("Priv:\t%x\n", priv) fmt.Printf("Signature:\t%x\n", signature) fmt.Printf("Verified:\t%v\n", verified) }
And a sample run:
Message: Testing 123 Seed: qwerty12 Method: ECDSA_SECP256R1_SHA256 Priv: {9c6d405bba2db24bfbd22fc7ff74b39bd9c5e9c6ce66299c6519be517e6ed7c6 {041ab2e53c477dc6995e2b381c56f2a2461ac1b505607ca1cfd683da64446301f600135bcc8efdbbe316174f220c6e6734991a33b0c79f0dfc3a7f49996540dd96}} Signature: 304502210083d34632ca898a9e7b28db9c77aff5d6ed18cb44977f62021423755260e09f2402203062595798b88243f67818cdfd3fbc92c86eead14caf0eafa29d3b5c3b570930 Verified: true
With a key of:
{9c6d405bba2db24bfbd22fc7ff74b39bd9c5e9c6ce66299c6519be517e6ed7c6 {041ab2e53c477dc6995e2b381c56f2a2461ac1b505607ca1cfd683da64446301f600135bcc8efdbbe316174f220c6e6734991a33b0c79f0dfc3a7f49996540dd96}}
We have a private key of "9c6d405bba2db24bfbd22fc7ff74b39bd9c5e9c6ce66299c6519be517e6ed7c6", and a public key of "041ab2e53c477dc6995e2b381c56f2a2461ac1b505607ca1cfd683da64446301f600135bcc8efdbbe316174f220c6e6734991a33b0c79f0dfc3a7f49996540dd96". The "04" at the start of the public key defines an uncompressed point, and which has an x-axis and y-axis point:
1ab2e53c477dc6995e2b381c56f2a2461ac1b505607ca1cfd683da64446301f6, 00135bcc8efdbbe316174f220c6e6734991a33b0c79f0dfc3a7f49996540dd96
and for Ed25519:
Message: Testing 123 Seed: qwerty12 Method: Ed25519 Priv: {9c6d405bba2db24bfbd22fc7ff74b39bd9c5e9c6ce66299c6519be517e6ed7c69e5ebe774e7204d01bc1dff139cf9c8bff8d4a6c757f6f67128ca723f8090264 {9e5ebe774e7204d01bc1dff139cf9c8bff8d4a6c757f6f67128ca723f8090264}} Signature: fea051097ac3300c683fedf70476052bcc0c9d0713262218a80d5d10d9bff88c8e1b2e82ded0996adcd8b6a203493a0be36d513d8c9f4d17645eed0d88ff3900 Verified: true