我的原文所在 http://yanmin.in/archive.html
Arrow Encryption for Data in Transit
by Leor Brenman
翻译(卢彦民)
March 02, 2016 @ 6:00am
Appcelerator mobile apps use Secure Sockets Layer (SSL) for encrypting and decrypting all data transmitted and received by the device. However, for certain types of apps, one may wish to add another layer of encryption for added security. This post describes how to programmatically add additional encryption for data in transit between an Appcelerator app and an ArrowDB as illustrated below.
2016.03.02上午6:00
Appcelerator的移动应用程序使用安全套接字层(SSL)来加密和解密设备发送和接收的所有数据。然而,对于某些类型的应用程序,可能希望添加另一加密层来增加安全性。这篇文章介绍了如何以编程方式给在Appcelerator的应用程序和ArrowDB之间传输的数据增加额外的加密,正如下图所示。
Background
背景
The basic idea is to add a pre block to your Arrow model for decrypting data on a POST or PUT from the client app. This will decrypt data sent by the client app. Also, add a post block for encrypting data being sent to the client app on a GET.
其基本思想是给你的Arrow 模型为来自客户端的POST和PUT数据的解密添加一个pre block(解密块),这样将能解密客户端应用程序发送的数据。此外,为了被通过GET发送给客户端应用程序的数据的加密添加一个post block(加密块)。
For the purpose of this post, we will use a very simple XOR encryption JavaScript function from Henry Algus which is also the decryption function and is shown below:
对于这篇文章的目的,我们将使用一个来自Henry Algus的非常简单的异或加密JavaScript方法,并且这个函数也是一个解密方法,如下所示:
exports.jsEncode = function(s,k) {
var enc = "";
var str = "";
str = s.toString();
for (var i = 0; i < s.length; i++) {
var a = s.charCodeAt(i);
var b = a ^ k;
enc = enc + String.fromCharCode(b);
}
return enc;
}
Furthermore, since the Appcelerator Platform is a full stack JavaScript platform, this exact same function is used for both encryption and decryption in both the Appcelerator mobile app and the Arrow app.
此外,由于Appcelerator平台是一个完整的堆栈JavaScript平台,所以在Appcelerator移动应用和Arrow应用中的加密和解密中都可使用这一相同的方法。
Note that this XOR encryption should not be used for production apps and is strictly being used for demonstration purposes. In a production app, you may want to look at more secure encryption libraries such as the Appcelerator Premium “Crypto” Module, Securely, crypto-js or sjcl.
注意,这个异或加密不应该用于制作应用程序并且严格用于演示目的。在制作应用程序中,您可能想要看到更安全的加密库,例如Appcelerator Premium“CRypto”模块、Securely、crypto-js或sjcl。
Arrow Model
Arrow 模型
Here is a simple ArrowDB model, database, and a pre (decrypt) and post ((encrypt)) block that illustrates how to encrypt and decrypt data in Arrow:
这里是一个简单的ArrowDB模型、数据库和pre(解密)和post((加密))块,说明了如何在Arrow中加密和解密数据。
database.js
var Arrow = require("arrow");
var Model = Arrow.createModel("database",{
"fields": {
"name": {
"type": "String"
}
},
"connector": "appc.arrowdb",
"actions": [
"create",
"read",
"update",
"delete",
"deleteAll"
],
"before": "decrypt",
"after": "encrypt",
"singular": "database",
"plural": "databases"
});
module.exports = Model;
decrypt.js
var ENC_KEY = '123';
var Arrow = require('arrow');
var Utils = require('../lib/utils');
var PreBlock = Arrow.Block.extend({
name: 'decrypt',
description: 'will decrypt data from mobile app',
action: function (req, resp, next) {
if((req.method==="POST" || req.method==="PUT")) {
req.params.name = Utils.jsEncode(req.params.name, ENC_KEY);
}
next();
}
});
module.exports = PreBlock;
encrypt.js
var ENC_KEY = '123';
var Arrow = require('arrow');
var Utils = require('../lib/utils');
var PostBlock = Arrow.Block.extend({
name: 'encrypt',
description: 'will encrypt data to mobile app',
action: function (req, resp, next) {
if(req.method==="GET") {
var body = JSON.parse(resp.body);
var data = body[body.key];
var dataLen = data.length;
if(dataLen){ //findAll
data.forEach(function (_row, _index) {
_row.name = Utils.jsEncode(data[_index].name, ENC_KEY);
});
} else { //findOne
if(data.name) {
data.name = Utils.jsEncode(data.name, ENC_KEY);
}
}
resp.success(body[body.key], next);
} else {
next();
}
}
});
module.exports = PostBlock;
In the example above, a key of ‘123’ is used to encrypt and decrypt the data.
在上面的示例中,一个“123”的key是用来加密和解密数据的。
Mobile App
手机应用程序
The mobile app should encrypt the data prior to POSTing data using the jsEncode function with the same key that is used in the Arrow app (e.g. ‘123’). The example below illustrates encrypting the value of a TextField with an Alloy id of “nameTF” prior to POSTing the data in an Appcelerator mobile app.
移动应用程序应该在发送数据之前使用jsEncode函数以及和Arrow 应用相同的key(例如“123”)来加密数据。下面的例子演示了Appcelerator手机应用中在发送数据之前加密Alloy id 为“nameTF”的文本字段的值的方法。
var ENC_KEY = '123';
var xhr = Ti.Network.createHTTPClient({
onload: function onLoad() {
Ti.API.info("Loaded: " + this.status + ": " + this.responseText);
},
onerror: function onError() {
Ti.API.info("Errored: " + this.status + ": " + this.responseText);
}
});
xhr.open("POST","http://127.0.0.1:8080/api/database");
var authstr = 'Basic ' + Ti.Utils.base64encode('TCDiEh3jpghZ2rQ7ckSr1NhGo2AZURwG:');
xhr.setRequestHeader("Authorization", authstr);
xhr.setRequestHeader("Content-Type","application/json");
xhr.send(JSON.stringify({
"name": jsEncode($.nameTF.value, ENC_KEY)
}));
After a GET is called, the encrypted data received by the Appcelerator mobile app must be decrypted as illustrated below. In the example below, the received data is used to populate a TableView with an Alloy id of “TV”.
在一GET被请求后,Appcelerator移动应用接收到的加密的数据接必须解密,如下图所示。在下面的示例中,接收的数据被用于填充一个Alloy id为 “TV”的TableView的。
var ENC_KEY = '123';
var xhr = Ti.Network.createHTTPClient({
onload: function onLoad() {
Ti.API.info("Loaded: " + this.status + ": " + this.responseText);
var body = JSON.parse(this.responseText);
var data = body[body.key];
var rows = [];
if(data.length>0) {
_.each(data, function(item) {
rows.push(Alloy.createController('row', {
name: jsEncode(item.name, ENC_KEY)
}).getView());
});
}
$.TV.setData(rows);
},
onerror: function onError() {
Ti.API.info("Errored: " + this.status + ": " + this.responseText);
}
});
xhr.open("GET","http://127.0.0.1:8080/api/database");
var authstr = 'Basic ' + Ti.Utils.base64encode('TCDiEh3jpghZ2rQ7ckSr1NhGo2AZURwG:');
xhr.setRequestHeader("Authorization", authstr);
xhr.send();
Viewing Data in ArrowDB
在ArrowDB中查看数据
Recall that we are only encrypting the data in transit. The data in the ArrowDB is unencrypted. However, since we have added an encryption post block to the model for all GET operations, when we try to view the ArrowDB data in the Arrow console, we will see encrypted data as shown below:
回想一下,我们只是在运输途中加密了数据。ArrowDB中的数据是未加密的。然而,由于我们为所有的GET操作添加了一个加密块,当我们试图在Arrow控制台中查看ArrowDB的数据时,我们将看到加密了的数据,如下所示:
So, how do we view/access the unencrypted data?
那么,我们如何查看/访问未加密的数据?
One way is to use the Appcelerator Dashboard, select the Arrow app and navigate to the ArrowDB, and view the data in the Manage Data -> Custom Object section as shown below:
一种方法是使用Appcelerator仪表板,选择ArrowDB应用并导航到ArrowDB,然后在Mamage Data ->Custom Objext 部分中查看数据,如下所示:
Another technique for programmatically receiving unencrypted data is to modify the post block to look for a specific header and value and then send the data unencrypted. This code is provided here.
另一种以编程方式接收加密数据的技术是修改post块来寻找特定的header和value,然后把不加密的发送数据。代码如下。
An example curl command using this technique is shown below:
一个使用curl命令的技术例子如下所示:
$ curl -u TCDiEh3jpghZ2rQ7ckSr1NhGo2AZURwG: "http://127.0.0.1:8080/api/database" -H "admin-secret:admin-secret"
Results in the following reply:
结果如下:
{
"success": true,
"request-id": "b2a5d659-516d-49ba-a33e-629de4bab195",
"key": "databases",
"databases": [
{
"id": "564357e0dc26a0090d2f5b82",
"name": "Leor"
},
{
"id": "563d79043d24bb09100b7f6c",
"name": "Lillian"
},
{
"id": "563d78c8dc26a0090d0adfb3",
"name": "Kim"
},
{
"id": "563d78afdc26a009050af1b3",
"name": "Nate"
}
]
}
Compare this to using the curl command without the header:
比较一下没有header的curl命令的使用:
$ curl -u TCDiEh3jpghZ2rQ7ckSr1NhGo2AZURwG: "http://127.0.0.1:8080/api/database"
which returns the following encrypted data:
它返回的是以下加密的数据:
{
"success": true,
"request-id": "bf8cbf08-d2f2-4a24-a9a5-a37c0841535c",
"key": "databases",
"databases": [
{
"id": "564357e0dc26a0090d2f5b82",
"name": "7\u001e\u0014\t"
},
{
"id": "563d79043d24bb09100b7f6c",
"name": "7\u0012\u0017\u0017\u0012\u001a\u0015"
},
{
"id": "563d78c8dc26a0090d0adfb3",
"name": "0\u0012\u0016"
},
{
"id": "563d78afdc26a009050af1b3",
"name": "5\u001a\u000f\u001e"
}
]
}
Summary
总结
This post demonstrates how easy Arrow makes it to encrypt data in transit. Code for this post can be found here.
这篇文章演示了Arrow在传输途中加密数据是多么的容易。这篇文章的代码可以在这里找到。