/
module.cc
160 lines (143 loc) · 5.31 KB
/
module.cc
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <node.h>
#include <node_buffer.h>
#include "lib/include/libntruencrypt/ntru_crypto.h"
#include <fcntl.h>
#ifdef __unix__
#include <unistd.h>
#endif
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#define WINDOWS 1
#include <Windows.h>
#endif
namespace ntru {
#ifdef __unix__
static int rand_fd;
#endif
#ifdef WINDOWS
static HCRYPTPROV rand_fd;
#endif
uint32_t getRandBytes(uint8_t* out,uint32_t numBytes) {
#ifdef __unix__
read(rand_fd,(void*)out,numBytes);
#endif
#ifdef WINDOWS
if (!CryptGenRandom(rand_fd, numBytes, (unsigned char*)out)) {
abort();
}
#endif
DRBG_RET(DRBG_OK);
}
static DRBG_HANDLE rand = 0;
static DRBG_HANDLE seedDRBG;
static char *seedPtr;
static size_t KLENNGTH = 256; // because key size of NTRU_EES743EP1 is 256
using namespace v8;
static uint8_t
get_entropy(
ENTROPY_CMD cmd,
uint8_t *out)
{
/* 2k/8 bytes of entropy are needed to instantiate a DRBG with a
* security strength of k bits. Here k = KLENNGTH.
*/
static size_t kMaxLength = KLENNGTH * 2 / 8;
static size_t index;
if (cmd == INIT) {
/* Any initialization for a real entropy source goes here. */
index = 0;
return 1;
}
if (out == NULL)
return 0;
if (cmd == GET_NUM_BYTES_PER_BYTE_OF_ENTROPY) {
/* Here we return the number of bytes needed from the entropy
* source to obtain 8 bits of entropy. Maximum is 8.
*/
*out = 1; /* this is a perfectly random source */
return 1;
}
if (cmd == GET_BYTE_OF_ENTROPY) {
if (index == kMaxLength)
return 0; /* used up all our entropy */
*out = seedPtr[index++]; /* deliver an entropy byte */
return 1;
}
return 0;
}
static void _GenerateKeyPair(const FunctionCallbackInfo<Value>& args, DRBG_HANDLE drbg) {
Isolate* isolate = args.GetIsolate();
uint16_t publen;
uint16_t privlen;
ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES743EP1, &publen,0,&privlen,0);
uint8_t* pubkey = new uint8_t[publen];
uint8_t* privkey = new uint8_t[privlen];
ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES743EP1,&publen,pubkey,&privlen,privkey);
v8::Local<Object> obj = v8::Object::New(isolate);
obj->Set(v8::String::NewFromUtf8(isolate,"private"),node::Encode(isolate,(const char*)privkey,privlen,node::encoding::BUFFER));
obj->Set(v8::String::NewFromUtf8(isolate,"public"),node::Encode(isolate,(const char*)pubkey,publen,node::encoding::BUFFER));
args.GetReturnValue().Set(obj);
free(pubkey);
free(privkey);
}
void GenKey(const FunctionCallbackInfo<Value>& args) {
if (args[0]->IsUndefined()) {
if (rand != 0) {
ntru_crypto_drbg_uninstantiate(rand);
}
ntru_crypto_drbg_external_instantiate(getRandBytes,&rand);
_GenerateKeyPair(args, rand);
} else {
seedPtr = node::Buffer::Data(args[0]);
ntru_crypto_drbg_instantiate(KLENNGTH, NULL, 0, (ENTROPY_FN) &get_entropy, &seedDRBG);
_GenerateKeyPair(args, seedDRBG);
ntru_crypto_drbg_uninstantiate(seedDRBG);
}
}
void EncryptData(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
size_t dlen = node::Buffer::Length(args[0]);
char* ptr = node::Buffer::Data(args[0]);
size_t publen = node::Buffer::Length(args[1]);
char* pubkey = node::Buffer::Data(args[1]);
uint16_t outlen;
ntru_crypto_ntru_encrypt(rand,publen,(unsigned char*)pubkey,dlen,(unsigned char*)ptr,&outlen,0);
v8::Local<v8::Value> outbuffer = node::Buffer::New(isolate,outlen).ToLocalChecked();
ntru_crypto_ntru_encrypt(rand,publen,(unsigned char*)pubkey,dlen,(unsigned char*)ptr,&outlen,(unsigned char*)node::Buffer::Data(outbuffer));
v8::Local<v8::Object> output = v8::Object::New(isolate);
output->Set(String::NewFromUtf8(isolate,"buffer"),outbuffer);
output->Set(String::NewFromUtf8(isolate,"length"),Int32::NewFromUnsigned(isolate,(uint32_t)outlen));
args.GetReturnValue().Set(output);
}
void DecryptData(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
size_t dlen = node::Buffer::Length(args[0]);
char* ptr = node::Buffer::Data(args[0]);
size_t privlen = node::Buffer::Length(args[1]);
char* privkey = node::Buffer::Data(args[1]);
uint16_t outlen;
ntru_crypto_ntru_decrypt(privlen,(unsigned char*)privkey,dlen,(unsigned char*)ptr,&outlen,0);
v8::Local<v8::Value> outbuffer = node::Buffer::New(isolate,outlen).ToLocalChecked();
memset(node::Buffer::Data(outbuffer),0,outlen);
ntru_crypto_ntru_decrypt(privlen,(unsigned char*)privkey,dlen,(unsigned char*)ptr,&outlen,(unsigned char*)node::Buffer::Data(outbuffer));
v8::Local<v8::Object> output = v8::Object::New(isolate);
output->Set(String::NewFromUtf8(isolate,"buffer"),outbuffer);
output->Set(String::NewFromUtf8(isolate,"length"),Int32::NewFromUnsigned(isolate,(uint32_t)outlen));
args.GetReturnValue().Set(output);
if (rand != 0) {
ntru_crypto_drbg_uninstantiate(rand);
rand = 0;
}
}
void init(Local<Object> exports) {
#ifdef __unix__
rand_fd = open("/dev/urandom",O_RDONLY);
#endif
#ifdef WINDOWS
CryptAcquireContextA(&rand_fd, 0, NULL, PROV_RSA_FULL, 0);
#endif
NODE_SET_METHOD(exports, "genKey", GenKey);
NODE_SET_METHOD(exports,"encrypt",EncryptData);
NODE_SET_METHOD(exports,"decrypt",DecryptData);
}
NODE_MODULE(addon, init)
}