Qt plugin 加密的sqlite(sqlcipher)

sqlite所儲存的資料可以直接用記事本打開看裡面的資料
在資安上面不太安全
所以我在網路上找了加密的方法
也就是sqlcipher
他試建立在sqlite上的open source
不過要取的他的windows dll 需要錢
而且不知道跟qt有沒有相容
所以要自行編譯
  • 所需要的工具:
MinGW、MSYS、QT的windows的source code、sqlcipher、Open SSL、Tcl/Tk

  • MinGW:(C/C++編譯器)
在安裝QT SDK的時候通常都會一起安裝 ,除非你是安裝VS2008或是VS2010版本的編譯器

下載點:http://sourceforge.net/projects/mingw/
找到mingw-get-inst-XXXXXX.exe的下載
開啟後會自動到網路上下載安裝
MSYS也可以選擇下載
不過以上下載失敗機率很大
所以最簡單的方法就是去載QT SDK Online installer
選擇下載MinGW就好
  • MSYS:(在Windows上模擬Linux工具)
下載點:http://sourceforge.net/projects/mingw/files/MSYS/Base/msys-core/msys-1.0.11/MSYS-1.0.11.exe/download
下載後安裝會顯示出視窗
 就輸入y
安裝MSYS請先一定要先安裝MinGW
所以就輸入y
接下來就輸入mingw存放的路徑
因為我是用QtSDK的mingw所以就只定他
這裡是說要不要幫你設定mingw的檔案配置
之後也會需要修改/etc/fatab的設定
這裡就y就好

到這裡就安裝結束
到桌面開啟Msys就可以啟動Linux的模式
MSYS基本認知
 開啟後他所有的檔案都是在
 C:\msys\1.0為根路徑
所以在裡面新增資料夾或是其他程式在MSYS就可以看見
新增MSYS的其他掛載區域
開啟C:\msys\1.0\etc\fstab
沒有就自己創
假設你想要讀取C槽下面的資料
就輸入
C:/         /c
如下圖

這樣開啟MSYS就可以輸入cd /c 就可以讀取到c槽的東西
  • Qt的windows的source code:
並非QtSDK上的Desktop
因為上面沒有source code所以沒有辦法編譯額外plugin上去
下載點:http://qt.nokia.com/downloads/windows-cpp
安裝後就library會有src的這個資料夾也就是原始檔


  • Tcl/Tk:
是因為編譯sqlcipher會需要用到的tool
不過他是原始檔所以要自行編譯加入
下載點:http://prdownloads.sourceforge.net/tcl/tcl8.5.11-src.tar.gz
將檔案放到C:\msys\1.0\home\matttt
或是開啟MSYS
輸入
wget http://prdownloads.sourceforge.net/tcl/tcl8.5.11-src.tar.gz 
也可以
開啟MSYS
就解壓縮檔案
tar xvf tcl8.5.11-src.tar.gz
解壓縮完後就進入資料夾
並且下command開始編譯
注意mingw需要確定在MSYS系統下的哪裡
我是在/mingw裡

cd /home/matttt/tcl8.5.11
./configure --prefix=/mingw
make
make install 
接下來要改檔名
在mingw裡的bin
因為他安裝生成的檔名為tclsh85.exe
所以要改成tclsh.exe
要不然會後面會有問題

  • Open SSL:
因為要加密所以需要有加解密的程式碼
所以就去取得open source的Open SSL
下載點: http://slproweb.com/products/Win32OpenSSL.html
找到Win32 OpenSSL v1.0.1b
下載後安裝完就可以了
  •  sqlcipher
建立在sqlite上的open source可以加解密
下載點:https://github.com/sqlcipher/sqlcipher/zipball/v2.0.3
解壓縮到C槽下面
開始編譯
首先要先確定MSYS的fstab上有加上
qt的source code的位置
mingw的位置
sqlcipher的位置


