diff --git a/src/main.zig b/src/main.zig index c8a3f67..79969c6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,19 +1,119 @@ const std = @import("std"); +const DH = std.crypto.dh.X25519; +const AES = std.crypto.aead.aes_gcm.Aes256Gcm; +const SHA = std.crypto.hash.sha2.Sha256; + +const Encryptor = struct { + const Self = @This(); + + kp: DH.KeyPair, + + pub fn init() !Self { + const self = Self{}; + + var seed: [DH.seed_length]u8 = undefined; + std.crypto.random.bytes(&seed); + self.kp = try DH.KeyPair.create(seed); + @memset(seed, 0); + + return self; + } +}; + +const Peer = struct { + const Self = @This(); + + public_key: [DH.public_length]u8, + shared_key: [AES.key_length]u8, + + pub fn init(me: DH.KeyPair, peer_key: [DH.public_length]u8) Self { + const self = Self{ .public_key = peer_key }; + + const secret = try DH.scalarmult(me.secret_key, peer_key); + SHA.hash(&secret, self.shared_key, .{}); + + return self; + } + + pub fn encrypt(ally: std.mem.Allocator, msg: []const u8) !Packet { + var pkt: Packet = undefined; + std.crypto.random.bytes(&pkt.nonce); + } +}; + +const Packet = struct { + ally: std.mem.Allocator, + nonce: [AES.tag_length]u8, + + cipher_text: []u8, +}; + pub fn main() !void { - // Prints to stderr (it's a shortcut based on `std.io.getStdErr()`) - std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); + const me = try Encryptor.init(); + const him = try Encryptor.init(); - // stdout is for the actual output of your application, for example if you - // are implementing gzip, then only the compressed bytes should be sent to - // stdout, not any debugging messages. - const stdout_file = std.io.getStdOut().writer(); - var bw = std.io.bufferedWriter(stdout_file); - const stdout = bw.writer(); + const my_peer = Peer.init(me, him.kp.public_key); + const his_peer = Peer.init(him, me.kp.public_key); - try stdout.print("Run `zig build test` to run the tests.\n", .{}); + var seed: [dh.X25519.seed_length]u8 = undefined; + std.crypto.random.bytes(&seed); + const kp1 = try dh.X25519.KeyPair.create(seed); + std.crypto.random.bytes(&seed); + const kp2 = try dh.X25519.KeyPair.create(seed); - try bw.flush(); // don't forget to flush! + std.debug.print("{any}\n{any}\n\n", .{ kp1.public_key, kp1.secret_key }); + std.debug.print("{any}\n{any}\n\n", .{ kp2.public_key, kp2.secret_key }); + + const sec_1 = try dh.X25519.scalarmult(kp1.secret_key, kp2.public_key); + const sec_2 = try dh.X25519.scalarmult(kp2.secret_key, kp1.public_key); + + var key: [aead.aes_gcm.Aes256Gcm.key_length]u8 = undefined; + std.crypto.hash.sha2.Sha256.hash(&sec_1, &key, .{}); + + std.debug.print("{any}\n", .{sec_1}); + std.debug.print("{any}\n", .{sec_2}); + + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const ally = gpa.allocator(); + + const m: []const u8 = "hello world!"; + const ad: []const u8 = "foo"; + + // see https://crypto.stackexchange.com/a/5818 + // the nonce does not need to be random, it can be a counter + // it can be sent in clear, or each end may deduce it + // but it ___MUST___ be unique and unrelated to the key + var iv: [aead.aes_gcm.Aes256Gcm.nonce_length]u8 = undefined; + std.crypto.random.bytes(&iv); + + const c: []u8 = try ally.alloc(u8, m.len); + defer ally.free(c); + + @memset(c, 0); + var tag: [aead.aes_gcm.Aes256Gcm.tag_length]u8 = undefined; + + std.debug.print("c: {any}\n", .{c}); + aead.aes_gcm.Aes256Gcm.encrypt(c, &tag, m, ad, iv, key); + std.debug.print("{any} {any} {any}\n", .{ c, tag, iv }); + + // aead.aes_gcm.Aes256Gcm.encrypt(c: []u8, tag: *[tag_length]u8, m: []const u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) + + // var seed_a = [sign.Ed25519.KeyPair.seed_length]u8; + // std.crypto.random.bytes(&seed_a); + // const pair_a = try sign.Ed25519.KeyPair.create(seed_a); + // var pubkey_a = dh.X25519.publicKeyFromEd25519(pair_a.public_key); + // + // var seed_b = [sign.Ed25519.KeyPair.seed_length]u8; + // std.crypto.random.bytes(&seed_b); + // const pair_b = try sign.Ed25519.KeyPair.create(seed_b); + // var pubkey_b = try dh.X25519.publicKeyFromEd25519(pair_b.public_key); + + // var buf: [64]u8 = undefined; + // @memset(&buf, 0); + // std.debug.print("{any}\n", .{buf}); + // std.crypto.random.bytes(&buf); + // std.debug.print("{any}\n", .{buf}); } test "simple test" {