add encryption support

This commit is contained in:
Ari Lazier 2016-02-26 11:08:59 -08:00
parent f26415cd02
commit e495cc4685
5 changed files with 111 additions and 37 deletions

View File

@ -31,6 +31,7 @@
#include <cassert> #include <cassert>
using namespace realm; using namespace realm;
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
class RJSRealmDelegate : public BindingContext { class RJSRealmDelegate : public BindingContext {
public: public:
@ -152,17 +153,15 @@ JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t a
Realm::Config config; Realm::Config config;
std::map<std::string, realm::ObjectDefaults> defaults; std::map<std::string, realm::ObjectDefaults> defaults;
std::map<std::string, JSObjectRef> constructors; std::map<std::string, JSObjectRef> constructors;
switch (argumentCount) { if (argumentCount == 0) {
case 0:
config.path = RJSDefaultPath(); config.path = RJSDefaultPath();
break; }
case 1: { else if (argumentCount == 1) {
JSValueRef value = arguments[0]; JSValueRef value = arguments[0];
if (JSValueIsString(ctx, value)) { if (JSValueIsString(ctx, value)) {
config.path = RJSValidatedStringForValue(ctx, value, "path"); config.path = RJSValidatedStringForValue(ctx, value, "path");
break;
} }
if (JSValueIsObject(ctx, value)) { else if (JSValueIsObject(ctx, value)) {
JSObjectRef object = RJSValidatedValueToObject(ctx, value); JSObjectRef object = RJSValidatedValueToObject(ctx, value);
static JSStringRef pathString = JSStringCreateWithUTF8CString("path"); static JSStringRef pathString = JSStringCreateWithUTF8CString("path");
@ -188,10 +187,16 @@ JSObjectRef RealmConstructor(JSContextRef ctx, JSObjectRef constructor, size_t a
else { else {
config.schema_version = 0; config.schema_version = 0;
} }
break;
static JSStringRef encryptionKeyString = JSStringCreateWithUTF8CString("encryptionKey");
JSValueRef encryptionKeyValue = RJSValidatedPropertyValue(ctx, object, encryptionKeyString);
if (!JSValueIsUndefined(ctx, encryptionKeyValue)) {
std::string encryptionKey = RJSAccessor::to_binary(ctx, encryptionKeyValue);
config.encryption_key = std::vector<char>(encryptionKey.begin(), encryptionKey.end());;
} }
} }
default: }
else {
*jsException = RJSMakeError(ctx, "Invalid arguments when constructing 'Realm'"); *jsException = RJSMakeError(ctx, "Invalid arguments when constructing 'Realm'");
return NULL; return NULL;
} }

View File

@ -72,6 +72,9 @@ Realm::Realm(Config config)
m_group = m_read_only_group.get(); m_group = m_read_only_group.get();
} }
else { else {
if (m_config.encryption_key.data() && m_config.encryption_key.size() != 64) {
throw InvalidEncryptionKeyException();
}
m_history = realm::make_client_history(m_config.path, m_config.encryption_key.data()); m_history = realm::make_client_history(m_config.path, m_config.encryption_key.data());
SharedGroup::DurabilityLevel durability = m_config.in_memory ? SharedGroup::durability_MemOnly : SharedGroup::DurabilityLevel durability = m_config.in_memory ? SharedGroup::durability_MemOnly :
SharedGroup::durability_Full; SharedGroup::durability_Full;

View File

@ -199,6 +199,11 @@ namespace realm {
public: public:
UnitializedRealmException(std::string message) : std::runtime_error(message) {} UnitializedRealmException(std::string message) : std::runtime_error(message) {}
}; };
class InvalidEncryptionKeyException : public std::runtime_error {
public:
InvalidEncryptionKeyException() : std::runtime_error("Encryption key must be 64 bytes.") {}
};
} }
#endif /* defined(REALM_REALM_HPP) */ #endif /* defined(REALM_REALM_HPP) */

View File

@ -0,0 +1,60 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////
'use strict';
var Realm = require('realm');
var BaseTest = require('./base-test');
var TestCase = require('./asserts');
var Schemas = require('./schemas');
module.exports = BaseTest.extend({
testEncryptedInvalidKeys: function() {
// test failure with invalid keys
TestCase.assertThrows(function() {
new Realm({schema: [Schemas.TestObject], encryptionKey: " ".repeat(64)});
}, "Encryption Key must be an ArrayBuffer");
TestCase.assertThrows(function() {
new Realm({schema: [Schemas.TestObject], encryptionKey: new Int8Array(63)});
}, "Encryption Key must be 64 byes");
},
testEncryptionValidKey: function() {
var key = new Int8Array(64);
key[0] = 1;
var realm = new Realm({schema: [Schemas.TestObject], encryptionKey: key});
realm.write(function() {
realm.create('TestObject', {doubleCol: 1});
TestCase.assertEqual(realm.objects('TestObject').length, 1);
});
// test failure with different or missing
realm.close();
TestCase.assertThrows(function() {
new Realm({schema: [Schemas.TestObject], encryptionKey: new Int8Array(64)});
});
TestCase.assertThrows(function() {
new Realm({schema: [Schemas.TestObject]});
});
// test can reopen with original key
var realm = new Realm({schema: [Schemas.TestObject], encryptionKey: key});
TestCase.assertEqual(realm.objects('TestObject').length, 1);
},
});

View File

@ -24,6 +24,7 @@ var TESTS = {
RealmTests: require('./realm-tests'), RealmTests: require('./realm-tests'),
ResultsTests: require('./results-tests'), ResultsTests: require('./results-tests'),
QueryTests: require('./query-tests'), QueryTests: require('./query-tests'),
QueryTests: require('./encryption-tests'),
}; };
var SPECIAL_METHODS = { var SPECIAL_METHODS = {