From: http://cn.cocos2d-x.org/tutorial/show?id=2152java
C++的Base64算法實現android
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
/*
* base64.cpp
*
* Created on: 30/04/2011
* Author: nicholas
*/
#include "base64.h"
#include <cctype>
//#include <cstdint>
#include <algorithm>
namespace
base64
{
namespace
{
static
const
std::string BASE64_CHARS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
;
size_t
encoded_size(
size_t
raw)
{
switch
((raw*8)%6)
{
case
0:
return
(raw*8)/6;
case
2:
return
((raw*8)/6) + 3;
case
4:
return
((raw*8)/6) + 2;
}
return
raw;
}
size_t
decoded_size(
size_t
unpadded)
{
return
(unpadded*6)/8;
}
int
base64_index(std::string::value_type c)
{
if
(c >=
'A'
&& c <=
'Z'
)
return
c-
'A'
;
else
if
(c >=
'a'
&& c <=
'z'
)
return
c-
'a'
+ 26;
else
if
(c >=
'0'
&& c <=
'9'
)
return
c-
'0'
+ 52;
else
if
(c ==
'+'
)
return
62;
else
if
(c ==
'/'
)
return
63;
else
return
-1;
}
}
encode_t::encode_t(std::string::size_type size)
: state(zero), remainder(0)
{
encoded.reserve(encoded_size(size));
}
/*
State zero
8 bits input, zero remaining from last
6 bits consumed, 2 remaining
=> two
State two
8 bits input, 2 remaining from last
4 bits consumed, 4 remaining
=> four
State four
8 bits input, 4 remaining from last
2 bits consumed, 6 remaining
6 bits input, 6 remaining from last
6 bits consumed, 0 remaining
=> zero
*/
void
encode_t::operator() (std::string::value_type c)
{
unsigned
char
value(0);
switch
(state)
{
case
zero:
value = (c & 0xfc) >> 2;
remainder = c & 0x3;
encoded.push_back(BASE64_CHARS[value]);
state = two;
break
;
case
two:
value = (remainder << 4) | ((c & 0xf0) >> 4);
remainder = c & 0xf;
encoded.push_back(BASE64_CHARS[value]);
state = four;
break
;
case
four:
value = (remainder << 2) | ((c & 0xc0) >> 6);
remainder = c & 0x3f;
encoded.push_back(BASE64_CHARS[value]);
value = remainder;
encoded.push_back(BASE64_CHARS[value]);
state = zero;
break
;
}
}
std::string encode_t::str()
{
unsigned
char
value(0);
switch
(state)
{
case
zero:
break
;
case
two:
value = remainder << 4;
encoded.push_back(BASE64_CHARS[value]);
encoded.push_back(
'='
);
encoded.push_back(
'='
);
state = zero;
break
;
case
four:
value = remainder << 2;
encoded.push_back(BASE64_CHARS[value]);
encoded.push_back(
'='
);
state = zero;
break
;
}
return
encoded;
}
decode_t::decode_t(std::string::size_type size)
: state(zero), remainder(0)
{
decoded.reserve(decoded_size(size));
}
/*
State zero
6 bits input, zero remaining from last
6 bits consumed, zero remaining
=> six
State six
6 bits input, 6 remaining from last
write 1 byte, 4 remaining
=> four
State four
6 bits input, 4 remaining from last
write 1 byte, 2 remaining
=> two
State two
6 bits input, 2 remaining from last
write 1 byte, 0 remaining
=> zero
*/
void
decode_t::operator() (std::string::value_type c)
{
unsigned
char
value(0);
int
index = base64_index(c);
if
(index == -1)
return
;
switch
(state)
{
case
zero:
remainder = index;
state = six;
break
;
case
six:
value = (remainder << 2) | ((index & 0x30) >> 4);
remainder = index & 0xf;
decoded.push_back(value);
state = four;
break
;
case
four:
value = (remainder << 4) | ((index & 0x3c) >> 2);
remainder = index & 0x3;
decoded.push_back(value);
state = two;
break
;
case
two:
value = (remainder << 6) | index;
decoded.push_back(value);
state = zero;
break
;
}
}
std::string decode_t::str()
const
{
return
decoded;
}
std::string encode(
const
std::string& str)
{
return
std::for_each(str.begin(), str.end(), encode_t(str.size())).str();
}
std::string decode(
const
std::string& str)
{
size_t
unpadded_size = str.size();
if
(str.size() > 0 && str[str.size()-1] ==
'='
)
unpadded_size -= 1;
if
(str.size() > 1 && str[str.size()-2] ==
'='
)
unpadded_size -= 1;
return
std::for_each(str.begin(), str.end(), decode_t(unpadded_size)).str();
}
}
|
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
|
/*
* base64.h
*
* Created on: 30/04/2011
* Author: nicholas
*/
#ifndef BASE64_H_
#define BASE64_H_
#include <string>
namespace
base64
{
class
encode_t
{
private
:
enum
{
zero = 0,
two,
four
} state;
unsigned
int
remainder;
std::string encoded;
public
:
encode_t(std::string::size_type size);
void
operator() (std::string::value_type c);
std::string str();
};
class
decode_t
{
private
:
enum
{
zero = 0,
six,
four,
two
} state;
unsigned
int
remainder;
std::string decoded;
public
:
decode_t(std::string::size_type size);
void
operator() (std::string::value_type c);
std::string str()
const
;
};
/*
* Encode the given string @str into its base64 representation
*/
std::string encode(
const
std::string& str);
/*
* Decode the base64 encoded string @str
*/
std::string decode(
const
std::string& str);
}
#endif /* BASE64_H_ */
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include<iostream>
#include"base64.h"
using
namespace
std;
int
main ()
{
string str =
"abcdefghijklmn."
;
string out = base64::encode(str);
cout<<
"src:"
<<str<<endl;
cout<<
"encode: "
<<out<<endl;
cout<<
"decode: "
<<base64::decode(out)<<endl;
str =
"."
;
out = base64::encode(str);
cout<<endl<<
"src:"
<<str<<endl;
cout<<
"encode: "
<< out <<endl;
cout<<
"decode: "
<< base64::decode(out) <<endl;
system
(
"pause"
);
return
1;
}
|
Android平臺下使用Base64算法加密解密數據ios
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
import com.example.base64.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.Base64;
public
class
MainActivity extends Activity {
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String src =
"abcdefjhijklmn."
;
// 加密數據
String encode = Base64.encodeToString(src.getBytes(), Base64.DEFAULT);
// 解密數據
String decode =
new
String(Base64.decode(encode, Base64.DEFAULT));
System.out.println(
"src"
+ src);
System.out.println(
"encode"
+ encode);
System.out.println(
"decode"
+ decode);
}
}
|
數據庫數據項加密算法
Cocos2d-x中操做數據庫的實現都封裝在LocalStorage這個類中。使用的是sqlite3。sql
iOS、Win32平臺的加密數據庫
1.base64.h和base64.cpp添加項目Classes目錄下。api
2.右鍵libExtensions項目附加包含目錄把base64庫所在目錄添加到包含目錄中具體路徑根據本身項目結構而定
app
3.修改localStorageSetItem方法保存數據時加密數據這裏在win32平臺下忽略加密操做是由於通常win32平臺版本是用於內部測試的ide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
void
localStorageSetItem(
const
char
*key,
const
char
*value)
{
assert
( _initialized );
// 加密數據
#
if
(CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
//CCLOG("key=%s src=%s", key, value);
std::string encodeStr = base64::encode(value);
value = encodeStr.c_str();
//CCLOG("key=%s encode=%s", key, value);
#endif
int
ok = sqlite3_bind_text(_stmt_update, 1, key, -1, SQLITE_TRANSIENT);
ok |= sqlite3_bind_text(_stmt_update, 2, value, -1, SQLITE_TRANSIENT);
ok |= sqlite3_step(_stmt_update);
ok |= sqlite3_reset(_stmt_update);
if
( ok != SQLITE_OK && ok != SQLITE_DONE)
printf
(
"Error in localStorage.setItem()\n"
);
}
|
4.修改localStorageGetItem方法獲取數據時解密數據函數
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
|
const
char
* localStorageGetItem(
const
char
*key )
{
assert
( _initialized );
int
ok = sqlite3_reset(_stmt_select);
ok |= sqlite3_bind_text(_stmt_select, 1, key, -1, SQLITE_TRANSIENT);
ok |= sqlite3_step(_stmt_select);
const
unsigned
char
*ret = sqlite3_column_text(_stmt_select, 0);
if
( ok != SQLITE_OK && ok != SQLITE_DONE && ok != SQLITE_ROW)
printf
(
"Error in localStorage.getItem()\n"
);
// 加密數據
#
if
(CC_TARGET_PLATFORM != CC_PLATFORM_WIN32)
//CCLOG("decode src=%s", ret);
if
(ret)
{
std::string decodeStr = base64::decode((
const
char
*)ret);
char
* c =
new
char
;
strcpy_s(c, decodeStr.size() + 1, decodeStr.c_str());
//CCLOG("key=%s decode=%s", key, c);
return
c;
}
#endif
return
(
const
char
*)ret;
}
|
注 意c_str()方法返回的是string對象中保留的字符串指針該指針的生命週期是跟隨string對象的。也就是若是直接返回 decodeStr.c_str()返回的將是垃圾數據由於decodeStr在函數結束後已經被銷燬了指針所指向的是垃圾數據。
這種數據庫加密方案存在如下幾個問題
1.若是別人知道我所使用的加密算法而後經過程序計算出加密串仍是能夠修改爲功的。
2.數據庫仍是能夠用相關工具打開並查看數據表。
3.每次讀寫數據時增長了加密解密的步驟下降效率。
對於Cocos2d-x中數據庫的加密有更好的解決辦法就是使用wxsqlite3點擊查看【集成wxSqlite3到Cocos2d-x】這種數據庫加密的實現是在初始化數據庫的時候加密運行時加載數據庫時候調用相關api解密加載完成後數據的讀寫效率和未加密時同樣相對比較高效。
Android平臺的加密
從LocalStorage.cpp中使用的宏能夠看出這個實如今安卓平臺下是沒法使用的。
安卓平臺下的實如今cocos2d-x-2.1.5\extensions\LocalStorage目錄下的LocalStorageAndroid.cpp中。
從localStrorageInit的實現能夠看出它是經過jni調用了java層中org/cocos2dx/lib/Cocos2dxLocalStorage的靜態方法init。
在打包安卓版Cocos2d-x遊戲時須要用到引擎的一個java庫在cocos2d-x-2.1.5\cocos2dx\platform\android\java目錄下Cocos2dxLocalStorage類就在這個庫中。
修改這個類的setItem方法在保存數據的時候加密
1
2
3
4
5
6
7
8
9
10
11
12
|
public
static
void
setItem(String key, String value) {
try
{
// 加密數據
value = Base64.encodeToString(value.getBytes(), Base64.DEFAULT);
String sql =
"replace into "
+ TABLE_NAME
+
"(key,value)values(?,?)"
;
mDatabase.execSQL(sql,
new
Object[] { key, value });
}
catch
(Exception e) {
e.printStackTrace();
}
}
|
修改這個類的getItem方法在獲取數據的時候解密
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
|
public
static
String getItem(String key) {
String ret = null;
try
{
String sql =
"select value from "
+ TABLE_NAME +
" where key=?"
;
Cursor c = mDatabase.rawQuery(sql,
new
String[] { key });
while
(c.moveToNext()) {
// only return the first value
if
(ret != null) {
Log.e(TAG,
"The key contains more than one value."
);
break
;
}
ret = c.getString(c.getColumnIndex(
"value"
));
}
c.close();
}
catch
(Exception e) {
e.printStackTrace();
}
// 解密數據
if
(ret != null) {
ret =
new
String(Base64.decode(ret, Base64.DEFAULT));
}
return
ret == null ?
""
: ret;
}
|