C:\Qt\4.8.1\src\plugins\sqldrivers
下新增sqlcipher資料夾
接下來切換到source code的sqlcipher的資料夾下
設定並且編譯
cd /c/sqlcipher
./configure –prefix=/qt/src/plugins/sqldrivers/sqlcipher –disable-tcl –disable-amalgamation
CFLAGS="-DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -I/c/OpenSSL/include /c/Windows/System32/libeay32.dll -L/c/OpenSSL/lib/MinGW" LDFLAGS="-leay32"
make
make dll
make install
cp /c/OpenSSL/lib/MinGW/libeay32.a /qt/src/plugins/sqldrivers/sqlcipher/lib/
接下來在
C:\Qt\4.8.1\src\plugins\sqldrivers\sqlcipher
新增兩個檔案並輸入以下內容
sqlcipher.pro內容
TARGET   = qsqlcipher
HEADERS  = ../../../sql/drivers/sqlite/qsql_sqlite.h
SOURCES  = smain.cpp \
           ../../../sql/drivers/sqlite/qsql_sqlite.cpp
!system-sqlite:!contains( LIBS, .*sqlite.* ) {
    CONFIG(release, debug|release):DEFINES *= NDEBUG
    DEFINES     += SQLITE_OMIT_LOAD_EXTENSION SQLITE_OMIT_COMPLETE  SQLITE_HAS_CODEC
    INCLUDEPATH += include
    LIBS        += ./lib/libsqlite3.a ./lib/libeay32.a -Ic:/OpenSSL-Win32/include c:/Windows/System32/libeay32.dll
} else {
    LIBS *= $$QT_LFLAGS_SQLITE
    QMAKE_CXXFLAGS *= $$QT_CFLAGS_SQLITE
}
include(../qsqldriverbase.pri)

smain.cpp內容
#include <qsqldriverplugin.h>
#include <qstringlist.h> 
#include "../../../../src/sql/drivers/sqlite/qsql_sqlite.h"   
QT_BEGIN_NAMESPACE
class QSQLCipherDriverPlugin : public QSqlDriverPlugin
{
public:
    QSQLCipherDriverPlugin();
    QSqlDriver* create(const QString &);
    QStringList keys() const;
};
QSQLCipherDriverPlugin::QSQLCipherDriverPlugin()
    : QSqlDriverPlugin()
{
}

QSqlDriver* QSQLCipherDriverPlugin::create(const QString &name)
{
    if (name == QLatin1String("QSQLCIPHER")) {
        QSQLiteDriver* driver = new QSQLiteDriver();
        return driver;
    }
    return 0;
}

QStringList QSQLCipherDriverPlugin::keys() const
{
    QStringList l;
    l  << QLatin1String("QSQLCIPHER");
    return l;
}

Q_EXPORT_STATIC_PLUGIN(QSQLCipherDriverPlugin)
Q_EXPORT_PLUGIN2(qsqlite, QSQLCipherDriverPlugin)

QT_END_NAMESPACE



接下來就是用MSYS到
plugin下開始編譯
注意要用你安裝的source code的qmake而不是Qt SDK的qmake
cd /c/Qt/4.8.1/src/plugins/sqldrivers/sqlcipher
/c/Qt/4.8.1/bin/qmake
make
make install
這樣就完成編譯和設置了

將此Qt的source code加入Qt Creator的設定中
Tool→options...→Qt4→add
加入c:\Qt\4.8.1\qmake.exe
開啟一個新的Qt porject
加入
qDebug() << QSqlDatabase::drivers();
在project加上Qt4.8.1的debug編譯方式
最後用Qt4.8.1的debug編譯後執行
看有沒有QSQLCIPHER有就成功

使用方式

QSqlQuery query;
後面加上
query.exec("PRAGMA key = 'secretkey';");
secretkey是你想要設的key

embedded linux qt 支援 jpeg (static)

