Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update JsThemis tests #620

Merged
merged 13 commits into from
Apr 9, 2020
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ _Code:_

- New class `SymmetricKey` can be used to generate symmetric keys for Secure Cell ([#562](https://github.com/cossacklabs/themis/pull/562)).
- New makefile target `make jsthemis` can be used to build JsThemis from source ([#618](https://github.com/cossacklabs/themis/pull/618)).
- `SecureCell` now allows `null` to explicitly specify omitted encryption context ([#620](https://github.com/cossacklabs/themis/pull/620)).
- `SecureMessage` now allows `null` for omitted keys in sign/verify mode ([#620](https://github.com/cossacklabs/themis/pull/620)).
- Fixed a crash when an exception is thrown from `SecureSession` callback ([#620](https://github.com/cossacklabs/themis/pull/620)).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we add that we've changed the type of thrown errors from NaN::Error to NaN::TypeError? I'm not sure how js devs are used to catch errors (if they do catch errors), but it might be useful for them to know that error type has changed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we add that we've changed the type of thrown errors?

I don't think it's necessary. It is a programming error to pass an invalid type so it should be caught during development, not at run-time. If it's absolutely necessary to catch it at runtime then any existing catch clause for Error (which we have been throwing before) will catch TypeError too because it's a subclass.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, makes sense


- **PHP**

Expand Down
10 changes: 10 additions & 0 deletions src/wrappers/themis/jsthemis/errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ void ThrowError(const char* domain, themis_status_t status)
Nan::ThrowError(WithStatus(Nan::Error(message.c_str()), status));
}

void ThrowTypeError(const char* domain, const char* description)
{
std::string message;
message += "themis.";
message += domain;
message += ": ";
message += description;
Nan::ThrowError(Nan::TypeError(message.c_str()));
}

void ThrowParameterError(const char* domain, const char* description)
{
std::string message;
Expand Down
2 changes: 2 additions & 0 deletions src/wrappers/themis/jsthemis/errors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ void Init(v8::Local<v8::Object> exports);

void ThrowError(const char* domain, themis_status_t status);

void ThrowTypeError(const char* domain, const char* description);

void ThrowParameterError(const char* domain, const char* description);

void ThrowSecureSessionError(const char* domain, themis_status_t status);
Expand Down
19 changes: 9 additions & 10 deletions src/wrappers/themis/jsthemis/secure_cell_context_imprint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ void SecureCellContextImprint::New(const Nan::FunctionCallbackInfo<v8::Value>& a
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Context Imprint) constructor",
"master key is not a byte buffer");
ThrowTypeError("SecureCellContextImprint", "master key is not a byte buffer");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down Expand Up @@ -96,8 +95,8 @@ void SecureCellContextImprint::encrypt(const Nan::FunctionCallbackInfo<v8::Value
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Context Imprint) failed to encrypt",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellContextImprint",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand All @@ -107,8 +106,8 @@ void SecureCellContextImprint::encrypt(const Nan::FunctionCallbackInfo<v8::Value
return;
}
if (!args[1]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Context Imprint) failed to encrypt",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellContextImprint",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down Expand Up @@ -162,8 +161,8 @@ void SecureCellContextImprint::decrypt(const Nan::FunctionCallbackInfo<v8::Value
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Context Imprint) failed to decrypt",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellContextImprint",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand All @@ -173,8 +172,8 @@ void SecureCellContextImprint::decrypt(const Nan::FunctionCallbackInfo<v8::Value
return;
}
if (!args[1]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Context Imprint) failed to decrypt",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellContextImprint",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down
22 changes: 10 additions & 12 deletions src/wrappers/themis/jsthemis/secure_cell_seal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ void SecureCellSeal::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Seal) constructor",
"master key is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellSeal",
"master key is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down Expand Up @@ -96,8 +96,7 @@ void SecureCellSeal::encrypt(const Nan::FunctionCallbackInfo<v8::Value>& args)
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Seal) failed to encrypt",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellSeal", "message is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand All @@ -109,10 +108,10 @@ void SecureCellSeal::encrypt(const Nan::FunctionCallbackInfo<v8::Value>& args)
size_t length = 0;
const uint8_t* context = NULL;
size_t context_length = 0;
if (args.Length() == 2) {
if (args.Length() == 2 && !args[1]->IsNull()) {
if (!args[1]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Seal) failed to encrypt",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellSeal",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down Expand Up @@ -161,8 +160,7 @@ void SecureCellSeal::decrypt(const Nan::FunctionCallbackInfo<v8::Value>& args)
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Seal) failed to decrypt",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellSeal", "message is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand All @@ -174,10 +172,10 @@ void SecureCellSeal::decrypt(const Nan::FunctionCallbackInfo<v8::Value>& args)
size_t length = 0;
const uint8_t* context = NULL;
size_t context_length = 0;
if (args.Length() == 2) {
if (args.Length() == 2 && !args[1]->IsNull()) {
if (!args[1]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Seal) failed to decrypt",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellSeal",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down
28 changes: 14 additions & 14 deletions src/wrappers/themis/jsthemis/secure_cell_token_protect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ void SecureCellTokenProtect::New(const Nan::FunctionCallbackInfo<v8::Value>& arg
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Token Protect) constructor",
"master key is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellTokenProtect",
"master key is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down Expand Up @@ -96,8 +96,8 @@ void SecureCellTokenProtect::encrypt(const Nan::FunctionCallbackInfo<v8::Value>&
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Token Protect) failed to encrypt",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellTokenProtect",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand All @@ -110,10 +110,10 @@ void SecureCellTokenProtect::encrypt(const Nan::FunctionCallbackInfo<v8::Value>&
size_t token_length = 0;
const uint8_t* context = NULL;
size_t context_length = 0;
if (args.Length() == 2) {
if (args.Length() == 2 && !args[1]->IsNull()) {
if (!args[1]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Token Protect) failed to encrypt",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellTokenProtect",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down Expand Up @@ -175,8 +175,8 @@ void SecureCellTokenProtect::decrypt(const Nan::FunctionCallbackInfo<v8::Value>&
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Token Protect) failed to decrypt",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellTokenProtect",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand All @@ -186,8 +186,8 @@ void SecureCellTokenProtect::decrypt(const Nan::FunctionCallbackInfo<v8::Value>&
return;
}
if (!args[1]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Token Protect) failed to decrypt",
"token is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellTokenProtect",
"token is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand All @@ -199,10 +199,10 @@ void SecureCellTokenProtect::decrypt(const Nan::FunctionCallbackInfo<v8::Value>&
size_t length = 0;
const uint8_t* context = NULL;
size_t context_length = 0;
if (args.Length() == 3) {
if (args.Length() == 3 && !args[2]->IsNull()) {
if (!args[2]->IsUint8Array()) {
ThrowParameterError("Secure Cell (Token Protect) failed to decrypt",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureCellTokenProtect",
"context is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down
7 changes: 3 additions & 4 deletions src/wrappers/themis/jsthemis/secure_comparator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ void SecureComparator::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Comparator constructor",
"secret is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureComparator",
"secret is not a byte buffer, use ByteBuffer or Uint8Array");
return;
}
if (node::Buffer::Length(args[0]) == 0) {
Expand Down Expand Up @@ -133,8 +133,7 @@ void SecureComparator::proceedCompare(const Nan::FunctionCallbackInfo<v8::Value>
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Comparator failed to proceed comparison",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureComparator", "message is not a byte buffer, use ByteBuffer or Uint8Array");
return;
}
if (node::Buffer::Length(args[0]) == 0) {
Expand Down
12 changes: 5 additions & 7 deletions src/wrappers/themis/jsthemis/secure_keygen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ void KeyPair::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
if (args.IsConstructCall()) {
if (args.Length() == 2) {
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Key Pair constructor",
"private key is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("KeyPair",
"private key is not a byte buffer, use ByteBuffer or Uint8Array");
return;
}
if (node::Buffer::Length(args[0]) == 0) {
ThrowParameterError("Key Pair constructor", "private key is empty");
return;
}
if (!args[1]->IsUint8Array()) {
ThrowParameterError("Key Pair constructor",
"public key is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("KeyPair",
"public key is not a byte buffer, use ByteBuffer or Uint8Array");
return;
}
if (node::Buffer::Length(args[1]) == 0) {
Expand Down Expand Up @@ -228,8 +228,7 @@ void SymmetricKey::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
// a byte buffer that we copy.
v8::Local<v8::Value> value = args[0];
if (!value->IsUint8Array()) {
ThrowParameterError("Themis SymmetricKey",
"key is not a byte buffer (use Buffer or Uint8Array)");
ThrowTypeError("SymmetricKey", "key is not a byte buffer (use Buffer or Uint8Array)");
args.GetReturnValue().SetUndefined();
return;
}
Expand All @@ -240,7 +239,6 @@ void SymmetricKey::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
}

args.GetReturnValue().Set(CopyIntoBuffer(value));
return;
}

// TODO: return properly inherited instances of SymmetricKey
Expand Down
58 changes: 34 additions & 24 deletions src/wrappers/themis/jsthemis/secure_message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ void SecureMessage::Init(v8::Local<v8::Object> exports)
Nan::Set(exports, className, function);
}

static inline void assign_buffer_to_vector(std::vector<uint8_t>& vector,
const v8::Local<v8::Value>& buffer)
{
const uint8_t* data = reinterpret_cast<const uint8_t*>(node::Buffer::Data(buffer));
size_t length = node::Buffer::Length(buffer);
vector.assign(data, data + length);
}

void SecureMessage::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
{
if (args.IsConstructCall()) {
Expand All @@ -66,24 +74,26 @@ void SecureMessage::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
args.GetReturnValue().SetUndefined();
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Message constructor",
"private key is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
std::vector<uint8_t> private_key;
if (!args[0]->IsNull()) {
if (!args[0]->IsUint8Array()) {
ThrowTypeError("SecureMessage",
"private key is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
assign_buffer_to_vector(private_key, args[0]);
}
if (!args[1]->IsUint8Array()) {
ThrowParameterError("Secure Message constructor",
"public key is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
std::vector<uint8_t> public_key;
if (!args[1]->IsNull()) {
if (!args[1]->IsUint8Array()) {
ThrowTypeError("SecureMessage",
"public key is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
assign_buffer_to_vector(public_key, args[1]);
}
std::vector<uint8_t> private_key((uint8_t*)(node::Buffer::Data(args[0])),
(uint8_t*)(node::Buffer::Data(args[0])
+ node::Buffer::Length(args[0])));
std::vector<uint8_t> public_key((uint8_t*)(node::Buffer::Data(args[1])),
(uint8_t*)(node::Buffer::Data(args[1])
+ node::Buffer::Length(args[1])));
if (!ValidateKeys(private_key, public_key)) {
args.GetReturnValue().SetUndefined();
return;
Expand All @@ -102,6 +112,10 @@ void SecureMessage::New(const Nan::FunctionCallbackInfo<v8::Value>& args)
bool SecureMessage::ValidateKeys(const std::vector<uint8_t>& private_key,
const std::vector<uint8_t>& public_key)
{
if (private_key.empty() && public_key.empty()) {
ThrowParameterError("SecureMessage", "private and public key cannot be both empty");
return false;
}
if (!private_key.empty()) {
if (!IsValidKey(private_key)) {
ThrowParameterError("Secure Message constructor", "invalid private key");
Expand Down Expand Up @@ -146,8 +160,7 @@ void SecureMessage::encrypt(const Nan::FunctionCallbackInfo<v8::Value>& args)
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Message failed to encrypt message",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureMessage", "message is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down Expand Up @@ -209,8 +222,7 @@ void SecureMessage::decrypt(const Nan::FunctionCallbackInfo<v8::Value>& args)
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Message failed to decrypt message",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureMessage", "message is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down Expand Up @@ -267,8 +279,7 @@ void SecureMessage::sign(const Nan::FunctionCallbackInfo<v8::Value>& args)
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Message failed to sign message",
"message is not a byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureMessage", "message is not a byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down Expand Up @@ -321,8 +332,7 @@ void SecureMessage::verify(const Nan::FunctionCallbackInfo<v8::Value>& args)
return;
}
if (!args[0]->IsUint8Array()) {
ThrowParameterError("Secure Message failed to verify signature",
"message is not byte buffer, use ByteBuffer or Uint8Array");
ThrowTypeError("SecureMessage", "message is not byte buffer, use ByteBuffer or Uint8Array");
args.GetReturnValue().SetUndefined();
return;
}
Expand Down
Loading