1 // Written in the D programming language.
2 
3 module wrapper.sodium.crypto_auth;
4 
5 import wrapper.sodium.core; // assure sodium got initialized
6 
7 public
8 import  deimos.sodium.crypto_auth : crypto_auth_BYTES,
9                                     crypto_auth_bytes,
10                                     crypto_auth_KEYBYTES,
11                                     crypto_auth_keybytes,
12                                     crypto_auth_PRIMITIVE,
13 /*                                  crypto_auth_primitive,
14                                     crypto_auth,
15                                     crypto_auth_verify; */
16                                     crypto_auth_keygen;
17 
18 /*
19  deimos.sodium.crypto_auth.crypto_auth_primitive() gets trusted to return a valid (program lifetime) address, to be evaluated as a null-terminated C string
20  added nothrow again for D, i.e. return value must be used
21 */
22 string crypto_auth_primitive() @nogc nothrow pure @trusted
23 {
24   import std..string : fromStringz; // @system
25   static import deimos.sodium.crypto_auth;
26   const(char)[] c_arr;
27   try
28     c_arr = fromStringz(deimos.sodium.crypto_auth.crypto_auth_primitive()); // strips terminating \0
29   catch (Exception e) { /* known not to throw */ }
30   return c_arr; // assumeUnique not strictly required, as compiler can infer uniqueness for a pure function // omit .idup for @nogc
31 }
32 
33 // overloading some functions between module deimos.sodium.crypto_auth and this module
34 
35 alias crypto_auth        = deimos.sodium.crypto_auth.crypto_auth;
36 
37 /**
38  */
39 pragma(inline, true)
40 bool crypto_auth(out ubyte[crypto_auth_BYTES] mac, scope const ubyte[] message, const ubyte[crypto_auth_KEYBYTES] skey) @nogc nothrow pure @trusted
41 {
42   bool result;
43   try
44     result =  crypto_auth(mac.ptr, message.ptr, message.length, skey.ptr) == 0;
45   catch(Exception e) { /* known not to throw */ }
46   return result;
47 }
48 
49 alias crypto_auth_verify = deimos.sodium.crypto_auth.crypto_auth_verify;
50 
51 /**
52  */
53 pragma(inline, true)
54 bool crypto_auth_verify(const ubyte[crypto_auth_BYTES] mac, scope const ubyte[] message, const ubyte[crypto_auth_KEYBYTES] skey) @nogc nothrow pure @trusted
55 {
56   return  crypto_auth_verify(mac.ptr, message.ptr, message.length, skey.ptr) == 0;
57 }
58 
59 
60 @safe
61 unittest
62 {
63   import std..string : representation;
64   import std.stdio : writeln;
65   import wrapper.sodium.randombytes : randombytes;
66 
67   debug writeln("unittest block 1 from sodium.crypto_auth.d");
68 
69   assert(crypto_auth_bytes()      == crypto_auth_BYTES);
70   assert(crypto_auth_keybytes()   == crypto_auth_KEYBYTES);
71   assert(crypto_auth_primitive()  == crypto_auth_PRIMITIVE);
72 
73   auto                        message = representation("test");
74   ubyte[crypto_auth_KEYBYTES] skey;
75   ubyte[crypto_auth_BYTES]    mac;
76 
77   randombytes(skey);
78   assert(crypto_auth(mac, message, skey));
79 
80   assert(crypto_auth_verify(mac, message, skey));
81 //  if (!crypto_auth_verify(mac, message, skey))
82 //    writeln("*** ATTENTION : The message has been forged ! ***");
83   ubyte[crypto_auth_KEYBYTES] k;
84   crypto_auth_keygen(k);
85 }
86 
87 @safe
88 unittest
89 {
90   ubyte[crypto_auth_BYTES] mac;
91   ubyte[4] message  = [116, 101, 115, 116]; //representation("test");
92   ubyte[crypto_auth_KEYBYTES] skey;
93   crypto_auth_keygen(skey);
94   assert(crypto_auth(mac, message, skey));
95   assert(crypto_auth_verify(mac, message, skey));
96 }