1 // Written in the D programming language.
2 
3 module wrapper.sodium.crypto_kdf;
4 
5 import wrapper.sodium.core; // assure sodium got initialized
6 
7 public
8 import  deimos.sodium.crypto_kdf : crypto_kdf_BYTES_MIN,
9                                    crypto_kdf_bytes_min,
10                                    crypto_kdf_BYTES_MAX,
11                                    crypto_kdf_bytes_max,
12                                    crypto_kdf_CONTEXTBYTES,
13                                    crypto_kdf_contextbytes,
14                                    crypto_kdf_KEYBYTES,
15                                    crypto_kdf_keybytes,
16                                    crypto_kdf_PRIMITIVE,
17 /*                                 crypto_kdf_primitive,
18                                    crypto_kdf_derive_from_key, */
19                                    crypto_kdf_keygen;
20 
21 
22 string crypto_kdf_primitive() pure nothrow @nogc @trusted
23 {
24   import std..string : fromStringz;
25   static import deimos.sodium.crypto_kdf;
26   return  fromStringz(deimos.sodium.crypto_kdf.crypto_kdf_primitive()); // strips terminating \0
27 }
28 
29 /* overload */
30 
31 alias crypto_kdf_derive_from_key = deimos.sodium.crypto_kdf.crypto_kdf_derive_from_key;
32 
33 pragma(inline, true)
34 bool  crypto_kdf_derive_from_key(scope ubyte[] subkey,
35                                  const ulong subkey_id,
36                                  const char[crypto_kdf_CONTEXTBYTES] ctx,
37                                  const ubyte[crypto_kdf_KEYBYTES] key) @nogc @trusted
38 {
39     import nogc.exception: enforce;
40 //  enforce(subkey.length>=crypto_kdf_BYTES_MIN && subkey.length<=crypto_kdf_BYTES_MAX,
41 //    "Expected subkey.length: ", subkey.length, " to be greater-equal to crypto_kdf_BYTES_MIN: ", crypto_kdf_BYTES_MIN, " and less-equal to crypto_kdf_BYTES_MAX: ", crypto_kdf_BYTES_MAX);
42   enforce(subkey.length>=crypto_kdf_BYTES_MIN && subkey.length<=crypto_kdf_BYTES_MAX,
43     "Expected subkey.length is not greater-equal to crypto_kdf_BYTES_MIN and not less-equal to crypto_kdf_BYTES_MAX");
44   return  crypto_kdf_derive_from_key(subkey.ptr, subkey.length, subkey_id, ctx, key) == 0;
45 }
46 
47 @safe
48 unittest {
49   import std.stdio : writeln;
50   debug writeln("unittest block 1 from sodium.crypto_kdf.d");
51 }
52 
53 @nogc @safe
54 unittest {
55   assert(crypto_kdf_bytes_min()    == crypto_kdf_BYTES_MIN);
56   assert(crypto_kdf_bytes_max()    == crypto_kdf_BYTES_MAX);
57   assert(crypto_kdf_contextbytes() == crypto_kdf_CONTEXTBYTES);
58   assert(crypto_kdf_keybytes()     == crypto_kdf_keybytes);
59   assert(crypto_kdf_primitive()    == crypto_kdf_PRIMITIVE);
60 
61   char[crypto_kdf_CONTEXTBYTES] context = "Examples";
62   ubyte[crypto_kdf_KEYBYTES]  master_key;
63   ubyte[32]  subkey1;
64   ubyte[32]  subkey2;
65   ubyte[64]  subkey3;
66   crypto_kdf_keygen(master_key);
67   assert(crypto_kdf_derive_from_key(subkey1, 1, context, master_key));
68   assert(crypto_kdf_derive_from_key(subkey2, 2, context, master_key));
69   assert(crypto_kdf_derive_from_key(subkey3, 3, context, master_key));
70 }
71 
72 @safe
73 unittest {
74   import std.exception : assertThrown;
75 
76   char[crypto_kdf_CONTEXTBYTES] context = "Examples";
77   ubyte[crypto_kdf_KEYBYTES]  master_key;
78   crypto_kdf_keygen(master_key);
79   ubyte[15]  subkey4;
80   ubyte[65]  subkey5;
81   assertThrown(crypto_kdf_derive_from_key(subkey4, 4, context, master_key));
82   assertThrown(crypto_kdf_derive_from_key(subkey5, 5, context, master_key));
83   ubyte[crypto_kdf_KEYBYTES]  master_key2;
84   crypto_kdf_keygen(master_key2);
85   assert(master_key != master_key2);
86   ubyte[32]  subkey1;
87   ubyte[32]  subkey2;
88   assert(crypto_kdf_derive_from_key(subkey1, 1, context, master_key));
89   assert(crypto_kdf_derive_from_key(subkey2, 1, context, master_key));
90   assert(subkey1 == subkey2);
91   assert(crypto_kdf_derive_from_key(subkey2, 2, context, master_key));
92   assert(subkey1 != subkey2);
93 }