加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Cocos2d-x数据加密解密详解

发布时间:2020-12-14 19:57:20 所属栏目:百科 来源:网络整理
导读: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

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
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);
std::stringstr() const ;
};
/*
*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;
system ( "pause" );
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));
System.out.println( "src" +src);
System.out.println( "encode" +encode);
System.out.println( "decode" +decode);
}
}


数据库数据项加密

Cocos2d-x中操作数据库的实现都封装在LocalStorage这个类中。使用的是sqlite3。


iOS、Win32平台的加密

1.base64.h和base64.cpp添加项目Classes目录下。

2.右键libExtensions项目附加包含目录把base64库所在目录添加到包含目录中具体路径根据自己项目结构而定

20141118150237902.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)
//CCLOG("key=%ssrc=%s",key,value);
std::stringencodeStr=base64::encode(value);
value=encodeStr.c_str();
//CCLOG("key=%sencode=%s",value);
#endif
int ok=sqlite3_bind_text(_stmt_update,1,-1,SQLITE_TRANSIENT);
ok|=sqlite3_bind_text(_stmt_update,2,value,SQLITE_TRANSIENT);
ok|=sqlite3_step(_stmt_update);
ok|=sqlite3_reset(_stmt_update);
if (ok!=SQLITE_OK&&ok!=SQLITE_DONE)
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);
int ok=sqlite3_reset(_stmt_select);
ok|=sqlite3_bind_text(_stmt_select,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 ( "ErrorinlocalStorage.getItem()n" );
//加密数据
# if (CC_TARGET_PLATFORM!=CC_PLATFORM_WIN32)
//CCLOG("decodesrc=%s",ret);
if (ret)
{
std::stringdecodeStr=base64::decode(( const char *)ret);
char *c= new char ;
strcpy_s(c,decodeStr.size()+1,decodeStr.c_str());
//CCLOG("key=%sdecode=%s",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中使用的宏可以看出这个实现在安卓平台下是无法使用的。

20141118140919678.jpg

安卓平台下的实现在cocos2d-x-2.1.5extensionsLocalStorage目录下的LocalStorageAndroid.cpp中。

1419573233692547.jpg

从localStrorageInit的实现可以看出它是通过jni调用了java层中org/cocos2dx/lib/Cocos2dxLocalStorage的静态方法init。

在打包安卓版Cocos2d-x游戏时需要用到引擎的一个java库在cocos2d-x-2.1.5cocos2dxplatformandroidjava目录下Cocos2dxLocalStorage类就在这个库中。


修改这个类的setItem方法在保存数据的时候加密

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);
Stringsql= "replaceinto" +TABLE_NAME
+ "(key,value)values(?,?)" ;
mDatabase.execSQL(sql, new Object[]{key,value});
} catch (Exceptione){
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 StringgetItem(Stringkey){
Stringret=null;
try {
Stringsql= "selectvaluefrom" +TABLE_NAME+ "wherekey=?" ;
Cursorc=mDatabase.rawQuery(sql, new String[]{key});
while (c.moveToNext()){
//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;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读