• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            #ant

            The dreams in which I'm dying are the best I've ever had...

            MD5算法的C++實(shí)現(xiàn)

            1. Introduction
            MD5算法是一種消息摘要算法(Message Digest Algorithm),此算法以任意長(zhǎng)度的信息(message)作為輸入進(jìn)行計(jì)算,產(chǎn)生一個(gè)128-bit(16-byte)的指紋或報(bào)文摘要(fingerprint or message digest)。兩個(gè)不同的message產(chǎn)生相同message digest的幾率相當(dāng)小,從一個(gè)給定的message digest逆向產(chǎn)生原始message更是困難(不過(guò)據(jù)說(shuō)我國(guó)的某個(gè)教授很善于從message digest構(gòu)造message),因此MD5算法適合用在數(shù)字簽名應(yīng)用中。MD5實(shí)現(xiàn)簡(jiǎn)單,在32位的機(jī)器上運(yùn)行速度也相當(dāng)快,當(dāng)然實(shí)際應(yīng)用也不僅僅局限于數(shù)字簽名。

            2. MD5 Algorithm Description
            假設(shè)輸入信息(input message)的長(zhǎng)度為b(bit),我們想要產(chǎn)生它的報(bào)文摘要,在此處b為任意的非負(fù)整數(shù):b也可能為0,也不一定為8的整數(shù)倍,且可能是任意大的長(zhǎng)度。設(shè)該信息的比特流表示如下:

            ????????? M[0] M[1] M[2] ... M[b-1]

            計(jì)算此信息的報(bào)文摘要需要如下5步:
            2.1 Append Padding Bits
            信息計(jì)算前先要進(jìn)行位補(bǔ)位,設(shè)補(bǔ)位后信息的長(zhǎng)度為L(zhǎng)EN(bit),則LEN%512 = 448(bit),即數(shù)據(jù)擴(kuò)展至
            K*512+448(bit)。即K*64+56(byte),K為整數(shù)。補(bǔ)位操作始終要執(zhí)行,即使補(bǔ)位前信息的長(zhǎng)度對(duì)512求余的結(jié)果是448。具體補(bǔ)位操作:補(bǔ)一個(gè)1,然后補(bǔ)0至滿足上述要求。總共最少要補(bǔ)1bit,最多補(bǔ)512bit。

            2.2 Append Length
            將輸入信息的原始長(zhǎng)度b(bit)表示成一個(gè)64-bit的數(shù)字,把它添加到上一步的結(jié)果后面(在32位的機(jī)器上,這64位將用2個(gè)字來(lái)表示并且低位在前)。當(dāng)遇到b大于2^64這種極少的情況時(shí),b的高位被截去,僅使用b的低64位。經(jīng)過(guò)上面兩步,數(shù)據(jù)就被填補(bǔ)成長(zhǎng)度為512(bit)的倍數(shù)。也就是說(shuō),此時(shí)的數(shù)據(jù)長(zhǎng)度是16個(gè)字(32byte)的整數(shù)倍。此時(shí)的數(shù)據(jù)表示為:

            ????????? M[0 ... N-1]

            其中的N是16的倍數(shù)。

            2.3 Initialize MD Buffer
            用一個(gè)四個(gè)字的緩沖器(A,B,C,D)來(lái)計(jì)算報(bào)文摘要,A,B,C,D分別是32位的寄存器,初始化使用的是十六進(jìn)制表示的數(shù)字,注意低字節(jié)在前:

            ??????? word A: 01 23 45 67
            ??????? word B: 89 ab cd ef
            ??????? word C: fe dc ba 98
            ??????? word D: 76 54 32 10


            2.4 Process Message in 16-Word Blocks
            首先定義4個(gè)輔助函數(shù),每個(gè)函數(shù)的輸入是三個(gè)32位的字,輸出是一個(gè)32位的字:

            ??????? F(X,Y,Z) = XY v not(X) Z
            ??????? G(X,Y,Z) = XZ v Y not(Z)
            ??????? H(X,Y,Z) = X xor Y xor Z
            ??????? I(X,Y,Z) = Y xor (X v not(Z))

            NOTE:not(X)代表X的按位補(bǔ)運(yùn)算,X v Y 表示X和Y的按位或運(yùn)算,X xor Y代表X和Y的按位異或運(yùn)算,XY代表X和Y的按位與運(yùn)算。

            具體過(guò)程如下:
            ?1?/*?Process?each?16-word?block.?*/
            ?2????For?i?=?0?to?N/16-1?do
            ?3?
            ?4??????/*?Copy?block?i?into?X.?*/
            ?5??????For?j?=?0?to?15?do
            ?6????????Set?X[j]?to?M[i*16+j].
            ?7??????end?/*?of?loop?on?j?*/

            ?8?
            ?9??????/*?Save?A?as?AA,?B?as?BB,?C?as?CC,?and?D?as?DD.?*/
            10??????AA?=?A
            11??????BB?=
            ?B
            12??????CC?=
            ?C
            13??????DD?=
            ?D
            14?

            15??????/*?Round?1.?*/
            16??????/*?Let?[abcd?k?s?i]?denote?the?operation
            17???????????a?=?b?+?((a?+?F(b,c,d)?+?X[k]?+?T[i])?<<<?s).?*/

            18??????/*?Do?the?following?16?operations.?*/
            19??????[ABCD??0??7??1]??[DABC??1?12??2]??[CDAB??2?17??3]??[BCDA??3?22??4]
            20??????[ABCD??4??7??5]??[DABC??5?12??6]??[CDAB??6?17??7]??[BCDA??7?22??8
            ]
            21??????[ABCD??8??7??9]??[DABC??9?12?10]??[CDAB?10?17?11]??[BCDA?11?22?12
            ]
            22??????[ABCD?12??7?13]??[DABC?13?12?14]??[CDAB?14?17?15]??[BCDA?15?22?16
            ]
            23?

            24??????/*?Round?2.?*/
            25??????/*?Let?[abcd?k?s?i]?denote?the?operation
            26???????????a?=?b?+?((a?+?G(b,c,d)?+?X[k]?+?T[i])?<<<?s).?*/

            27??????/*?Do?the?following?16?operations.?*/
            28??????[ABCD??1??5?17]??[DABC??6??9?18]??[CDAB?11?14?19]??[BCDA??0?20?20]
            29??????[ABCD??5??5?21]??[DABC?10??9?22]??[CDAB?15?14?23]??[BCDA??4?20?24
            ]
            30??????[ABCD??9??5?25]??[DABC?14??9?26]??[CDAB??3?14?27]??[BCDA??8?20?28
            ]
            31??????[ABCD?13??5?29]??[DABC??2??9?30]??[CDAB??7?14?31]??[BCDA?12?20?32
            ]
            32?

            33??????/*?Round?3.?*/
            34??????/*?Let?[abcd?k?s?t]?denote?the?operation
            35???????????a?=?b?+?((a?+?H(b,c,d)?+?X[k]?+?T[i])?<<<?s).?*/

            36??????/*?Do?the?following?16?operations.?*/
            37??????[ABCD??5??4?33]??[DABC??8?11?34]??[CDAB?11?16?35]??[BCDA?14?23?36]
            38??????[ABCD??1??4?37]??[DABC??4?11?38]??[CDAB??7?16?39]??[BCDA?10?23?40
            ]
            39??????[ABCD?13??4?41]??[DABC??0?11?42]??[CDAB??3?16?43]??[BCDA??6?23?44
            ]
            40??????[ABCD??9??4?45]??[DABC?12?11?46]??[CDAB?15?16?47]??[BCDA??2?23?48
            ]
            41?

            42??????/*?Round?4.?*/
            43??????/*?Let?[abcd?k?s?t]?denote?the?operation
            44???????????a?=?b?+?((a?+?I(b,c,d)?+?X[k]?+?T[i])?<<<?s).?*/

            45??????/*?Do?the?following?16?operations.?*/
            46??????[ABCD??0??6?49]??[DABC??7?10?50]??[CDAB?14?15?51]??[BCDA??5?21?52]
            47??????[ABCD?12??6?53]??[DABC??3?10?54]??[CDAB?10?15?55]??[BCDA??1?21?56
            ]
            48??????[ABCD??8??6?57]??[DABC?15?10?58]??[CDAB??6?15?59]??[BCDA?13?21?60
            ]
            49??????[ABCD??4??6?61]??[DABC?11?10?62]??[CDAB??2?15?63]??[BCDA??9?21?64
            ]
            50?

            51??????/*?Then?perform?the?following?additions.?(That?is?increment?each
            52?
            ????????of?the?four?registers?by?the?value?it?had?before?this?block
            53?????????was?started.)?*/

            54??????A?=?A?+?AA
            55??????B?=?B?+
            ?BB
            56??????C?=?C?+
            ?CC
            57??????D?=?D?+
            ?DD
            58?

            59????end?/*?of?loop?on?i?*/

            2.5 Output
            報(bào)文摘要的產(chǎn)生后的形式為:A,B,C,D。也就是低位字節(jié)A開始,高位字節(jié)D結(jié)束。

            3. C++ Implementation
            有了上面5個(gè)步驟的算法描述,用C++實(shí)現(xiàn)起來(lái)就很直接了。需要注意的是在具體實(shí)現(xiàn)的時(shí)候上述5個(gè)步驟的順序會(huì)有所變動(dòng),因?yàn)樵诖蠖鄶?shù)情況下我們都無(wú)法或很難提前計(jì)算出輸入信息的長(zhǎng)度b(如輸入信息來(lái)自文件或網(wǎng)絡(luò))。因此在具體實(shí)現(xiàn)時(shí)Append Padding BitsAppend Length這兩步會(huì)放在最后面。

            4. Test Suite
            由于實(shí)現(xiàn)代碼比較長(zhǎng),在這里就不貼出來(lái)了,在本文后面會(huì)提供下載。MD5類的public接口如下:
            md5.h
            ?1?class?MD5?{
            ?2?public
            :
            ?3?
            ????MD5();
            ?4?????MD5(const?void*
            input,?size_t?length);
            ?5?????MD5(const?string&
            str);
            ?6?????MD5(ifstream?&
            in);
            ?7?????void?update(const?void*
            input,?size_t?length);
            ?8?????void?update(const?string&
            str);
            ?9?????void?update(ifstream&
            in);
            10?????const?byte*
            ?digest();
            11?
            ????string?toString();
            12?????void
            ?reset();
            13?
            ????...
            14?};

            下面簡(jiǎn)單介紹一下具體用法:
            1.計(jì)算字符串的MD5值
            下面的代碼計(jì)算字符串"abc"的MD5值并用cout輸出:
            1?MD5?md5;
            2?md5.update("abc"
            );
            3?cout?<<?md5.toString()?<<
            ?endl;
            4?//或者更簡(jiǎn)單點(diǎn)

            5?cout?<<?MD5("abc").toString()?<<?endl;

            2.計(jì)算文件的MD5值
            下面的代碼計(jì)算文本文件"D:\test.txt"的MD5值并用cout輸出,如果是二進(jìn)制文件打開的時(shí)候記得要指定ios::binary模式。另外需要注意的是用來(lái)計(jì)算的文件必須存在,所以最好在計(jì)算前先判斷下ifstream的狀態(tài)。
            (本來(lái)判斷ifstream是否有效不該是客戶的責(zé)任,原本想在ifstream無(wú)效時(shí)用文件名做參數(shù)拋出FileNotFoundException之類的異常,后來(lái)卻發(fā)現(xiàn)從ifstream中居然無(wú)法得到文件名...)
            1?MD5?md5;
            2?md5.update(ifstream("D:\\test.txt"
            ));
            3?cout?<<?md5.toString()?<<
            ?endl;
            4?//或者更簡(jiǎn)單點(diǎn)

            5?cout?<<?MD5(ifstream("D:\\test.txt")).toString()?<<?endl;

            3.最基本的用法
            上面的用來(lái)計(jì)算字符串和文件MD5值的接口都是為了方便才提供的,其實(shí)最基本的接口是:
            void update(const void *input, size_t length);
            update的另外兩個(gè)重載都是基于它來(lái)實(shí)現(xiàn)的,下面的代碼用上述接口來(lái)實(shí)現(xiàn)FileDigest函數(shù),該函數(shù)用來(lái)計(jì)算文件的MD5值:
            ?1?string?FileDigest(const?string& file)?{
            ?2?

            ?3?????ifstream?in(file.c_str(),?ios::binary);
            ?4?????if?(!
            in)
            ?5?????????return?""
            ;
            ?6?

            ?7?????MD5?md5;
            ?8?
            ????std::streamsize?length;
            ?9?????char?buffer[1024
            ];
            10?????while?(!
            in.eof())?{
            11?????????in.read(buffer,?1024
            );
            12?????????length?=
            ?in.gcount();
            13?????????if?(length?>?0
            )
            14?
            ????????????md5.update(buffer,?length);
            15?
            ????}
            16?
            ????in.close();
            17?????return
            ?md5.toString();
            18?}

            下面看看測(cè)試代碼:
            test.cpp
            ?1?#include?"md5.h"
            ?2?#include?<iostream>
            ?3?
            ?4?using?namespace?std;
            ?5?

            ?6?void?PrintMD5(const?string& str,?MD5& md5)?{
            ?7?????cout?<<?"MD5(\""?<<?str?<<?"\")?=?"?<<?md5.toString()?<<
            ?endl;
            ?8?
            }
            ?9?

            10?int?main()?{
            11?

            12?????MD5?md5;
            13?????md5.update(""
            );
            14?????PrintMD5(""
            ,?md5);
            15?

            16?????md5.update("a");
            17?????PrintMD5("a"
            ,?md5);
            18?

            19?????md5.update("bc");
            20?????PrintMD5("abc"
            ,?md5);
            21?

            22?????md5.update("defghijklmnopqrstuvwxyz");
            23?????PrintMD5("abcdefghijklmnopqrstuvwxyz"
            ,?md5);
            24?

            25?????md5.reset();
            26?????md5.update("message?digest"
            );
            27?????PrintMD5("message?digest"
            ,?md5);
            28?

            29?????md5.reset();
            30?????md5.update(ifstream("D:\\test.txt"
            ));
            31?????PrintMD5("D:\\test.txt"
            ,?md5);
            32?

            33?????return?0;
            34?}

            測(cè)試結(jié)果:
            MD5("") = d41d8cd98f00b204e9800998ecf8427e
            MD5("a") = 0cc175b9c0f1b6a831c399e269772661
            MD5("abc") = 900150983cd24fb0d6963f7d28e17f72
            MD5("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
            MD5("message digest") = f96b697d7cb7938d525a2f31aaf161d0
            MD5("D:\test.txt") = 7ac66c0f148de9519b8bd264312c4d64


            源代碼下載:點(diǎn)擊下載
            在這里放上Vrcats修改的Qt版本:點(diǎn)擊下載

            posted on 2007-09-11 12:20 螞蟻終結(jié)者 閱讀(57539) 評(píng)論(121)  編輯 收藏 引用 所屬分類: Encrypt

            評(píng)論共2頁(yè): 1 2 

            Feedback

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-10 08:27 SmartPtr

            .NET中產(chǎn)生HashCode用的貌似也是MD5算法???  回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-10 09:56 Ray

            其實(shí)頭文件里的那些define都可以放到cpp里。
            類接口也可以再簡(jiǎn)化一下。  回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-10 11:25 螞蟻終結(jié)者

            @Ray
            Thanks!
            頭文件的define確實(shí)該放在cpp里,是我疏忽了。
            類的接口也正在優(yōu)化...  回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-10 11:45 螞蟻終結(jié)者

            @SmartPtr
            Sorry!我對(duì).Net不太熟悉呵呵  回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-11 00:34 fanofcpp

            不錯(cuò)的說(shuō),希望把優(yōu)化的代碼貼出來(lái)。  回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-11 12:25 螞蟻終結(jié)者

            總算抽出時(shí)間修改了一下接口,只敢說(shuō)比以前的好。實(shí)在想不出比較完美的,要是哪位有好的想法還望告知...
              回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-11 13:27 Minidx全文檢索

            奇怪,怎么跑上面來(lái)了  回復(fù)  更多評(píng)論   

            # Hi,哥們兒 2007-09-11 14:38 VrcatS

            我在做一個(gè)手機(jī)的IM項(xiàng)目,沒(méi)有合適的MD5庫(kù),試了一下你這個(gè),喲,還真管用。于是我就順手給你這庫(kù)寫了一個(gè)Qt的移植,可以直接用在Qt和Qtopia里頭。在GCC4下面測(cè)過(guò)了,回頭等我項(xiàng)目整測(cè)的時(shí)候還會(huì)測(cè)其他平臺(tái)。下載點(diǎn)在這里HTTP://www.vrcats.com/md5.tar.gz
            我的MSN:robot_liuzheng\@hotmail\.com有空交流  回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-11 15:32 螞蟻終結(jié)者

            @VrcatS
            有意思,thanks!
              回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-12 23:46 ornaking

            呵呵~~~還是受不了了~~~
            辭職了~~~
            看了你的帖子~~~好強(qiáng)啊~~~
            以后多過(guò)來(lái)學(xué)習(xí)學(xué)習(xí)哈~~~  回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-13 08:27 螞蟻終結(jié)者

            @ornaking
            呵呵,共同學(xué)習(xí)  回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-14 22:04 abc

            代碼在VC++ 2005上鏈接是發(fā)生錯(cuò)誤!
            錯(cuò)誤 1 error LNK2019: 無(wú)法解析的外部符號(hào) "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall MD5::toString(void)" (?toString@MD5@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ),該符號(hào)在函數(shù) "void __cdecl PrintMD5(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class MD5 &)" (?PrintMD5@@YAXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAVMD5@@@Z) 中被引用 test.obj
            錯(cuò)誤 2 error LNK2019: 無(wú)法解析的外部符號(hào) "public: void __thiscall MD5::update(void const *,unsigned int)" (?update@MD5@@QAEXPBXI@Z),該符號(hào)在函數(shù) "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl FileDigest(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?FileDigest@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV12@@Z) 中被引用 test.obj
            錯(cuò)誤 3 error LNK2019: 無(wú)法解析的外部符號(hào) "public: __thiscall MD5::MD5(void)" (??0MD5@@QAE@XZ),該符號(hào)在函數(shù) "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl FileDigest(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?FileDigest@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABV12@@Z) 中被引用 test.obj
            錯(cuò)誤 4 error LNK2019: 無(wú)法解析的外部符號(hào) "public: void __thiscall MD5::update(class std::basic_ifstream<char,struct std::char_traits<char> > &)" (?update@MD5@@QAEXAAV?$basic_ifstream@DU?$char_traits@D@std@@@std@@@Z),該符號(hào)在函數(shù) _main 中被引用 test.obj
            錯(cuò)誤 5 error LNK2019: 無(wú)法解析的外部符號(hào) "public: void __thiscall MD5::reset(void)" (?reset@MD5@@QAEXXZ),該符號(hào)在函數(shù) _main 中被引用 test.obj
            錯(cuò)誤 6 error LNK2019: 無(wú)法解析的外部符號(hào) "public: void __thiscall MD5::update(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?update@MD5@@QAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z),該符號(hào)在函數(shù) _main 中被引用 test.obj
            錯(cuò)誤 7 error LNK2019: 無(wú)法解析的外部符號(hào) "public: __thiscall MD5::MD5(class std::basic_ifstream<char,struct std::char_traits<char> > &)" (??0MD5@@QAE@AAV?$basic_ifstream@DU?$char_traits@D@std@@@std@@@Z),該符號(hào)在函數(shù) _main 中被引用 test.obj
            錯(cuò)誤 8 error LNK2019: 無(wú)法解析的外部符號(hào) "public: __thiscall MD5::MD5(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??0MD5@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z),該符號(hào)在函數(shù) _main 中被引用 test.obj
            錯(cuò)誤 9 fatal error LNK1120: 8 個(gè)無(wú)法解析的外部命令 C:\Documents and Settings\1\桌面\程設(shè)大賽\1003\Debug\1003.exe
              回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-15 09:52 螞蟻終結(jié)者

            @abc
            我最早就是在VC++ 2005上寫的代碼,在GCC上也測(cè)試過(guò)。
            有可能你沒(méi)有把md5.cpp加入工程,如果只用md5.h和test.cpp進(jìn)行編譯就會(huì)出現(xiàn)上面的8個(gè)error。
              回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-15 14:19 abc

            呵呵,這怎么可能沒(méi)加?
            今天重新生成了一遍莫名其妙地又好了……
            感謝您的代碼,我要急用所以沒(méi)時(shí)間再研究md5算法,直接用您的代碼構(gòu)建程序后提交答案。  回復(fù)  更多評(píng)論   

            # re: MD5算法的C++實(shí)現(xiàn) 2007-09-15 18:41 螞蟻終結(jié)者

            @abc
            沒(méi)問(wèn)題就好。“您”字看得我好怪...  回復(fù)  更多評(píng)論   

            評(píng)論共2頁(yè): 1 2 
            久久99毛片免费观看不卡| 国产91久久综合| 一级a性色生活片久久无| 久久久久国产| AAA级久久久精品无码区| 亚洲国产精品一区二区久久| 曰曰摸天天摸人人看久久久| 久久综合狠狠综合久久激情 | 久久综合久久久| 国产精品无码久久综合网| 久久精品女人天堂AV麻| 亚洲精品WWW久久久久久| 久久人人青草97香蕉| 中文字幕乱码人妻无码久久| 伊人久久大香线蕉AV色婷婷色| 中文国产成人精品久久不卡| 人妻少妇久久中文字幕| 国产一级做a爰片久久毛片| 丰满少妇人妻久久久久久| 久久综合丁香激情久久| 国产精品成人精品久久久 | 久久WWW免费人成一看片| 精品国产乱码久久久久久呢| 久久久国产精品亚洲一区 | 久久精品成人国产午夜| 精品国产青草久久久久福利| 亚洲精品tv久久久久| 久久天堂AV综合合色蜜桃网 | 久久精品成人免费国产片小草| 亚洲精品97久久中文字幕无码| 亚洲AV无码久久精品成人| 女人香蕉久久**毛片精品| 亚洲中文字幕伊人久久无码 | 亚洲午夜久久影院| 老男人久久青草av高清| 久久99国产精品久久| 伊人 久久 精品| 国产精品久久影院| 久久久久久精品免费看SSS| 精品久久久久久久久中文字幕| 亚洲国产精品综合久久网络|