1 // Written in the D programming language.
2 
3 module wrapper.sodium.crypto_kx;
4 
5 import wrapper.sodium.core; // assure sodium got initialized
6 
7 public
8 import  deimos.sodium.crypto_kx : crypto_kx_PUBLICKEYBYTES,
9                                   crypto_kx_publickeybytes,
10                                   crypto_kx_SECRETKEYBYTES,
11                                   crypto_kx_secretkeybytes,
12                                   crypto_kx_SEEDBYTES,
13                                   crypto_kx_seedbytes,
14                                   crypto_kx_SESSIONKEYBYTES,
15                                   crypto_kx_sessionkeybytes,
16                                   crypto_kx_PRIMITIVE,
17 //                                crypto_kx_primitive,
18                                   crypto_kx_seed_keypair,
19                                   crypto_kx_keypair,
20                                   crypto_kx_client_session_keys,
21                                   crypto_kx_server_session_keys;
22 
23 
24 string crypto_kx_primitive() pure nothrow @nogc @trusted
25 {
26   import std..string : fromStringz;
27   static import deimos.sodium.crypto_kx;
28   const(char)[] c_arr;
29   try
30     c_arr = fromStringz(deimos.sodium.crypto_kx.crypto_kx_primitive()); // strips terminating \0
31   catch (Exception e) { /* known not to throw */ }
32   return c_arr;
33 }
34 
35 
36 @safe
37 unittest {
38   import std.stdio : writeln;
39   debug writeln("unittest block 1 from sodium.crypto_kx.d");
40 }
41 
42 @nogc @safe
43 unittest {
44   import wrapper.sodium.crypto_secretbox;
45   import wrapper.sodium.randombytes;
46   assert(crypto_kx_publickeybytes()  == crypto_kx_PUBLICKEYBYTES);
47   assert(crypto_kx_secretkeybytes()  == crypto_kx_SECRETKEYBYTES);
48   assert(crypto_kx_seedbytes()       == crypto_kx_SEEDBYTES);
49   assert(crypto_kx_sessionkeybytes() == crypto_kx_SESSIONKEYBYTES);
50   assert(crypto_kx_primitive()       == crypto_kx_PRIMITIVE);
51 
52   ubyte[crypto_kx_PUBLICKEYBYTES]  client_pk;
53   ubyte[crypto_kx_SECRETKEYBYTES]  client_sk;
54 
55   ubyte[crypto_kx_SESSIONKEYBYTES]  client_rx, client_tx;
56 
57   /*Generate the client's key pair */
58   crypto_kx_keypair(client_pk, client_sk);
59   /* Prerequisite after this point: the server's public key must be known by the client */
60 
61     ubyte[crypto_kx_PUBLICKEYBYTES]   server_pk;
62     ubyte[crypto_kx_SECRETKEYBYTES]   server_sk;
63 
64     ubyte[crypto_kx_SESSIONKEYBYTES]  server_rx, server_tx;
65     /* Generate the server's key pair */
66     crypto_kx_keypair(server_pk, server_sk);
67 
68   /* Compute two shared keys using the server's public key and the client's secret key.
69      client_rx will be used by the client to receive data from the server,
70      client_tx will by used by the client to send data to the server.      */
71   assert(crypto_kx_client_session_keys(client_rx, client_tx, client_pk, client_sk, server_pk) == 0);
72 
73     /* Prerequisite after this point: the client's public key must be known by the server */
74     /* Compute two shared keys using the client's public key and the server's secret key.
75        server_rx will be used by the server to receive data from the client,
76        server_tx will by used by the server to send data to the client. */
77     assert(crypto_kx_server_session_keys(server_rx, server_tx, server_pk, server_sk, client_pk) == 0);
78 
79   enum message_len = 4;
80   ubyte[message_len]  message  = [116, 101, 115, 116]; //representation("test");
81   ubyte[message_len]  decrypted;
82   ubyte[message_len+crypto_secretbox_MACBYTES]  ciphertext;
83   ubyte[crypto_secretbox_NONCEBYTES] nonce;
84   randombytes(nonce);
85   // client sends to server
86   assert(crypto_secretbox_easy(ciphertext, message, nonce, client_tx));
87     // server verifies and decrypts
88     assert(crypto_secretbox_open_easy(decrypted, ciphertext, nonce, server_rx));
89     assert(decrypted == message);
90 
91   message  = [110, 101, 120, 116]; //representation("next");
92   // server sends to client
93     assert(crypto_secretbox_easy(ciphertext, message, nonce, server_tx));
94     // client verifies and decrypts
95   assert(crypto_secretbox_open_easy(decrypted, ciphertext, nonce, client_rx));
96   assert(decrypted == message);
97   assert(client_tx == server_rx);
98   assert(server_tx == client_rx);
99 }