天天看點

POS DES MAC 算法

本文根據《中國銀聯直聯pos終端規範》的闡述,用c語言程式設計實作,該算法在實際的商業pos終端中使用。pos終端采用ECB的加密方式,簡述如下:

a) 将欲發送給pos中心的消息中,從消息類型(mti)到63域之間的部分構成mac 

elemement block (mab)。

b) 對mab,按每8個位元組做異或(不管資訊中的字元格式),如果最後不滿8個位元組,則添加“0x00”。

示例 :

mab = m1 m2 m3 m4

其中: 

m1 = ms11 ms12 ms13 ms14 ms15 ms16 ms17 ms18

m2 = ms21 ms22 ms23 ms24 ms25 ms26 ms27 ms28

m3 = ms31 ms32 ms33 ms34 ms35 ms36 ms37 ms38

m4 = ms41 ms42 ms43 ms44 ms45 ms46 ms47 ms48

按如下規則進行異或運算:

ms11 ms12 ms13 ms14 ms15 ms16 ms17 ms18

xor) ms21 ms22 ms23 ms24 ms25 ms26 ms27 ms28

---------------------------------------------------

temp block1 = tm11 tm12 tm13 tm14 tm15 tm16 tm17 tm18

然後,進行下一步的運算:

tm11 tm12 tm13 tm14 tm15 tm16 tm17 tm18

xor) ms31 ms32 ms33 ms34 ms35 ms36 ms37 ms38

temp block2 = tm21 tm22 tm23 tm24 tm25 tm26 tm27 tm28

再進行下一步的運算:

tm21 tm22 tm23 tm24 tm25 tm26 tm27 tm28

xor) ms41 ms42 ms43 ms44 ms45 ms46 ms47 ms48

result block = tm31 tm32 tm33 tm34 tm35 tm36 tm37 tm38

c) 将異或運算後的最後8個位元組(result block)轉換成16 個hexdecimal:

= tm311 tm312 tm321 tm322 tm331 tm332 tm341 tm342 ||

tm351 tm352 tm361 tm362 tm371 tm372 tm381 tm382

d) 取前8 個位元組用mak加密:

enc block1 = emak(tm311 tm312 tm321 tm322 tm331 tm332 tm341 tm342)

= en11 en12 en13 en14 en15 en16 en17 en18

e) 将加密後的結果與後8 個位元組異或:

en11 en12 en13 en14 en15 en16 en17 en18

xor) tm351 tm352 tm361 tm362 tm371 tm372 tm381 tm382

------------------------------------------------------------

temp block= te11 te12 te13 te14 te15 te16 te17 te18

f) 用異或的結果temp block 再進行一次單倍長密鑰算法運算。

enc block2 = emak(te11 te12 te13 te14 te15 te16 te17 te18)

= en21 en22 en23 en24 en25 en26 en27 en28

g) 将運算後的結果(enc block2)轉換成16 個hexdecimal:

enc block2 = en21 en22 en23 en24 en25 en26 en27 en28

= em211 em212 em221 em222 em231 em232 em241 em242 ||

em251 em252 em261 em262 em271 em272 em281 em282

enc result= %h84, %h56, %hb1, %hcd, %h5a, %h3f, %h84, %h84

轉換成16 個hexdecimal:

“8456b1cd5a3f8484”

h) 取前8個位元組作為mac值。

取”8456b1cd”為mac值。

POS DES MAC 算法

資料封包:  

0x 1234567890abcdefabcdef1234567890   //$body  

mak:2222222222222222  

mac計算:  

m1 = 0x 1234567890abcdef   

m2 = 0x abcdef1234567890  

m1 xor m2 結果: 0x b9f9b96aa4fdb57f  

擴充成16位元組資料:0x 42394639423936414134464442353746  

mak加密前半部分資料結果:0x 9fde90a34cf73b2e  

加密結果與後半部分資料異或,結果:0x deead6e70ec20c68  

mak加密異或結果:0x e267b6e21913d339  

擴充成16位元組資料:0x45323637423645323139313344333339  

mac:e267b6e2  

php mac

POS DES MAC 算法

public function splitdata($hexmacdatasource, $num=16)  

{  

    $len = 0;  

    $modvalue = strlen($hexmacdatasource) % $num;  

    if($modvalue != 0)  

    {  

        $hexsrcdatalen = strlen($hexmacdatasource);  

        $totallen = $hexsrcdatalen + ($num - $modvalue);  

        $hexmacdatasource = str_pad($hexmacdatasource, $totallen, "0");//16進制右補0  

    }  

    $len = strlen($hexmacdatasource) / $num;  

    $ds = array();  

    for ($i = 0; $i < $len; $i++)  

        if (strlen($hexmacdatasource) >= $num)  

        {  

            $ds[] = substr($hexmacdatasource,0, $num);  

            $hexmacdatasource = substr($hexmacdatasource,$num);  

        } else  

            throw new exception("填充的資料非法!",6008);  

        }  

    return $ds;  

}  

public function hexxor($hexstr1 , $hexstr2)  

    return str_pad(strtoupper(gmp_strval(gmp_xor(gmp_init($hexstr1, 16),gmp_init($hexstr2, 16)), 16)),16,'0',str_pad_left);  

public function getbodymac($body)  

    //拆分mac資料源,每組16位hex(8 byte())  

    $ds = $this->splitdata($body);  

    $des = "";  

    for ($i = 0; $i < count($ds); $i++)  

        if ($i == 0)  

            $des = $ds[$i];//$ds[$i] 是16進制數  

            $des = $this->hexxor($des, $ds[$i]);  

    #異或結果擴充成 16位元組 的 hex  

    $hexstr16 = $this->encodehex($des);  

    #加密前8位元組資料  

    $left8  = substr($hexstr16,0,16);  

    $right8 = substr($hexstr16,16,16);  

    $tmpxor = $this->hexxor($this->encryptbydes($left8,$this->mackey), $right8);  

    $bodymac =  substr($this->encryptbydes($tmpxor,$this->mackey),0,8);  

    return $bodymac;  

public function encodehex($str)  

    return strtoupper(bin2hex($str));  

#開始4個位元組封包長度

$requestbodylength = intval(trim(substr($request, 0, 4)));

$body = substr($request, 4, $requestbodylength);

#封包體

$requestbody = substr($body, 0, $requestbodylength - 8);

#最後8個位元組為mac

$requestmac = substr($body, -8);

繼續閱讀