[尚未編譯]
1.準備QT source
2.準備libjpeg (http://www.ijg.org)
3.編譯libjpeg
4.configure QT 將 -qt-libjpeg 、 -I (include)和 -L(library)額外設定好
5.make install

[編譯完成]
1.尋找你install資料夾下plugins/imageformats是否有libqjpeg.so
2.將imageformats整個複製到embedded下的/lib/plugins
3.將libjpeg的so檔複製到複製到embedded下的/lib
4.設定環境變數 export QT_PLUGIN_PATH=/lib
5.將成試放入執行即可

[偵錯]
1.設定環境變數export QT_DEBUG_PLUGINS=1
2.執行程式
3.執行到jpeg的地方就會顯示有沒有載入成功

編譯出來的hex燒入後無反應

編譯出來的hex燒入後無反應
需要將底下的
C:\Texas Instruments\ZStack-CC2530-2.4.0\Projects\zstack\Tools\CC2530DB\f8w2530.xcl
修改到hex生成模式
找到下列這幾行
// Include these two lines when generating a .hex file for banked code model:
//-M(CODE)[(_CODEBANK_START+_FIRST_BANK_ADDR)-(_CODEBANK_END+_FIRST_BANK_ADDR)]*\
//_NR_OF_BANKS+_FIRST_BANK_ADDR=0x8000
將前面的註解去掉
// Include these two lines when generating a .hex file for banked code model:
-M(CODE)[(_CODEBANK_START+_FIRST_BANK_ADDR)-(_CODEBANK_END+_FIRST_BANK_ADDR)]*\
_NR_OF_BANKS+_FIRST_BANK_ADDR=0x8000
在重新編譯所生成的檔案就可以燒入並且會動
但是要是編成可以直接燒入執行的模式
會出現一個warring就是開啟這個所出現的
但不會有問題

z-stack cc2530 SPI code

z-stack cc2530 SPI code:
/*******************************************************
 *                 INCLUDES
 *******************************************************/
#include "hal_types.h"
#include "hal_spi.h"
#include "OSAL.h"
#include "OnBoard.h"
#include "hal_assert.h"

/******************************************************
 *                     CONSTANTS
 ******************************************************/
/*
  //control軟體控制
  P1.4 - CS
  //spi硬體控制
  P1.5 - CLK
  P1.6 - MOSI
  P1.7 - MISO
*/

#define HAL_SPI_CS_PORT 1
#define HAL_SPI_CS_PIN  4
#define HAL_SPI_CLK_PORT 1
#define HAL_SPI_CLK_PIN  5
#define HAL_SPI_MOSI_PORT 1
#define HAL_SPI_MOSI_PIN  6
#define HAL_SPI_MISO_PORT 1
#define HAL_SPI_MISO_PIN  7

/**************************************************

 *                       MACROS

 **************************************************/
#define HAL_IO_SET(port, pin, val)        HAL_IO_SET_PREP(port, pin, val)
#define HAL_IO_SET_PREP(port, pin, val)   st( P##port##_##pin## = val; )
#define HAL_CONFIG_IO_OUTPUT(port, pin, val)      HAL_CONFIG_IO_OUTPUT_PREP(port, pin, val)
#define HAL_CONFIG_IO_OUTPUT_PREP(port, pin, val) st( P##port##SEL &= ~BV(pin); \
                                                      P##port##_##pin## = val; \
                                                      P##port##DIR |= BV(pin); )
#define HAL_CONFIG_IO_PERIPHERAL(port, pin)      HAL_CONFIG_IO_PERIPHERAL_PREP(port, pin)
#define HAL_CONFIG_IO_PERIPHERAL_PREP(port, pin) st( P##port##SEL |= BV(pin); )
/*******************************************************
 *                   FUNCTIONS - API
 *******************************************************/

void HalSpi_HW_Init(void);

void HalSpiInit(void)
{
  HalSpi_HW_Init();
}

static void halSpi_ConfigSPI(void)
{
   uint8 baud_exponent;
   uint8 baud_mantissa;

  PERCFG |= 0x02;
  //設定硬體控制腳位
  HAL_CONFIG_IO_PERIPHERAL(HAL_SPI_CLK_PORT,  HAL_SPI_CLK_PIN);
  HAL_CONFIG_IO_PERIPHERAL(HAL_SPI_MOSI_PORT, HAL_SPI_MOSI_PIN);
  HAL_CONFIG_IO_PERIPHERAL(HAL_SPI_MISO_PORT, HAL_SPI_MISO_PIN);
  //設定傳輸速度
  baud_exponent = 10;
  baud_mantissa =  0;

  /* Configure SPI */
  U1UCR  = 0x80;
  U1CSR  = 0x00;
  //U1GCR  = HAL_SPI_TRANSFER_MSB_FIRST | HAL_SPI_CLOCK_PHA_0 | HAL_SPI_CLOCK_POL_LO | baud_exponent;//正緣觸發,正緣接收資料
  U1GCR  = HAL_SPI_TRANSFER_MSB_FIRST | 0x40 | HAL_SPI_CLOCK_POL_LO | baud_exponent;//正緣觸發,負緣接收資料
  U1BAUD = baud_mantissa;
}

void HalSpi_HW_Init(void)
{
  //設定基本output模式
  HAL_CONFIG_IO_OUTPUT(HAL_SPI_CS_PORT,    HAL_SPI_CS_PIN,    1);
  halSpi_ConfigSPI();
}

static void spi_tx(uint8 x)
{
  U1CSR &= ~((1<<2) | (1<<1));
  U1DBUF = x;
  while( !(U1CSR & (1<<1)) );
}

void HalSpi_Ad7763_Read(uint8 addr, uint8 *recv_data)
{
    //將CS腳位到LOW
    HAL_IO_SET(HAL_SPI_CS_PORT, HAL_SPI_CS_PIN, 0);  //begin
    addr &= 0x3f;//ADE7765讀取 8bit→0 7bit→0
    spi_tx(addr);//傳送
    spi_tx(0);
    *recv_data = U1DBUF;//接收
    spi_tx(0);
    *(recv_data+1) = U1DBUF;
    spi_tx(0);
    *(recv_data+2) = U1DBUF;
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    //將CS腳位到HIGH
    HAL_IO_SET(HAL_SPI_CS_PORT, HAL_SPI_CS_PIN, 1);  //end
}

void HalSpi_Ad7763_Write(uint8 addr, uint16 send_data)
{
    //將CS腳位到LOW
    HAL_IO_SET(HAL_SPI_CS_PORT, HAL_SPI_CS_PIN, 0);  //begin
    addr |= 0x80;//ADE7765寫入 8bit→1 7bit→0
    spi_tx(addr);
    spi_tx((send_data&0xff00)>>8);
    spi_tx(send_data&0x00ff);
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    //將CS腳位到HIGH
    HAL_IO_SET(HAL_SPI_CS_PORT, HAL_SPI_CS_PIN, 1);  //end
}

使用z-stack內部function且return處理

使用z-stack內部function
例如:
ZDP_NwkAddrReq()
ZDP_IEEEAddrReq()
等等....
使用方法請查看Z-Stack API.pdf
發送端送出指令給各個device
假設有device回應會在以下函數做處理並且return (並非所有函數都會預設啟動)
ZDP_NWKAddrRsp() 
ZDP_IEEEAddrRsp()
等等....

這時候發送端會接收到return的值
這時候就要做register
在你的
void SampleApp_Init( uint8 task_id )
裡面加上
ZDO_RegisterForZDOMsg(SampleApp_TaskID, NWK_addr_rsp);
NWK_addr_rsp在Z-Stack API.pdf裡面的文件有寫到對應的function
例如:
ZDP_NWKAddrRsp()→NWK_addr_rsp
ZDP_IEEEAddrRsp()→IEEE_addr_rsp 
接下來就要處理接收後的值
也就是在
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
加上而外的判斷事件

switch ( MSGpkt->hdr.event )
裡面額外加上
case ZDO_CB_MSG:
例如:
if ( events & SYS_EVENT_MSG ) {
  MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
  while ( MSGpkt ) {
    switch ( MSGpkt->hdr.event ) {  
    case AF_INCOMING_MSG_CMD:
      SampleApp_MessageMSGCB( MSGpkt );
      break;
    case ZDO_CB_MSG:
      zdoapp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
      break; 
    default:
      break;
    }
    osal_msg_deallocate( (uint8 *)MSGpkt );
    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
  }  
  return (events ^ SYS_EVENT_MSG);
}

接下來就在副程式
zdoapp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt )
去解析收到的值
例如:解析NWK_addr_rsp
void zdoapp_ProcessZDOMsgs(zdoIncomingMsg_t *inMsg )
{
  ZDO_NwkIEEEAddrResp_t *pAddrRsp;
  switch ( inMsg->clusterID ) {
  case NWK_addr_rsp:
    pAddrRsp = ZDO_ParseAddrRsp( inMsg );
    if ( pAddrRsp ) {
      if ( pAddrRsp->status == ZSuccess ) {
        pAddrRsp->nwkAddr;//short address
        pAddrRsp->extAddr;//MAC address
      }
      osal_mem_free( pAddrRsp );
    }
    break;
  }
}
要看如何解析的話請到
ZDProfile.c
因為要看他如何編譯就可以解析