Cocos2d-x數據加密解密詳解

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

20141118150237902.jpg

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中使用的宏能夠看出這個實如今安卓平臺下是沒法使用的。

20141118140919678.jpg

安卓平臺下的實如今cocos2d-x-2.1.5\extensions\LocalStorage目錄下的LocalStorageAndroid.cpp中。

1419573233692547.jpg

從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;  
}
相關文章
相關標籤/搜索