libsodium.vapi 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /* Vala Bindings for LibSodium
  2. * Copyright (c) 2020 Billy Barrow <billyb@pcthingz.com>
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. [CCode (cheader_filename = "sodium.h", lower_case_cprefix = "sodium_")]
  17. namespace Sodium {
  18. namespace Random {
  19. [CCode (cname = "randombytes_SEEDBYTES")]
  20. public const size_t SEED_BYTES;
  21. [CCode (cname = "randombytes_random")]
  22. public uint32 random();
  23. [CCode (cname = "randombytes_uniform")]
  24. public uint32 random_uniform(uint32 upper_bound);
  25. [CCode (cname = "randombytes_buf")]
  26. public void random_bytes(uint8[] buffer);
  27. [CCode (cname = "randombytes_buf_deterministic")]
  28. public void random_bytes_deterministic(uint8[] buffer, uint8[] seed);
  29. }
  30. namespace Symmetric {
  31. [CCode (cname = "crypto_secretbox_KEYBYTES")]
  32. public const size_t KEY_BYTES;
  33. [CCode (cname = "crypto_secretbox_NONCEBYTES")]
  34. public const size_t NONCE_BYTES;
  35. [CCode (cname = "crypto_secretbox_MACBYTES")]
  36. public const size_t MAC_BYTES;
  37. [CCode (cname = "crypto_secretbox_keygen")]
  38. private void key_gen([CCode (array_length = false)]uint8[] key);
  39. public uint8[] generate_key() {
  40. uint8[] key = new uint8[KEY_BYTES];
  41. key_gen(key);
  42. return key;
  43. }
  44. [CCode (cname = "crypto_secretbox_easy")]
  45. private void secretbox(
  46. [CCode (array_length = false)]uint8[] ciphertext,
  47. uint8[] message,
  48. [CCode (array_length = false)]uint8[] nonce,
  49. [CCode (array_length = false)]uint8[] key
  50. );
  51. public uint8[] encrypt(uint8[] message, uint8[] key, uint8[] nonce)
  52. requires (key.length == KEY_BYTES)
  53. requires (nonce.length == NONCE_BYTES)
  54. {
  55. // Initialise array for ciphertext
  56. size_t ciphertext_size = MAC_BYTES + message.length;
  57. uint8[] ciphertext = new uint8[ciphertext_size];
  58. // Encrypt
  59. secretbox(ciphertext, message, nonce, key);
  60. // Return ciphertext
  61. return ciphertext;
  62. }
  63. [CCode (cname = "crypto_secretbox_open_easy")]
  64. private int secretbox_open(
  65. [CCode (array_length = false)]uint8[] message,
  66. uint8[] ciphertext,
  67. [CCode (array_length = false)]uint8[] nonce,
  68. [CCode (array_length = false)]uint8[] key
  69. );
  70. public uint8[]? decrypt(uint8[] ciphertext, uint8[] key, uint8[] nonce)
  71. requires (ciphertext.length > MAC_BYTES)
  72. requires (key.length == KEY_BYTES)
  73. requires (nonce.length == NONCE_BYTES)
  74. {
  75. // Initialise array for message
  76. size_t message_size = ciphertext.length - MAC_BYTES;
  77. uint8[] message = new uint8[message_size];
  78. // Decrypt
  79. int status = secretbox_open(message, ciphertext, nonce, key);
  80. // Did it work?
  81. if(status != 0) {
  82. // No, return null
  83. return null;
  84. }
  85. return message;
  86. }
  87. }
  88. namespace Asymmetric {
  89. namespace Signing {
  90. [CCode (cname = "crypto_sign_PUBLICKEYBYTES")]
  91. public const size_t PUBLIC_KEY_BYTES;
  92. [CCode (cname = "crypto_sign_SECRETKEYBYTES")]
  93. public const size_t SECRET_KEY_BYTES;
  94. [CCode (cname = "crypto_sign_BYTES")]
  95. public const size_t MAX_HEADER_BYTES;
  96. [CCode (cname = "crypto_sign_keypair")]
  97. public void generate_keypair(
  98. [CCode (array_length = false)]uint8[] public_key,
  99. [CCode (array_length = false)]uint8[] secret_key)
  100. requires (public_key.length == PUBLIC_KEY_BYTES)
  101. requires (secret_key.length == SECRET_KEY_BYTES);
  102. [CCode (cname = "crypto_sign")]
  103. private void sign_message(
  104. [CCode (array_length = false)] uint8[] signed_message,
  105. out int signature_length,
  106. uint8[] message,
  107. [CCode (array_length = false)] uint8[] secret_key
  108. );
  109. public uint8[] sign(
  110. uint8[] message,
  111. uint8[] secret_key)
  112. requires (secret_key.length == SECRET_KEY_BYTES)
  113. {
  114. int signature_length;
  115. uint8[] signed_message = new uint8[MAX_HEADER_BYTES + message.length];
  116. sign_message(signed_message, out signature_length, message, secret_key);
  117. signed_message.resize(signature_length);
  118. return signed_message;
  119. }
  120. [CCode (cname = "crypto_sign_open")]
  121. private int sign_open(
  122. [CCode (array_length = false)] uint8[] message,
  123. out int message_length,
  124. uint8[] signed_message,
  125. [CCode (array_length = false)] uint8[] public_key
  126. );
  127. public uint8[]? verify(
  128. uint8[] signed_message,
  129. uint8[] public_key)
  130. requires (public_key.length == PUBLIC_KEY_BYTES)
  131. {
  132. int message_length;
  133. uint8[] message = new uint8[signed_message.length];
  134. if(sign_open(message, out message_length, signed_message, public_key) != 0) {
  135. return null;
  136. }
  137. message.resize(message_length);
  138. return message;
  139. }
  140. [CCode (cname = "crypto_sign_detached")]
  141. private void sign_detached_message(
  142. [CCode (array_length = false)] uint8[] signature,
  143. out int signature_length,
  144. uint8[] message,
  145. [CCode (array_length = false)] uint8[] secret_key
  146. );
  147. /**
  148. * Signs a message and returns only the detached signature.
  149. *
  150. * The signature is MAX_HEADER_BYTES long and does not include the
  151. * message itself, allowing the message and signature to be
  152. * transported separately (e.g. a Statum frame's content/signature).
  153. */
  154. public uint8[] sign_detached(
  155. uint8[] message,
  156. uint8[] secret_key)
  157. requires (secret_key.length == SECRET_KEY_BYTES)
  158. {
  159. uint8[] signature = new uint8[MAX_HEADER_BYTES];
  160. int signature_length;
  161. sign_detached_message(signature, out signature_length, message, secret_key);
  162. signature.resize(signature_length);
  163. return signature;
  164. }
  165. [CCode (cname = "crypto_sign_verify_detached")]
  166. private int verify_detached_message(
  167. [CCode (array_length = false)] uint8[] signature,
  168. [CCode (array_length = false)] uint8[] message,
  169. size_t message_length,
  170. [CCode (array_length = false)] uint8[] public_key
  171. );
  172. /**
  173. * Verifies a detached signature against a message.
  174. *
  175. * @return true if the signature is valid for the message.
  176. */
  177. public bool verify_detached(
  178. uint8[] signature,
  179. uint8[] message,
  180. uint8[] public_key)
  181. requires (public_key.length == PUBLIC_KEY_BYTES)
  182. requires (signature.length == MAX_HEADER_BYTES)
  183. {
  184. return verify_detached_message(signature, message, (size_t)message.length, public_key) == 0;
  185. }
  186. }
  187. namespace Sealing {
  188. [CCode (cname = "crypto_box_PUBLICKEYBYTES")]
  189. public const size_t PUBLIC_KEY_BYTES;
  190. [CCode (cname = "crypto_box_SECRETKEYBYTES")]
  191. public const size_t SECRET_KEY_BYTES;
  192. [CCode (cname = "crypto_box_SEALBYTES")]
  193. public const size_t HEADER_BYTES;
  194. [CCode (cname = "crypto_box_keypair")]
  195. public void generate_keypair(
  196. [CCode (array_length = false)]uint8[] public_key,
  197. [CCode (array_length = false)]uint8[] secret_key)
  198. requires (public_key.length == PUBLIC_KEY_BYTES)
  199. requires (secret_key.length == SECRET_KEY_BYTES);
  200. [CCode (cname = "crypto_box_seal")]
  201. private void seal_message(
  202. [CCode (array_length = false)] uint8[] ciphertext,
  203. uint8[] message,
  204. [CCode (array_length = false)] uint8[] public_key
  205. );
  206. public uint8[] seal(uint8[] message, uint8[] public_key)
  207. requires (public_key.length == PUBLIC_KEY_BYTES)
  208. {
  209. uint8[] ciphertext = new uint8[HEADER_BYTES + message.length];
  210. seal_message(ciphertext, message, public_key);
  211. return ciphertext;
  212. }
  213. [CCode (cname = "crypto_box_seal_open")]
  214. private int seal_open(
  215. [CCode (array_length = false)] uint8[] message,
  216. uint8[] ciphertext,
  217. [CCode (array_length = false)] uint8[] public_key,
  218. [CCode (array_length = false)] uint8[] secret_key
  219. );
  220. public uint8[]? unseal(
  221. uint8[] ciphertext,
  222. uint8[] public_key,
  223. uint8[] secret_key)
  224. requires (public_key.length == PUBLIC_KEY_BYTES)
  225. requires (secret_key.length == SECRET_KEY_BYTES)
  226. requires (ciphertext.length > HEADER_BYTES)
  227. {
  228. uint8[] message = new uint8[ciphertext.length - HEADER_BYTES];
  229. if(seal_open(message, ciphertext, public_key, secret_key) != 0){
  230. return null;
  231. }
  232. return message;
  233. }
  234. }
  235. }
  236. namespace PasswordHashing {
  237. [CCode (cname = "crypto_pwhash_STRBYTES")]
  238. public const size_t STR_BYTES;
  239. [CCode (cname = "crypto_pwhash_OPSLIMIT_INTERACTIVE")]
  240. public const size_t OPSLIMIT_INTERACTIVE;
  241. [CCode (cname = "crypto_pwhash_MEMLIMIT_INTERACTIVE")]
  242. public const size_t MEMLIMIT_INTERACTIVE;
  243. [CCode (cname = "crypto_pwhash_OPSLIMIT_MODERATE")]
  244. public const size_t OPSLIMIT_MODERATE;
  245. [CCode (cname = "crypto_pwhash_MEMLIMIT_MODERATE")]
  246. public const size_t MEMLIMIT_MODERATE;
  247. [CCode (cname = "crypto_pwhash_OPSLIMIT_SENSITIVE")]
  248. public const size_t OPSLIMIT_SENSITIVE;
  249. [CCode (cname = "crypto_pwhash_MEMLIMIT_SENSITIVE")]
  250. public const size_t MEMLIMIT_SENSITIVE;
  251. [CCode (cname = "crypto_pwhash_str")]
  252. private int pwhash_str(
  253. [CCode (array_length = false)] uint8[] out,
  254. string passwd,
  255. size_t passwdlen,
  256. ulong opslimit,
  257. size_t memlimit
  258. );
  259. public string? hash(string password, ulong opslimit = OPSLIMIT_MODERATE, size_t memlimit = MEMLIMIT_MODERATE) {
  260. uint8[] out_buf = new uint8[STR_BYTES];
  261. if (pwhash_str(out_buf, password, password.length, opslimit, memlimit) != 0) {
  262. return null;
  263. }
  264. // Null-terminated string
  265. return (string)out_buf;
  266. }
  267. [CCode (cname = "crypto_pwhash_str_verify")]
  268. private int pwhash_str_verify(string hash, string password, size_t passwdlen);
  269. public bool check(string hash, string password) {
  270. return pwhash_str_verify(hash, password, password.length) == 0;
  271. }
  272. }
  273. }