淺析php加密的有關(guān)幾個(gè)函數(shù)及iOS的實(shí)現(xiàn)

最近對(duì)加密比較感興趣,其中有一段加密算法的php的函數(shù),著實(shí)讓我花費(fèi)的了一些時(shí)間才弄明白這個(gè)坑。由此記錄下來(lái),并闡述發(fā)現(xiàn)及解決問題本質(zhì)的一點(diǎn)皮毛,當(dāng)做拋磚引玉。

function hmacsha1($key, $data) {
    $blocksize = 64;
    $hashfunc = 'sha1';

    if (strlen($key) > $blocksize)
        $key = pack('H*', $hashfunc($key));

    $key = str_pad($key, $blocksize, chr(0x00));

    $ipad = str_repeat(chr(0x66), $blocksize);
    $opad = str_repeat(chr(0x55), $blocksize);
    $hmac = pack ('H*',(此處為$key,$ipad,$opad的一些邏輯運(yùn)算))
    //本文假設(shè)為$hmac = pack('H*', $hashfunc($key ^ $ipad.$key^$opad));

   return bin2hex($hmac);
}

科普幾個(gè)php的函數(shù)

pack(format,args) 函數(shù)把數(shù)據(jù)裝入一個(gè)二進(jìn)制字符串

參數(shù) 描述
format 必需。規(guī)定在包裝數(shù)據(jù)時(shí)所使用的格式。
args+ 可選。規(guī)定被包裝的一個(gè)或多個(gè)參數(shù)。

