--- /dev/null
+#ifndef __HASHMAP_H_
+#define __HASHMAP_H_
+
+#include<sodium.h>
+
+struct hash_map {
+ void **map;
+ size_t size;
+ unsigned char key[crypto_shorthash_KEYBYTES];
+};
+
+void *hashmap_find(struct hash_map*,void*,size_t);
+void hashmap_free(struct hash_map*);
+int hashmap_init(struct hash_map**,size_t);
+int hashmap_insert(struct hash_map*,void*,size_t,void*);
+void *hashmap_remove(struct hash_map*,void*,size_t);
+
+#endif
--- /dev/null
+#include<hashmap.h>
+
+void *hashmap_find(struct hash_map *p, void *key, size_t key_size) {
+ unsigned char hash[crypto_shorthash_KEYBYTES];
+ size_t index;
+
+ if(crypto_shorthash(hash,key,key_size,p->key)<0) { return NULL; }
+
+ index = ((uint64_t) hash)%p->size;
+ return p->map[index];
+}
+
+void hashmap_free(struct hash_map *p) {
+ for(size_t i=0;i<p->size;i++) {
+ if(p->map[i]!=NULL) { free(p->map[i]); }
+ }
+
+ if(p->map!=NULL) { free(p->map); }
+ free(p);
+}
+
+int hashmap_init(struct hash_map **p, size_t initial_size) {
+ if(sodium_init()<0) {
+ perror("sodium_init");
+ return -1;
+ }
+
+ *p = malloc(sizeof(struct hash_map));
+ if(NULL==(*p)) {
+ perror("malloc");
+ return -1;
+ }
+
+ (*p)->map = malloc(sizeof(void*)*initial_size);
+ (*p)->size = initial_size;
+
+ for(size_t i=0;i<initial_size;i++) {
+ (*p)->map[i] = NULL;
+ }
+
+ crypto_shorthash_keygen((*p)->key);
+
+ return 1;
+}
+
+int hashmap_insert(struct hash_map *p, void *key, size_t key_size, void *value) {
+ unsigned char hash[crypto_shorthash_KEYBYTES];
+ size_t index;
+
+ if(crypto_shorthash(hash,key,key_size,p->key)<0) { return -1; }
+
+ index = ((uint64_t) hash)%p->size;
+ if(p->map[index]!=NULL) { return 0; }
+
+ p->map[index] = value;
+
+ return 1;
+}
+
+void *hashmap_remove(struct hash_map *p, void *key, size_t key_size) {
+ unsigned char hash[crypto_shorthash_KEYBYTES];
+ size_t index;
+ void *removed;
+
+ if(crypto_shorthash(hash,key,key_size,p->key)<0) { return NULL; }
+
+ index = ((uint64_t) hash)%p->size;
+ removed = p->map[index];
+
+ p->map[index] = NULL;
+
+ return removed;
+}