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 }