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;
}
|