Add Kyber post-quantum key encapsulation mechanism (#14902)

Implementation of the IND-CCA2 post-quantum secure key encapsulation
mechanism (KEM) CRYSTALS-Kyber, as submitted to the third round of the NIST
Post-Quantum Cryptography (v3.02/"draft00"), and selected for standardisation.

Co-authored-by: Frank Denis <124872+jedisct1@users.noreply.github.com>
This commit is contained in:
Bas Westerbaan 2023-03-15 04:50:45 +01:00 committed by GitHub
parent e17998b396
commit 4414f9c46e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 1874 additions and 0 deletions

View File

@ -68,6 +68,11 @@ pub const dh = struct {
pub const X25519 = @import("crypto/25519/x25519.zig").X25519;
};
/// Key Encapsulation Mechanisms.
pub const kem = struct {
pub const kyber_d00 = @import("crypto/kyber_d00.zig");
};
/// Elliptic-curve arithmetic.
pub const ecc = struct {
pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
@ -240,6 +245,8 @@ test {
_ = dh.X25519;
_ = kem.kyber_d00;
_ = ecc.Curve25519;
_ = ecc.Edwards25519;
_ = ecc.P256;

View File

@ -203,6 +203,72 @@ pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime
return throughput;
}
const kems = [_]Crypto{
Crypto{ .ty = crypto.kem.kyber_d00.Kyber512, .name = "kyber512d00" },
Crypto{ .ty = crypto.kem.kyber_d00.Kyber768, .name = "kyber768d00" },
Crypto{ .ty = crypto.kem.kyber_d00.Kyber1024, .name = "kyber1024d00" },
};
pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int) !u64 {
const key_pair = try Kem.KeyPair.create(null);
var timer = try Timer.start();
const start = timer.lap();
{
var i: usize = 0;
while (i < kems_count) : (i += 1) {
const e = key_pair.public_key.encaps(null);
mem.doNotOptimizeAway(&e);
}
}
const end = timer.read();
const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
const throughput = @floatToInt(u64, kems_count / elapsed_s);
return throughput;
}
pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_int) !u64 {
const key_pair = try Kem.KeyPair.create(null);
const e = key_pair.public_key.encaps(null);
var timer = try Timer.start();
const start = timer.lap();
{
var i: usize = 0;
while (i < kems_count) : (i += 1) {
const ss2 = try key_pair.secret_key.decaps(&e.ciphertext);
mem.doNotOptimizeAway(&ss2);
}
}
const end = timer.read();
const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
const throughput = @floatToInt(u64, kems_count / elapsed_s);
return throughput;
}
pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_int) !u64 {
var timer = try Timer.start();
const start = timer.lap();
{
var i: usize = 0;
while (i < kems_count) : (i += 1) {
const key_pair = try Kem.KeyPair.create(null);
mem.doNotOptimizeAway(&key_pair);
}
}
const end = timer.read();
const elapsed_s = @intToFloat(f64, end - start) / time.ns_per_s;
const throughput = @floatToInt(u64, kems_count / elapsed_s);
return throughput;
}
const aeads = [_]Crypto{
Crypto{ .ty = crypto.aead.chacha_poly.ChaCha20Poly1305, .name = "chacha20Poly1305" },
Crypto{ .ty = crypto.aead.chacha_poly.XChaCha20Poly1305, .name = "xchacha20Poly1305" },
@ -485,4 +551,25 @@ pub fn main() !void {
try stdout.print("{s:>17}: {d:10.3} s/ops\n", .{ H.name, throughput });
}
}
inline for (kems) |E| {
if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
const throughput = try benchmarkKem(E.ty, mode(1000));
try stdout.print("{s:>17}: {:10} encaps/s\n", .{ E.name, throughput });
}
}
inline for (kems) |E| {
if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
const throughput = try benchmarkKemDecaps(E.ty, mode(25000));
try stdout.print("{s:>17}: {:10} decaps/s\n", .{ E.name, throughput });
}
}
inline for (kems) |E| {
if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
const throughput = try benchmarkKemKeyGen(E.ty, mode(25000));
try stdout.print("{s:>17}: {:10} keygen/s\n", .{ E.name, throughput });
}
}
}

1780
lib/std/crypto/kyber_d00.zig Normal file

File diff suppressed because it is too large Load Diff