-
-
Notifications
You must be signed in to change notification settings - Fork 93
/
argon2.cpp
114 lines (94 loc) · 3.79 KB
/
argon2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include "argon2/include/argon2.h"
#include <napi.h>
#include <string>
namespace {
class HashWorker final : public Napi::AsyncWorker {
public:
HashWorker(const Napi::Env &env, const Napi::Buffer<uint8_t> &plain,
const Napi::Buffer<uint8_t> &salt,
const Napi::Buffer<uint8_t> &secret,
const Napi::Buffer<uint8_t> &ad, uint32_t hash_length,
uint32_t memory_cost, uint32_t time_cost, uint32_t parallelism,
uint32_t version, uint32_t type)
: AsyncWorker{env, "argon2:HashWorker"}, deferred{env},
plain{plain.Data(), plain.ByteLength()},
salt{salt.Data(), salt.ByteLength()},
secret{secret.Data(), secret.ByteLength()},
ad{ad.Data(), ad.ByteLength()}, hash_length{hash_length},
memory_cost{memory_cost}, time_cost{time_cost},
parallelism{parallelism}, version{version},
type{static_cast<argon2_type>(type)} {}
auto GetPromise() -> Napi::Promise { return deferred.Promise(); }
protected:
void Execute() override {
hash.resize(hash_length);
argon2_context ctx;
ctx.out = hash.data();
ctx.outlen = static_cast<uint32_t>(hash.size());
ctx.pwd = plain.data();
ctx.pwdlen = static_cast<uint32_t>(plain.size());
ctx.salt = salt.data();
ctx.saltlen = static_cast<uint32_t>(salt.size());
ctx.secret = secret.empty() ? nullptr : secret.data();
ctx.secretlen = static_cast<uint32_t>(secret.size());
ctx.ad = ad.empty() ? nullptr : ad.data();
ctx.adlen = static_cast<uint32_t>(ad.size());
ctx.m_cost = memory_cost;
ctx.t_cost = time_cost;
ctx.lanes = parallelism;
ctx.threads = parallelism;
ctx.allocate_cbk = nullptr;
ctx.free_cbk = nullptr;
ctx.flags = ARGON2_FLAG_CLEAR_PASSWORD | ARGON2_FLAG_CLEAR_SECRET;
ctx.version = version;
if (const int result = argon2_ctx(&ctx, type); result != ARGON2_OK) {
/* LCOV_EXCL_START */
SetError(argon2_error_message(result));
/* LCOV_EXCL_STOP */
}
}
void OnOK() override {
deferred.Resolve(
Napi::Buffer<uint8_t>::Copy(Env(), hash.data(), hash.size()));
}
void OnError(const Napi::Error &err) override {
deferred.Reject(err.Value());
}
private:
using ustring = std::basic_string<uint8_t>;
Napi::Promise::Deferred deferred;
ustring hash = {};
ustring plain;
ustring salt;
ustring secret;
ustring ad;
uint32_t hash_length;
uint32_t memory_cost;
uint32_t time_cost;
uint32_t parallelism;
uint32_t version;
argon2_type type;
};
auto Hash(const Napi::CallbackInfo &info) -> Napi::Value {
NAPI_CHECK(info.Length() == 1, "Hash", "expected 1 argument");
const auto &args = info[0].As<Napi::Object>();
auto *worker = new HashWorker{info.Env(),
args["password"].As<Napi::Buffer<uint8_t>>(),
args["salt"].As<Napi::Buffer<uint8_t>>(),
args["secret"].As<Napi::Buffer<uint8_t>>(),
args["data"].As<Napi::Buffer<uint8_t>>(),
args["hashLength"].ToNumber(),
args["m"].ToNumber(),
args["t"].ToNumber(),
args["p"].ToNumber(),
args["version"].ToNumber(),
args["type"].ToNumber()};
worker->Queue();
return worker->GetPromise();
}
auto init(Napi::Env env, Napi::Object exports) -> Napi::Object {
exports["hash"] = Napi::Function::New(env, Hash);
return exports;
}
} // namespace
NODE_API_MODULE(argon2_lib, init)