zig
                                
                                
                                
                                    zig copied to clipboard
                            
                            
                            
                        tls: send post-quantum secure keyshare
Sends post-quantum secure hybrid key share X25519+Kyber768Draft00, deployed by Cloudflare.
A few notes:
- The method of hybridisation is as per this IETF TLS WG draft version -06.
 - Kyber will probably change before final standardisation by NIST. When it does, we'll use a new TLS codepoint and update. The current version is v3.02 of the specification and version -00 of this I-D.
 - The only other big deployment of post-quantum kex is CECPQ2 (ref1, ref2) by Google, but they'll move to Kyber. It is not clear though whether they'll adopt a preliminary version such as this one.
 - Zig already generates and sends two key shares: P-256 and X25519. We generate a Kyber768 on top of that and reuse the X25519 share to make the hybrid. Kyber768 is fast — faster than X25519 — even with the currently unoptimised implementation:
x25519: 33753 exchanges/s kyber768d00: 49095 encaps/s kyber768d00: 62798 decaps/s kyber768d00: 43287 keygen/s - Kyber's keyshare is bigger: 1184 bytes for the client keyshare and 1088 bytes for the server keyshare. This will typically split the ClientHello into two TCP segments. The standards allow this, but it might well be that some middle boxes don't expect this.
 
To test
const std = @import("std");
pub fn main() !void {
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const hdrs = std.http.Client.Request.Headers{};
    const opts = std.http.Client.Request.Options{};
    var buf: [1000]u8 = undefined;
    const uri = try std.Uri.parse("https://cloudflare.com/cdn-cgi/trace");
    var client = std.http.Client{
        .allocator= arena.allocator(),
    };
    var req = try client.request(uri, hdrs, opts);
    try req.finish();
    const read = try req.readAll(&buf);
    const stdout = std.io.getStdOut().writer();
    try stdout.print("{s}\n", .{buf[0..read]});
}
Output:
fl=555f40
h=cloudflare.com
ip=[snip]
ts=1678868428.064
visit_scheme=https
uag=zig (std.http)
colo=AMS
sliver=none
http=http/1.1
loc=NL
tls=TLSv1.3
sni=plaintext
warp=off
gateway=off
rbi=off
kex=X25519Kyber768Draft00
                                    
                                    
                                    
                                
@jedisct1
Seeing that is amazing, well done Bas!
@jedisct1 build passed.