| ... | @@ -1721,53 +1721,55 @@ test "Test happy flow" { | ... | @@ -1721,53 +1721,55 @@ test "Test happy flow" { |
| 1721 | | 1721 | |
| 1722 | // Code to test NIST Known Answer Tests (KAT), see PQCgenKAT.c. | 1722 | // Code to test NIST Known Answer Tests (KAT), see PQCgenKAT.c. |
| 1723 | | 1723 | |
| 1724 | const sha2 = crypto.hash.sha2; | 1724 | test "NIST KAT test d00.Kyber512" { |
| 1725 | | 1725 | try testNistKat(d00.Kyber512, "e9c2bd37133fcb40772f81559f14b1f58dccd1c816701be9ba6214d43baf4547"); |
| 1726 | test "NIST KAT test" { | 1726 | } |
| 1727 | inline for (.{ | | |
| 1728 | .{ d00.Kyber512, "e9c2bd37133fcb40772f81559f14b1f58dccd1c816701be9ba6214d43baf4547" }, | | |
| 1729 | .{ d00.Kyber1024, "89248f2f33f7f4f7051729111f3049c409a933ec904aedadf035f30fa5646cd5" }, | | |
| 1730 | .{ d00.Kyber768, "a1e122cad3c24bc51622e4c242d8b8acbcd3f618fee4220400605ca8f9ea02c2" }, | | |
| 1731 | }) |modeHash| { | | |
| 1732 | const mode = modeHash[0]; | | |
| 1733 | var seed: [48]u8 = undefined; | | |
| 1734 | for (&seed, 0..) |*s, i| { | | |
| 1735 | s.* = @as(u8, @intCast(i)); | | |
| 1736 | } | | |
| 1737 | var f = sha2.Sha256.init(.{}); | | |
| 1738 | const fw = f.writer(); | | |
| 1739 | var g = NistDRBG.init(seed); | | |
| 1740 | try std.fmt.format(fw, "# {s}\n\n", .{mode.name}); | | |
| 1741 | for (0..100) |i| { | | |
| 1742 | g.fill(&seed); | | |
| 1743 | try std.fmt.format(fw, "count = {}\n", .{i}); | | |
| 1744 | try std.fmt.format(fw, "seed = {X}\n", .{&seed}); | | |
| 1745 | var g2 = NistDRBG.init(seed); | | |
| 1746 | | | |
| 1747 | // This is not equivalent to g2.fill(kseed[:]). As the reference | | |
| 1748 | // implementation calls randombytes twice generating the keypair, | | |
| 1749 | // we have to do that as well. | | |
| 1750 | var kseed: [64]u8 = undefined; | | |
| 1751 | var eseed: [32]u8 = undefined; | | |
| 1752 | g2.fill(kseed[0..32]); | | |
| 1753 | g2.fill(kseed[32..64]); | | |
| 1754 | g2.fill(&eseed); | | |
| 1755 | const kp = try mode.KeyPair.generateDeterministic(kseed); | | |
| 1756 | const e = kp.public_key.encaps(eseed); | | |
| 1757 | const ss2 = try kp.secret_key.decaps(&e.ciphertext); | | |
| 1758 | try testing.expectEqual(ss2, e.shared_secret); | | |
| 1759 | try std.fmt.format(fw, "pk = {X}\n", .{&kp.public_key.toBytes()}); | | |
| 1760 | try std.fmt.format(fw, "sk = {X}\n", .{&kp.secret_key.toBytes()}); | | |
| 1761 | try std.fmt.format(fw, "ct = {X}\n", .{&e.ciphertext}); | | |
| 1762 | try std.fmt.format(fw, "ss = {X}\n\n", .{&e.shared_secret}); | | |
| 1763 | } | | |
| 1764 | | 1727 | |
| 1765 | var out: [32]u8 = undefined; | 1728 | test "NIST KAT test d00.Kyber1024" { |
| 1766 | f.final(&out); | 1729 | try testNistKat(d00.Kyber1024, "89248f2f33f7f4f7051729111f3049c409a933ec904aedadf035f30fa5646cd5"); |
| 1767 | var outHex: [64]u8 = undefined; | 1730 | } |
| 1768 | _ = try std.fmt.bufPrint(&outHex, "{x}", .{&out}); | 1731 | |
| 1769 | try testing.expectEqual(outHex, modeHash[1].*); | 1732 | test "NIST KAT test d00.Kyber768" { |
| | 1733 | try testNistKat(d00.Kyber768, "a1e122cad3c24bc51622e4c242d8b8acbcd3f618fee4220400605ca8f9ea02c2"); |
| | 1734 | } |
| | 1735 | |
| | 1736 | fn testNistKat(mode: type, hash: []const u8) !void { |
| | 1737 | var seed: [48]u8 = undefined; |
| | 1738 | for (&seed, 0..) |*s, i| { |
| | 1739 | s.* = @as(u8, @intCast(i)); |
| 1770 | } | 1740 | } |
| | 1741 | var fw: std.Io.Writer.Hashing(crypto.hash.sha2.Sha256) = .init(&.{}); |
| | 1742 | var g = NistDRBG.init(seed); |
| | 1743 | try fw.writer.print("# {s}\n\n", .{mode.name}); |
| | 1744 | for (0..100) |i| { |
| | 1745 | g.fill(&seed); |
| | 1746 | try fw.writer.print("count = {}\n", .{i}); |
| | 1747 | try fw.writer.print("seed = {X}\n", .{&seed}); |
| | 1748 | var g2 = NistDRBG.init(seed); |
| | 1749 | |
| | 1750 | // This is not equivalent to g2.fill(kseed[:]). As the reference |
| | 1751 | // implementation calls randombytes twice generating the keypair, |
| | 1752 | // we have to do that as well. |
| | 1753 | var kseed: [64]u8 = undefined; |
| | 1754 | var eseed: [32]u8 = undefined; |
| | 1755 | g2.fill(kseed[0..32]); |
| | 1756 | g2.fill(kseed[32..64]); |
| | 1757 | g2.fill(&eseed); |
| | 1758 | const kp = try mode.KeyPair.generateDeterministic(kseed); |
| | 1759 | const e = kp.public_key.encaps(eseed); |
| | 1760 | const ss2 = try kp.secret_key.decaps(&e.ciphertext); |
| | 1761 | try testing.expectEqual(ss2, e.shared_secret); |
| | 1762 | try fw.writer.print("pk = {X}\n", .{&kp.public_key.toBytes()}); |
| | 1763 | try fw.writer.print("sk = {X}\n", .{&kp.secret_key.toBytes()}); |
| | 1764 | try fw.writer.print("ct = {X}\n", .{&e.ciphertext}); |
| | 1765 | try fw.writer.print("ss = {X}\n\n", .{&e.shared_secret}); |
| | 1766 | } |
| | 1767 | |
| | 1768 | var out: [32]u8 = undefined; |
| | 1769 | fw.hasher.final(&out); |
| | 1770 | var outHex: [64]u8 = undefined; |
| | 1771 | _ = try std.fmt.bufPrint(&outHex, "{x}", .{&out}); |
| | 1772 | try testing.expectEqualStrings(&outHex, hash); |
| 1771 | } | 1773 | } |
| 1772 | | 1774 | |
| 1773 | const NistDRBG = struct { | 1775 | const NistDRBG = struct { |