代碼中pack('H*', )是16進(jìn)制打包。(其它參數(shù)類型

example1:

        <?php
            echo pack("C*",80,72,80);
        ?>
        輸出:PHP
C*表示不帶有符號(hào)的字符,此處為10進(jìn)制,80,72,80對(duì)應(yīng)的ASCII碼為PHP
example2:
        <?php
            echo pack("H*",50,48,50);
        ?>
        輸出:PHP
H*表示十六進(jìn)制字符串,此處為16進(jìn)制,0x50 = 80; 0x48 = 72;結(jié)果同上。

bin2hex() 函數(shù)把 ASCII 字符的字符串轉(zhuǎn)換為十六進(jìn)制值。字符串可通過(guò)使用 pack() 函數(shù)再轉(zhuǎn)換回去。unpack() 函數(shù)從二進(jìn)制字符串對(duì)數(shù)據(jù)進(jìn)行解包。

pack()和unpack()是成對(duì)的,pack加密數(shù)據(jù),unpack()解密數(shù)據(jù)。這兩個(gè)功能很強(qiáng)大,但是需要輸入一些格式化的東西。感覺bin2hex()是在unpack()上封裝了一下,使用起來(lái)更方便。

example1:
            <?php
                echo bin2hex("504850");
            ?>
            輸出:PHP
example2:
            <?php
                echo unpack('H*',"504850");
            ?>
            輸出:PHP
        

sha1為hash算法中的sha1加密

strlen($key)求字符串$key的長(zhǎng)度

str_pad() 函數(shù)把字符串填充為新的長(zhǎng)度。

參數(shù) 描述
string 必需。規(guī)定要填充的字符串。
length 必需。規(guī)定新的字符串長(zhǎng)度。如果該值小于字符串的原始長(zhǎng)度,則不進(jìn)行任何操作
pad_string 可選。規(guī)定供填充使用的字符串。默認(rèn)是空白。
pad_type 可選。規(guī)定填充字符串的哪邊。可能的值:STR_PAD_BOTH - 填充字符串的兩側(cè)。如果不是偶數(shù),則右側(cè)獲得額外的填充。STR_PAD_LEFT - 填充字符串的左側(cè)。*STR_PAD_RIGHT - 填充字符串的右側(cè)。默認(rèn)。

str_repeat() 函數(shù)把字符串重復(fù)指定的次數(shù)。

chr()進(jìn)制數(shù)字字符轉(zhuǎn)化ASCII字符
example:
        <?php
            echo str_repeat(chr(0x66), 3);
        ?>
        輸出:fff
        ASCII中0x66--->f

至此上面的php一部分加密的算法應(yīng)該是可以看懂了,開始o(jì)c的實(shí)現(xiàn)

剛剛開始沒有想做太多的優(yōu)化,用面向?qū)ο蟮乃枷雭?lái)直接寫,
具體的實(shí)現(xiàn)部分就不貼代碼了,我直接寫出方法的定義就可以。
實(shí)現(xiàn)思路很簡(jiǎn)單,對(duì)應(yīng)的實(shí)現(xiàn)各個(gè)php中的函數(shù)就可以了.
可以新建一個(gè)Security的類
- (NSString *)pack:(NSString *)str;
- (NSString *)unpack:(NSString *)str;
- (NSString *)hashFunc:(NSString *)str;
- (NSString *)str_pad:(NSString *)str;
- (NSString *)hashfunc:(NSString *)str;
- (NSString *)str_repeat:(NSString *)str1 size:(NSIntger)size;
- (NSString *)hmacsha1:(NSString *)key data:(NSString *)data;
這個(gè)是相應(yīng)的邏輯運(yùn)算,比如同或 異或等等,具體的邏輯運(yùn)算相應(yīng)的計(jì)算。
主要是因?yàn)閛c無(wú)法直接進(jìn)行邏輯運(yùn)算
 example:0x36->6; 0x6b->[;=> 6 ^ [= m;
 php 底層優(yōu)化,6和[為二進(jìn)制數(shù)據(jù)00110110(6)和01011011([)的存儲(chǔ)方式,
 然后進(jìn)行^運(yùn)算    
 01101101
 00110110(6)
 ^
 01011011([)
 ----------------
 01101101(m)
這個(gè)方法里面為了邏輯運(yùn)算會(huì)將字符遍歷獲取char類型,然后計(jì)算
- (NSString *)str1:(NSString *)str1 str2:(NSString *)str2;

基本上實(shí)現(xiàn)上面的方法就可以大功告成了,但是總會(huì)有意向不到的事情。
用以下一個(gè)例子來(lái)說(shuō)明遇到的pack()和unpack()實(shí)現(xiàn)的問題。

php example:
<?php
for($a = 0; $a < 256; $a++) {
    $b = pack('S*', $a);
    $c = unpack('C*', $b);
    echo "pack".$a."=".$b."******unpack".$b."=".$c[1]."\n";
}
oc example:
//這樣會(huì)crash,characterAtIndex越界了,
//是因?yàn)闀?huì)有不可見字符,str可能為nil,而nil轉(zhuǎn)為ASCII碼會(huì)出現(xiàn)問題
    for (int i = 0; i < 256; i++) {
        NSString *str = [NSString stringWithFormat:@"%c", (char)i];
        NSLog(@"pack(%d) = %c,unpack(%c)=%d", i,(char)i, (char)i,[str characterAtIndex:0]);
    }

?>

發(fā)生上面的情況著實(shí)沒有想到,原先以為各個(gè)平臺(tái)的ASCII應(yīng)該會(huì)是完全一樣的,以為ASCII轉(zhuǎn)字符和字符轉(zhuǎn)ASCII是完全一樣的,可以相互轉(zhuǎn)化而沒有任何差異的。但是事實(shí)不是,各個(gè)平臺(tái)有一些差異,比如php這個(gè)當(dāng)為不可見字符是有問號(hào)表示,然后用bin2hex()解碼還能夠轉(zhuǎn)回來(lái),底層的優(yōu)化我認(rèn)為類似指針一樣,存儲(chǔ)的數(shù)據(jù)是沒有變化的?;跀?shù)據(jù)存儲(chǔ)的二進(jìn)制數(shù)據(jù)是沒有變化的,減少不必要的數(shù)據(jù)格式化,設(shè)計(jì)了以下的方法。

- (NSMutableData *)hashFunc:(NSData *)data;
- (NSString *)str_repeat:(NSInteger)size str:(NSString *)str;
//異或函數(shù)
- (NSData *)str1:(NSData *)str1Data str2:(NSData *)str2Data;
- (NSMutableData *)appendData:(NSData *)targetData data:(NSData *)data;
- (NSString *)convertPack:(NSData *)data;
- (NSData *) stringToHexData:(NSString *)hexStr;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容