From: http://cn.cocos2d-x.org/tutorial/show?id=2152
C++的Base64算法实现
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
@H_502_328@
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
*
*Createdon:30/04/2011
*Author:nicholas
*/
#include"base64.h"
#include<cctype>
//#include<cstdint>
#include<algorithm>
namespace
base64
{
namespace
{
static
const
std::stringBASE64_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_typec)
{
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_typesize)
:state(zero),remainder(0)
{
encoded.reserve(encoded_size(size));
}
/*
Statezero
8bitsinput,zeroremainingfromlast
6bitsconsumed,2remaining
=>two
Statetwo
8bitsinput,2remainingfromlast
4bitsconsumed,4remaining
=>four
Statefour
8bitsinput,4remainingfromlast
2bitsconsumed,6remaining
6bitsinput,6remainingfromlast
6bitsconsumed,0remaining
=>zero
*/
void
encode_t::operator()(std::string::value_typec)
{
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::stringencode_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_typesize)
:state(zero),remainder(0)
{
decoded.reserve(decoded_size(size));
}
/*
Statezero
6bitsinput,zeroremainingfromlast
6bitsconsumed,zeroremaining
=>six
Statesix
6bitsinput,6remainingfromlast
write1byte,4remaining
=>four
Statefour
6bitsinput,4remainingfromlast
write1byte,2remaining
=>two
Statetwo
6bitsinput,2remainingfromlast
write1byte,0remaining
=>zero
*/
void
decode_t::operator()(std::string::value_typec)
{
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::stringdecode_t::str()
const
{
return
decoded;
}
std::stringencode(
const
std::string&str)
{
return
std::for_each(str.begin(),str.end(),encode_t(str.size())).str();
}
std::stringdecode(
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(),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
*
*Createdon:30/04/2011
*Author:nicholas
*/
#ifndefBASE64_H_
#defineBASE64_H_
#include<string>
namespace
base64
{
class
encode_t
{
private
:
enum
{
zero=0,
two,
four
}state;
unsigned
int
remainder;
std::stringencoded;
public
:
encode_t(std::string::size_typesize);
void
operator()(std::string::value_typec);
std::stringstr();
};
class
decode_t
{
private
:
enum
{
zero=0,
six,
four,
two
}state;
unsigned
int
remainder;
std::stringdecoded;
public
:
decode_t(std::string::size_typesize);
void
operator()(std::string::value_typec);
};
/*
*Encodethegivenstring@strintoitsbase64representation
*/
std::stringencode(
const
std::string&str);
/*
*Decodethebase64encodedstring@str
*/
std::stringdecode(
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()
{
stringstr=
"abcdefghijklmn."
;
stringout=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;
return
1;
}
|
Android平台下使用Base64算法加密解密数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
importcom.example.base64.R;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.util.Base64;
public
class
MainActivityextendsActivity{
@Override
protected
void
onCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Stringsrc=
"abcdefjhijklmn."
;
//加密数据
Stringencode=Base64.encodetoString(src.getBytes(),Base64.DEFAULT);
//解密数据
Stringdecode=
new
String(Base64.decode(encode,Base64.DEFAULT));
}
}
|
数据库数据项加密
Cocos2d-x中操作数据库的实现都封装在LocalStorage这个类中。使用的是sqlite3。
iOS、Win32平台的加密
1.base64.h和base64.cpp添加项目Classes目录下。
2.右键libExtensions项目附加包含目录把base64库所在目录添加到包含目录中具体路径根据自己项目结构而定
50237902.jpg" src="http://api.cocoachina.com/uploads/20141226/1419573260430321.jpg">
3.修改localStorageSetItem方法保存数据时加密数据这里在win32平台下忽略加密操作是因为一般win32平台版本是用于内部测试的
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)
std::stringencodeStr=base64::encode(value);
value=encodeStr.c_str();
#endif
ok|=sqlite3_step(_stmt_update);
ok|=sqlite3_reset(_stmt_update);
printf
(
"ErrorinlocalStorage.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);
ok|=sqlite3_step(_stmt_select);
printf
(
"ErrorinlocalStorage.getItem()\n"
);
//加密数据
#
if
(CC_TARGET_PLATFORM!=CC_PLATFORM_WIN32)
if
(ret)
{
std::stringdecodeStr=base64::decode((
const
char
*)ret);
char
*c=
new
char
;
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类就在这个库中。
1
2
3
4
5
6
7
8
9
10
11
12
|
public
static
void
setItem(Stringkey,Stringvalue){
try
{
//加密数据
value=Base64.encodetoString(value.getBytes(),Base64.DEFAULT);
+
"(key,value)values(?,?)"
;
}
catch
(Exceptione){
e.printstacktrace();
}
}
|
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
StringgetItem(Stringkey){
Stringret=null;
try
{
//onlyreturnthefirstvalue
if
(ret!=null){
Log.e(TAG,
"Thekeycontainsmorethanonevalue."
);
break
;
}
ret=c.getString(c.getColumnIndex(
"value"
));
}
c.close();
}
catch
(Exceptione){
e.printstacktrace();
}
//解密数据
if
(ret!=null){
ret=
new
String(Base64.decode(ret,Base64.DEFAULT));
}
return
ret==null?
""
:ret;
}
|
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。