本方案中采用的PHP擴(kuò)展方式為:
?下載PHP對(duì)應(yīng)版本的源碼趁尼,在其中加入、生成擴(kuò)展(如smsupport.so);
?然后針對(duì)安裝同一版本的PHP(注意眨业,不需要是源碼安裝的,可以通過yum install沮协,apt-get install安裝的)龄捡,將smsupport.so放置到extension_dir中;在php.ini最后一行加入extension = smsupport.so慷暂;
?重啟apached服務(wù)
?此后聘殖,在php文件中直接調(diào)用smsupport.so提供的方法即可晨雳。
注意點(diǎn)
?在進(jìn)行擴(kuò)展及測(cè)試的過程中我們需要設(shè)置PHP的SAFE_MODE為OFF,否則可能無法完成擴(kuò)展或測(cè)試奸腺。SAFE_MODE默認(rèn)為OFF餐禁。
?編譯php擴(kuò)展的環(huán)境和運(yùn)行環(huán)境需要一致!
?建議先使用PHP執(zhí)行腳本突照,此時(shí)提供錯(cuò)誤信息較為豐富帮非。
PHP擴(kuò)展開發(fā)
1.從http://php.net/releases/ php中下載對(duì)應(yīng)目標(biāo)的PHP版本;
2.由于php依賴libxml2-dev讹蘑,為此末盔,首先通過apt-get install libxml2-dev或者yum install libxml2-dev(注libxml2-dev在不同Linux下名稱不同,baidu下)
3.解壓縮1中下載的php包座慰,進(jìn)入目錄陨舱,運(yùn)行./configure完成配置,此時(shí)會(huì)生成編寫extension所需的一些文件
4.進(jìn)入到php源碼中的ext目錄版仔,執(zhí)行./ext_skel --extname=smsupport游盲,其會(huì)自動(dòng)生成一系列目錄及目錄內(nèi)的文件
5.在ext/smsupport目錄中
a)在.c文件中找到const zend_function_entry cqwei_functions[] = {,在其后添加自己定義的函數(shù)
注意:自動(dòng)生成的為c文件蛮粮,由于本擴(kuò)展中要用到cpp益缎,強(qiáng)行將其改為cpp,在編譯時(shí)在后端加上-lstdc++然想,使得編譯成功
PHP_FE(testadd,NULL)/*For testing, remove later. */
PHP_FE(dcsSM2Verify,arg_dcsSM2Verify)
PHP_FE(dcsSM4Decrypt,arg_dcsSM4Decrypt)
注意點(diǎn):
ü將PHP_FE的名稱改成自己的函數(shù)链峭,可以同時(shí)包含多個(gè);
ü如果PHP_FE中包含的函數(shù)需要參數(shù)又沾,則應(yīng)加入?yún)?shù)信息弊仪,如arg_Verify,其中arg_Verify包含4個(gè)參數(shù)杖刷,arg_Decrypt包含2個(gè)參數(shù)励饵。
nZEND_BEGIN_ARG_INFO_EX(arg_Verify,
0, 0, 1)
ZEND_ARG_INFO(0,user)
ZEND_ARG_INFO(0,pubKey)
ZEND_ARG_INFO(0,ticket)
ZEND_ARG_INFO(0,sig)
ZEND_END_ARG_INFO()
nZEND_BEGIN_ARG_INFO_EX(arg_Decrypt,0, 0, 1)
ZEND_ARG_INFO(0,key)
ZEND_ARG_INFO(0,cipher)
ZEND_END_ARG_INFO()
b)PHP_FUNCTION(testadd)在定義自定義函數(shù)testadd的函數(shù)體,如下所示為最簡(jiǎn)單的內(nèi)容
PHP_FUNCTION(testadd)
{
zend_printf("testadd00");
}
c)PHP_FUNCTION(Verify)滑燃,稍微復(fù)雜役听,因?yàn)橛袇?shù)和返回值,示例如下
PHP_FUNCTION(Verify)
{
char * user;
char * pubKey;
char* ticket;
char * sig;
intuserLen,pubKeyLen,ticketLen,sigLen;
charpubKeyArray[64];
if(zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC,"ssss",&user,&userLen,&pubKey,&pubKeyLen,&ticket,&ticketLen,&sig,&sigLen)== FAILURE)
{//解析參數(shù)表窘,參數(shù)為4個(gè)char *典予,s表示char
*,其他格式見下文中的表格
RETURN_FALSE;
return;
}
if(pubKeyLen != 128 || sigLen !=64)
{
zend_printf("the sm2 parameter isincorrect\n");
RETURN_FALSE;
return;
}
CECCPublicKey *verify = new CECCPublicKey();
loadHexStr(pubKey,(unsigned char *)pubKeyArray,64);
if(verify->SetPublicKey((constunsigned char*)pubKeyArray, 64) == 0)
{
zend_printf("the public key isincorrect\n");
delete verify;
RETURN_FALSE;//表示返回false
return;
}
if(verify->VerifyMessage((constunsigned char *)ticket, ticketLen, (const unsigned char *)sig, sigLen, (constchar *)user, userLen) != 1)
{
zend_printf("the signature is incorrect\n");
delete verify;
RETURN_FALSE;
return;
}
delete verify;
RETURN_TRUE;//表示返回true
return;
}
d)char *plain = emalloc(cipherLen);
efree (plain);//動(dòng)態(tài)分配內(nèi)存和釋放
e)返回string變量RETVAL_STRINGL(plain, cipherLen, 1); plain為char *乐严,cipherLen為長(zhǎng)度
f)在.h文件中加入如下內(nèi)容
PHP_FUNCTION(testadd);
PHP_FE(Verify);
PHP_FE(Decrypt);
g)在php源碼/ext/smsupport下編譯:cc -fpic -DCOMPILE_DL_SMSUPPORT=1 -I /usr/local/include -I../ -I../../main -I ../.. -I ../../TSRM -I ../../Zend -c smsupport.cppEllipticCurve.cpp sm3hash.cpp Mpi.cpp SMS4.cpp -lstdc++ -fpermissive-Wwrite-strings
其中除smsupport.cpp外為正常的cpp文件
h)在php源碼/ext/smsupport下鏈接:cc -shared -L /usr/local/lib -rdynamic -o smsupport.so *.o -lstdc++
部署示例
1.在CentOS上搭建php+apache
a)Yum install php
b)Yum install httpd
c)Service httpd start
2.配置php
a)將上述生成的so文件(如smsupport.so)放置到extension_dir目錄中瘤袖,extension_dir路徑可通過echo phpinfo()獲取
b)Find / -name “php.ini”,加入extension
cqwei.so;(在較為靠后的位置加入)
c)Service httpd start
d)在php中直接調(diào)用方法即可
細(xì)節(jié)介紹
?zend_parse_parameters
n如if(zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC,"ssss",&user,&userLen,&pubKey,&pubKeyLen,&ticket,&ticketLen,&sig,&sigLen)== FAILURE)
nZEND_NUM_ARGS()告訴Zend引擎要取得的參數(shù)的信息
nTSRMLS_CC用來確保線程安全
n返回值將被檢查是SUCCESS還是FAILURE昂验。
u通常情況下捂敌,zend_parse_parameters()將返回SUCCESS艾扮;
u然而,如果調(diào)用腳本試圖傳入太多或太少的參數(shù)占婉,或者傳入的參數(shù)不能被轉(zhuǎn)為適當(dāng)?shù)念愋团葑欤琙end會(huì)自動(dòng)輸出一條錯(cuò)誤信息并優(yōu)雅地將控制權(quán)還給調(diào)用腳本
n本例指定s表明此函數(shù)期望只傳入一個(gè)參數(shù),而且該參數(shù)應(yīng)該被轉(zhuǎn)為string數(shù)據(jù)類型并裝入通過地址傳入的char*變量逆济。
n注意酌予,還有一個(gè)int變量通過地址被傳入zend_parse_parameters()。這使Zend引擎提供字符串的字節(jié)長(zhǎng)度奖慌,如此二進(jìn)制安全的函數(shù)不再需要依賴strlen(name)確定字符串的長(zhǎng)度抛虫。實(shí)際上使用strlen(name)甚至得不到正確的結(jié)果,因?yàn)閚ame可能在字符串結(jié)束之前包含一個(gè)或多個(gè)NULL字符升薯。
n再比如if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ld|b", &a,&b, &return_long) == FAILURE) {
u這次你的數(shù)據(jù)類型字符串讀起來像:“我要一個(gè)long(l)莱褒,一個(gè)double(d)”击困。
u下一個(gè)管道字符表示其余的參數(shù)是可選的涎劈。如果函數(shù)調(diào)用時(shí)沒有傳入可選參數(shù),那么zend_parse_parameters()將不會(huì)改變傳給它的對(duì)應(yīng)變量阅茶。
lb是用于Boolean蛛枚。
u數(shù)據(jù)類型字符串后面的是a、b和return_long脸哀,它們按地址傳遞蹦浦,這樣zend_parse_parameters()可以將值裝入它們。
u警告:在32位平臺(tái)中經(jīng)常不加區(qū)分地使用int和long撞蜂,但是盲镶,當(dāng)你的代碼在64位硬件上編譯時(shí),在本該使用一個(gè)的地方使用另一個(gè)是很危險(xiǎn)的蝌诡。所以記住要把long用于整型溉贿,把int用于字符串的長(zhǎng)度。
?表1顯示不同的類型和對(duì)應(yīng)的字母代碼浦旱,以及可用于zend_parse_parameters()的C類型:
類型代碼變量類型
Booleanbzend_bool
Longllong
Doubleddouble
Stringschar*, int
Resourcerzval*
Arrayazval*
Objectozval*
zvalzzval*
n你可能立刻注意到表1中的最后四個(gè)類型都是zval*宇色。待會(huì)兒你將看到,PHP中實(shí)際使用zval數(shù)據(jù)類型存儲(chǔ)所有的用戶空間變量颁湖。三種“復(fù)雜”數(shù)據(jù)類型宣蠕,資源、數(shù)組和對(duì)象甥捺,當(dāng)它們的數(shù)據(jù)類型代碼被用于zend_parse_parameters()時(shí)抢蚀,Zend引擎會(huì)進(jìn)行類型檢查,但是因?yàn)樵贑中沒有與它們對(duì)應(yīng)的數(shù)據(jù)類型镰禾,所以不會(huì)執(zhí)行類型轉(zhuǎn)換思币。
?返回值
n返回值的設(shè)置方法鹿响,網(wǎng)上大多數(shù)是錯(cuò)誤的,可以借鑒ext目錄下其他的擴(kuò)展谷饿。
mcrypt安裝
?首先安裝mcrypt:http://blog.csdn.net/zy112289/article/details/52840062
l先安裝Libmcrypt
#tar -zxvf libmcrypt-2.5.8.tar.gz
#cd libmcrypt-2.5.8
#./configure
#make
#make install說明:libmcript默認(rèn)安裝在/usr/local
l安裝mhash
#tar -zxvf mhash-0.9.9.9.tar.gz
#cd mhash-0.9.9.9
#./configure
#make
#make install
l安裝mcrypt
#tar -zxvf mcrypt-2.6.8.tar.gz
#cd mcrypt-2.6.8
#LD_LIBRARY_PATH=/usr/local/lib ./configure//注意惶我,在一行輸入
#make
#make install
?安裝phpize: yum install php-devel
?編譯、安裝mcrypt
ncd php-5.3.3/ext/mcrypt/
nphpize
n./configure --with-php-config=/usr/bin/php-config
nmake && make install
n提示:Installing shared extensions:/usr/lib64/php/modules/博投,說明安裝成功
n在php.ini中加入extension = mcrypt.so以加入擴(kuò)展绸贡。
?$