Сегодня мы рассмотрим как шифровать важные данные с помощью CryptoJS и сохранить их в
базу Couchbase Mobile на устройстве.
Couchbase Mobile это встраиваемая NoSQL база данных для мобильных устройств. Она часто используется как замена SQLite.
Программа в примере чисто гипотетически может даже быть использована Секретной Службой США, так как она безопасно хранит кодовые имена [бывших] американских президентов.
Чтобы работать с базой данных Couchbase Mobile, мы будем использовать плагин NativeScript Couchbase, созданный Nic Raboy.
С CryptoJS возможна работа с различными алгоритмами шифрования. Мы будем использовать алгоритм шифрования AES-256, используемый АНБ для суперсекретной информации.
Разрабатывать приложение будем с помощью NativeScript и Angular под iOS, это мой любимый инструментарий разработки {N} приложений.
Так как NativeScript кроссплатформен, вы так же можете писать под Android. Просто используйте специфичные для него команды. Вместо «ios» пишите «android» и у вас всё получится! 😉
Вы можете выполнить описанное ниже или же просто скачать готовый пример NSNL_Couchbase с GitHub.
1. Создание приложения на NativeScript и Angular
С помощью следующих команд мы создадим новый проект и добавим в него платформу iOS:
tns create projectname --ng
cd projectname
tns platform add ios
2. Установка crypto-js
crypto-js это пакет npm, поэтому он устанавливается стандартно:
npm install crypto-js --save
3. Установка плагина couchbase
Couchbase Mobile это плагин NativeScript, поэтому он устанавливается стандартно:
tns plugin add nativescript-couchbase
4. Сборка проекта
После установки плагина обязательно пересобирайте проект:
tns build ios
5. Запуск приложения
Давайте запустим наше приложение и проверим возможные ошибки:
tns run ios
Если у вас будут подобные ошибки, перезапустите компьютер и вернитесь к шагу 4:
Error: Uncaught (in promise): ReferenceError: Can't find variable: CBLManager
6. Редактируем app.component.ts
Давайте заменим стандартный код на наш.
Сверху у нас будет label, показывающий сколько документов хранится в нашей базе данных.
Ниже идут две кнопки: одна для загрузки нескольких президентов в программу с сохранением их в базу и другая для удаления всех из программы и базы данных.
И, наконец, идёт список list-view, в котором отображаются имена и зашифрованные кодовые имена каждого президента. При нажатии на президента в списке, отображается расшифрованное кодовое имя.
7. Редактируем references.d.ts
Поскольку мы используем Angular, нужно добавить строку в файл references.d.ts. Она добавляет определение типов для этого плагина. Определения типов нужны для проверки типов, автодополнения кода и документации в IDE.
///
8. Редактируем app.component.ts
Нам нужно импортировать модуль Couchbase и библиотеку CryptoJS:
import {Couchbase} from "nativescript-couchbase";
let CryptoJS = require("crypto-js");
Теперь удалим переменную-счётчик и функции message() и onTap() из класса AppComponent и заменим их следующим кодом:
private database: Couchbase;
private header: string = 'No documents found!';
private presidentList = [];
readonly VERY_SECRET_CODE: string = 'My very secret code';
Мы задали базу данных, заголовок с текстом, массив для показа президентов в списке и VERY_SECRET_CODE как ключ шифрования.
Внимание:
В настоящей программе никогда не храните в коде ключ шифрования. Более грамотно будет дать пользователю возможность вводить свою фразу или цифровой код (но не забудьте его преобразовать в строку методом .toString(), потому как фраза должна быть строкой!). Затем вы будете использовать эту фразу или код каждый раз при шифровании/дешифровке данных.
А теперь добавим конструктор класса, в нём прокомментирована каждая строка:
public constructor() {
// откроем или создадаим базу данных
this.database = new Couchbase("sampledb");
// нам необходим view для хранения и извлечения данных
this.database.createView("sampledata", "1", function (document, emitter) {
emitter.emit(document._id, document);
});
// извлечём документы в этот view
let documents = this.database.executeQuery("sampledata");
// первый документ доступен?
if (documents[0]) {
// показать количество документов в заголовке
this.header = 'Found ' + (documents.length) + ' documents!';
// пройдёмся по всем документам
for (let i = 0; i < documents.length; i++) {
// и добавим каждый документ в список
this.presidentList.push(documents[i]);
}
}
}
Добавим два частных метода для шифрования и расшифровки данных:
private _encryptData(data: string): string {
// используем шифрование AES-256 -> очень безопасное
let cipherText = CryptoJS.AES.encrypt(data, this.VERY_SECRET_CODE);
return cipherText;
}
private _decryptData(data: string): string {
// сначала расшифруем в байты
let bytes = CryptoJS.AES.decrypt(data.toString(), this.VERY_SECRET_CODE);
// преобразуем байты в текст
let plainText = bytes.toString(CryptoJS.enc.Utf8);
return plainText;
}
И добавим метод loadSaveData() для кнопки "Load & save":
public loadSaveData() {
// зашифруем кодовое имя
let encryptedCodeName: string = this._encryptData('Renegade');
// создадим строку JSON
let president:string = '{"name": "Barack Obama", "codename": "' + encryptedCodeName + '"}';
// сконвертируем в объект JSON
let presidentObj: any = JSON.parse(president);
// создадим новый документ
this.database.createDocument(presidentObj);
// создадим документ для каждого президента
this.database.createDocument(JSON.parse('{"name": "George W. Bush", "codename": "' + this._encryptData('Trailblazer') + '"}'));
this.database.createDocument(JSON.parse('{"name": "Bill Clinton", "codename": "' + this._encryptData('Eagle') + '"}'));
this.database.createDocument(JSON.parse('{"name": "Ronald Reagan", "codename": "' + this._encryptData('Rawhide') + '"}'));
// извлечём документы в наш view
let documents = this.database.executeQuery("sampledata");
// отобразим количество документов в заголовке
this.header = 'Found ' + (documents.length) + ' documents!';
// цикл по всем документам
for (let i = 0; i < documents.length; i++) {
// добавим каждый документ в список
this.presidentList.push(documents[i]);
}
}
Внимание:
В настоящей программе никогда так не загружайте данные в базу, здесь кодовые имена жестко прописаны в коде программы. Лучше всего создать форму для ввода данных пользователем или создать безопасный REST API для загрузки данных с доверенного сервера.
Теперь добавим метод deleteData() для кнопки "Delete all":
public deleteData() {
// извлечём документы в этот view
let documents = this.database.executeQuery("sampledata");
// цикл по всем документам
for (let i = 0; i < documents.length; i++) {
// удалим каждый документ
// couchbase присвоит id (_id) документу при создании
this.database.deleteDocument(documents[i]._id);
}
// очистим массив с президентами, это удалит их из listview
this.presidentList = [];
// изменим заголовок
this.header = 'All documents are deleted!';
}
И, наконец, удостоверимся, что показываем расшифрованное кодовое имя для выбранного президента.
public showCodeName(event) {
// event содержит индекс нажатого элемента
// по этому индексу мы извлекаем зашифрованное кодовое имя и расшифровываем его
alert(this._decryptData(this.presidentList[event.index].codename));
}
Рекомендую посмотреть более расширенный пример NSNL_Couchbase на GitHub, в котором также используется Angular routing.
* Оригинал взят у NativeScript.nl
Разработчик: java, kotlin, c#, javascript, dart, 1C, python, php.
Пишите: @ighar. Buy me a coffee, please :).