TLS 1.3科普——新特性与协议实现
上海交通大學(xué)密碼與計(jì)算機(jī)安全實(shí)驗(yàn)室(LoCCS)軟件安全小組(GoSSIP)版權(quán)所有,轉(zhuǎn)載請(qǐng)與作者取得聯(lián)系!
在今年的GoSSIP軟件安全小組面向全國(guó)優(yōu)秀的本科同學(xué)開(kāi)放的暑期實(shí)習(xí)中,來(lái)自上海交通大學(xué)的胡嘉尚同學(xué)深入研究了SSL/TLS協(xié)議,并撰寫(xiě)了這篇TLS 1.3的科普文章,希望能夠幫助國(guó)內(nèi)的安全研究人員和企業(yè)開(kāi)發(fā)人員更加深入地理解和部署TLS 1.3協(xié)議。
======================================================================
時(shí)隔九年之后的新升級(jí),TLS 1.3備受關(guān)注。針對(duì)目前已知的漏洞和安全威脅,IETF小組對(duì)TLS協(xié)議進(jìn)行了一次大的更新,從2014年4月,第0份TLS 1.3草案公開(kāi),到2017年7月第21份草案發(fā)布,TLS 1.3的編寫(xiě)工作已經(jīng)進(jìn)入尾聲,跨時(shí)3年的編寫(xiě),讓該協(xié)議成為有史以來(lái)最安全、也是最復(fù)雜的TLS協(xié)議。
正式的RFC雖然尚未發(fā)布,TLS 1.3已經(jīng)開(kāi)始被國(guó)內(nèi)外一些網(wǎng)站使用,Chrome、Firefox、OpenSSL、Nginx等均提供了相應(yīng)支持,TLS 1.3已經(jīng)悄然進(jìn)入我們的生活。借著這篇文章先來(lái)了解一下吧~
Part 1-簡(jiǎn)介
20年——從開(kāi)始到現(xiàn)在
對(duì)于安全加密通信,傳輸層安全協(xié)議(SSL/TLS)的重要性不言而喻。?
起初,網(wǎng)景公司針對(duì)傳輸層協(xié)議(TCP/UDP)并沒(méi)有對(duì)傳輸?shù)臄?shù)據(jù)進(jìn)行加密保護(hù)的缺陷,為自家瀏覽器設(shè)計(jì)了SSL協(xié)議,于1995年公開(kāi)協(xié)議的2.0版本。1999年,IETF小組基于SSL 3.0設(shè)計(jì)了與SSL協(xié)議獨(dú)立的TLS 1.0協(xié)議,正式成為互聯(lián)網(wǎng)傳輸層加密的標(biāo)準(zhǔn)。此后,TLS協(xié)議于2006年、2008年再次經(jīng)歷更新,分別命名為T(mén)LS 1.1和TLS 1.2。?
如今的TLS協(xié)議不僅被用于傳輸層通訊,更作為一個(gè)標(biāo)準(zhǔn)的加密保護(hù)協(xié)議被廣泛應(yīng)用于 FTP, 電子郵件和VPN等領(lǐng)域,時(shí)刻保護(hù)著我們網(wǎng)絡(luò)通信的安全。
當(dāng)前的TLS協(xié)議存在問(wèn)題
老版本的SSL協(xié)議被公認(rèn)在完整性校驗(yàn)、密鑰協(xié)商過(guò)程中有重大缺陷,因此,2011年與2015年IETF小組相繼聲明禁止使用SSL?2.0、3.0。?
TLS協(xié)議針對(duì)此前披露的漏洞做了相應(yīng)的處理,但是因?yàn)槠鋸?fù)雜性,還沒(méi)有一個(gè)版本能真正保證絕對(duì)的安全。?
目前最新版本的TLS 1.2發(fā)布距今已有九年時(shí)間,在此期間,許多SSL/TLS協(xié)議的新漏洞被發(fā)現(xiàn),比如針對(duì)其壓縮機(jī)制的CRIME漏洞,針對(duì)CBC塊加密模式的BEAST漏洞(主要是針對(duì)SSL 3.0和TLS 1.0),早已不再是當(dāng)初設(shè)計(jì)者認(rèn)為的那么安全,人們迫切需要新的協(xié)議將其代替。
TLS1.3與之前的協(xié)議有較大差異
SSL/TLS協(xié)議為網(wǎng)絡(luò)通信提供了以下兩種功能:
上述功能在以往的TLS協(xié)議中是這樣實(shí)現(xiàn)的:
- 加密:使用對(duì)稱加密算法(塊加密、流加密)加密會(huì)話數(shù)據(jù),密鑰交換主要通過(guò)非對(duì)稱算法加密會(huì)話過(guò)程中使用的對(duì)稱密鑰傳遞給對(duì)方來(lái)實(shí)現(xiàn)(RSA)。從TLS 1.0起引入了DH密鑰交換算法作為另一種可選的密鑰交換算法。
- 完整性校驗(yàn):使用MAC對(duì)發(fā)送的報(bào)文進(jìn)行完整性校驗(yàn)計(jì)算,先計(jì)算MAC再加密。在TLS 1.2中引入了更具有安全性的AEAD算法(同時(shí)完成加密和完整性校驗(yàn))作為一個(gè)加密機(jī)制的備選選項(xiàng) 。
- 身份認(rèn)證:所有的身份認(rèn)證都基于證書(shū)公鑰體系完成。
因?yàn)镽SA密鑰交換過(guò)程安全性完全依賴于服務(wù)器私鑰的安全性,TLS 1.3徹底廢棄了RSA密鑰交換算法。?
因?yàn)橄扔?jì)算MAC再加密的方法存在相當(dāng)?shù)陌踩毕?#xff0c;TLS 1.3廢棄了使用MAC的塊加密和流加密機(jī)制,僅采用AEAD類對(duì)稱加密算法作為唯一的加密選項(xiàng)。?
此外,TLS 1.3引入了一種新的密鑰協(xié)商機(jī)制——PSK。
其他新協(xié)議大的改變還包括:?
- 支持0-RTT數(shù)據(jù)傳輸?
- 廢棄了3DES、RC4、AES-CBC等加密組件。廢棄了SHA1、MD5等哈希算法。?
- 不再允許對(duì)加密報(bào)文進(jìn)行壓縮、不再允許雙方發(fā)起重協(xié)商,密鑰的改變不再需要發(fā)送change_cipher_spec報(bào)文給對(duì)方。?
- 握手階段的報(bào)文可見(jiàn)明文大大減少。
對(duì)比以往的協(xié)議RFC中不足一頁(yè)的Major Differences from Previous。TLS 1.3確實(shí)可以稱得上是向前的一大步。
TLS 1.3包括3個(gè)子協(xié)議——alert、handshake、record
handshake協(xié)議負(fù)責(zé)協(xié)商使用的TLS版本、加密算法、哈希算法、密鑰材料和其他與通信過(guò)程有關(guān)的信息,對(duì)服務(wù)器進(jìn)行身份認(rèn)證,對(duì)客戶端進(jìn)行可選的身份認(rèn)證,最后對(duì)整個(gè)握手階段信息進(jìn)行完整性校驗(yàn)以防范中間人攻擊,是整個(gè)TLS協(xié)議的核心。?
record協(xié)議負(fù)責(zé)對(duì)接收到的報(bào)文進(jìn)行加密解密,將其分片為合適的長(zhǎng)度后轉(zhuǎn)發(fā)給其他協(xié)議層。?
alert協(xié)議負(fù)責(zé)處理消息傳輸與握手階段中的異常情況。?
此前的協(xié)議中還定義了一個(gè)子協(xié)議change_cipher_spec來(lái)決定何時(shí)對(duì)傳遞的數(shù)據(jù)進(jìn)行加密,TLS 1.3取消了這一機(jī)制,密鑰的使用和改變隨著服務(wù)器和客戶端狀態(tài)的改變自然進(jìn)行。
Part 2-新的術(shù)語(yǔ)
PSK(pre_shared_key)——新的密鑰交換暨身份認(rèn)證機(jī)制
在TLS 1.3草案中提出了幾個(gè)對(duì)性能消耗比較大的可能的解決方法,感興趣的話可以找來(lái)讀一讀。
HKDF(HMAC_based_key_derivation_function)——新的密鑰導(dǎo)出函數(shù)
AEAD(Authenticated_Encrypted_with_associated_data)——唯一保留的加密方式
Part 3-Handshake子協(xié)議
TLS 1.3完整握手工作流
- +表示該報(bào)文中值得注意的extension
- * 表示該內(nèi)容也可能不被發(fā)送
- {} 表示該內(nèi)容使用handshake_key加密
- [] 表示該內(nèi)容使用application_key加密
TLS 1.3握手執(zhí)行步驟
TLS 1.3握手按照嚴(yán)格的順序發(fā)送不同的報(bào)文,各個(gè)報(bào)文包含標(biāo)識(shí)自己種類的數(shù)據(jù)以及其他與握手協(xié)商有關(guān)的擴(kuò)展數(shù)據(jù)(extension)。任何時(shí)候收到不按順序發(fā)出的報(bào)文種類,服務(wù)器會(huì)報(bào)錯(cuò),并轉(zhuǎn)交給alert協(xié)議層處理。?
一個(gè)正常情況下的TLS 1.3握手應(yīng)該按照以下順序組織報(bào)文:
- 客戶端發(fā)送Client Hello(CH)報(bào)文,包含有關(guān)密鑰協(xié)商以及其他與TLS連接建立有關(guān)的擴(kuò)展給服務(wù)端。
- 服務(wù)端發(fā)送Server Hello(SH)報(bào)文,包含有關(guān)密鑰協(xié)商的擴(kuò)展返還給客戶端,雙方根據(jù)CH和SH的協(xié)商結(jié)果可以得出密鑰材料。
- 如果客戶端發(fā)送的CH報(bào)文不滿足服務(wù)端的需要(如:不包含服務(wù)端支持的DH組件),服務(wù)端會(huì)發(fā)送一個(gè)Hello Retry Request報(bào)文給客戶端,要求客戶端重新發(fā)送符合要求的CH報(bào)文。
- 利用密鑰材料和前兩個(gè)報(bào)文的哈希值,使用HKDF可以計(jì)算出一個(gè)handshake_key,此后握手階段的信息受該密鑰保護(hù)。
- 服務(wù)端發(fā)送Encypted Extension(EE)報(bào)文,包含其他與密鑰協(xié)商無(wú)關(guān)的擴(kuò)展數(shù)據(jù)給客戶端。
- 如果使用公鑰證書(shū)進(jìn)行身份認(rèn)證,服務(wù)端發(fā)送Certificate報(bào)文(傳遞自己的證書(shū)信息),和Certificate Verify(CV)報(bào)文(使用自己的證書(shū)私鑰對(duì)之前的報(bào)文進(jìn)行HMAC簽名證明自己持有該證書(shū))給客戶端。
- 如果需要對(duì)客戶端身份進(jìn)行認(rèn)證,服務(wù)端還需要發(fā)送Certificate Request(CR)報(bào)文給對(duì)方請(qǐng)求客戶端發(fā)送證書(shū)。
- 服務(wù)端發(fā)送Finished報(bào)文。表明服務(wù)端到客戶端信道的握手階段結(jié)束,理論上不得再由該信道發(fā)送任何握手報(bào)文。
- 如果客戶端收到了服務(wù)端的CR報(bào)文,返回自己的Certificate報(bào)文和CV報(bào)文。
- 客戶端發(fā)送Finished報(bào)文,表明握手階段結(jié)束,可以正式開(kāi)始會(huì)話通訊。Finished報(bào)文使用會(huì)話密鑰對(duì)上述所有握手信息進(jìn)行HMAC簽名,校驗(yàn)簽名可以檢驗(yàn)握手階段的完整性,也可以驗(yàn)證雙方是否協(xié)商出了一致的密鑰。
所有握手階段的報(bào)文都是由record協(xié)議層加解密、分片、填充、轉(zhuǎn)發(fā)的。?
在這個(gè)過(guò)程中,如果發(fā)生了任何錯(cuò)誤(如:服務(wù)端證書(shū)驗(yàn)證失敗、完整性校驗(yàn)錯(cuò)誤),則會(huì)發(fā)送一個(gè)alert報(bào)文,轉(zhuǎn)交給alert協(xié)議層進(jìn)行錯(cuò)誤處理。
其他沒(méi)有提及到的報(bào)文種類
除了正常的情況之外,還有其他一些報(bào)文可能出現(xiàn)在握手過(guò)程中。
TLS 1.3定義了12種握手報(bào)文
使用Hello傳遞的信息進(jìn)行密鑰協(xié)商——選擇加密組件
經(jīng)過(guò)兩個(gè)Hello報(bào)文后,雙方就明確了計(jì)算密鑰的初始材料和最終使用的加密算法。加密算法是通過(guò)協(xié)商加密組件獲知的。?
因?yàn)橹皇褂肁EAD加密機(jī)制,且徹底禁止了所有不安全的加密算法,TLS 1.3目前支持的加密組件只有以下五種:
以TLS_AES_128_CCM_SHA256為例,TLS表明該加密組件用于TLS協(xié)議,AES表明使用AES對(duì)稱加密算法,128表示密鑰長(zhǎng)度為128位,CCM表明分組加密模式,SHA256是HKDF過(guò)程使用的哈希算法。?
協(xié)商加密組件時(shí),雙方只需要傳遞相應(yīng)的value傳遞即可。由客戶端傳遞一個(gè)所有自己支持的加密組件的列表,由服務(wù)器將最終選定的加密組件值返還給對(duì)方完成協(xié)商。?
TLS 1.2中定義了多達(dá)37種的加密組件,大量使用了MD5、RC4、3DES等被證明不安全或者效率低下的加密算法。?
TLS 1.3僅支持速度快安全性強(qiáng)的加密標(biāo)準(zhǔn)算法AES,以及08年才提出的對(duì)性能消耗極低的CHACHA20。使用CHACHA20進(jìn)行AEAD運(yùn)算時(shí),CHACHA20本身不能提供完整性校驗(yàn)的功能,因此使用POLY1305——一種同樣不耗費(fèi)性能的MAC算法來(lái)提供完整性校驗(yàn)的功能。這些算法,包括協(xié)議中隨著算法使用的分組加密模式CCM和GCM,目前都是理論上安全的算法,不容易被攻擊者破解。
如何得出最終密鑰——PSK密鑰協(xié)商機(jī)制
協(xié)商出來(lái)加密算法,下一步則是協(xié)商出加密密鑰,TLS 1.3支持DH、PSK兩種密鑰協(xié)商機(jī)制,也支持同時(shí)使用兩者進(jìn)行密鑰協(xié)商。?
如果雙方持有未過(guò)有效期的PSK鍵值對(duì),則可以使用PSK進(jìn)行密鑰協(xié)商。雙方傳遞一個(gè)結(jié)構(gòu)體PSK_entry。該結(jié)構(gòu)體包括的內(nèi)容有:PSK對(duì)應(yīng)名字(PSK_name)、用該P(yáng)SK對(duì)之前的握手報(bào)文進(jìn)行的HMAC計(jì)算結(jié)果( PSK_identity)。?
具體的實(shí)施過(guò)程如下:
- 客戶端在CH報(bào)文的pre_key_share擴(kuò)展中傳遞一個(gè)PSK_entry的數(shù)組,包含所有自己持有的PSK信息。
- 服務(wù)端接收到該數(shù)組后,首先根據(jù)PSK_name選擇一個(gè)想要使用的PSK,再使用自己持有的該P(yáng)SK值計(jì)算HMAC值,若與PSK_identity一致,則說(shuō)明雙方持有的PSK一致,否則服務(wù)器報(bào)錯(cuò)。
- 服務(wù)端將選定的PSK_entry結(jié)構(gòu)體在Server Hello中的pre_key_share擴(kuò)展中返還給客戶端。協(xié)商完成,得到初始密鑰PSK
如果使用了PSK,則客戶端可以向服務(wù)端發(fā)送early_data,客戶端會(huì)選擇發(fā)送的PSK_entry數(shù)組中的第一個(gè)PSK計(jì)算early_trffic_key,因此,服務(wù)端也必須選擇第一個(gè)PSK,如果服務(wù)端拒絕接受early data,則返回其他的PSK_entry,客戶端丟棄已發(fā)送的ED報(bào)文。?
使用PSK密鑰協(xié)商,已經(jīng)對(duì)雙方的身份做了一定的認(rèn)證,不得再使用公鑰證書(shū)的認(rèn)證方式,即CV/CR/CT報(bào)文都不會(huì)再發(fā)送。
如何得出最終密鑰——DHE密鑰協(xié)商機(jī)制
使用DHE擴(kuò)展首先需要選定DH參數(shù),對(duì)于有限域DH來(lái)說(shuō)是g和p的值,對(duì)于橢圓域DH是橢圓曲線和基點(diǎn)的值,同選定加密組件一樣,TLS 1.3定義了幾組gp值,雙方只需要協(xié)商想要使用的pg對(duì)即可。?
在TLS 1.2中,g和p的值由雙方自己生成。TLS 1.3則定義了幾組g、p對(duì),雙方只需要選擇想要使用的DH組即可。使用確定的參數(shù)值保證了DH密鑰協(xié)商過(guò)程具有足夠的安全性。?
具體實(shí)施過(guò)程與PSK的實(shí)施過(guò)程類似,由客戶端生成一個(gè)列表包含所有自己支持的DH組,為每個(gè)組生成一個(gè)DH密鑰交換的參數(shù),將其組名和參數(shù)值封裝在key_share擴(kuò)展中,服務(wù)端選定DH組后,返回一個(gè)封裝好的key_share,雙方根據(jù)交換的公鑰參數(shù)和自己持有的私鑰參數(shù)計(jì)算出DH最終密鑰。
理論上,客戶端應(yīng)該將所有與密鑰協(xié)商有關(guān)的擴(kuò)展(pre_shared_key、shared_key)都發(fā)送給服務(wù)端,服務(wù)端選定哪一種,再將對(duì)應(yīng)選定的擴(kuò)展返還給客戶端,如果服務(wù)端同時(shí)使用兩種密鑰協(xié)商,則返還所有擴(kuò)展,如果客戶端沒(méi)有提供足夠的密鑰擴(kuò)展,服務(wù)端發(fā)送HRR報(bào)文要求客戶端重新發(fā)送CH。
使用密鑰協(xié)商結(jié)果計(jì)算實(shí)際使用密鑰
TLS 1.3最大的特點(diǎn)就是對(duì)于不同的報(bào)文使用多種不同的密鑰。?
在TLS 1.2中只使用了兩種密鑰,一個(gè)用于完整性校驗(yàn),一個(gè)用于報(bào)文加密,同一連接不同方向使用的加密密鑰不一樣。?
TLS 1.3因?yàn)槭褂肁EAD機(jī)制,不再需要使用MAC_key來(lái)進(jìn)行完整性校驗(yàn),同時(shí)由于其他各種用途的加密需要,TLS 1.3的實(shí)施過(guò)程還可能計(jì)算或者使用以下幾種key:?
- handshake_key?
- early_traffic_key?
- resumption_key?
- exporter_key(導(dǎo)出密鑰,用于用戶自定義的其他用途)
這些密鑰都是由之前協(xié)商的密鑰材料計(jì)算而出,區(qū)別在于HKDF的計(jì)算次數(shù)不同,HKDF計(jì)算使用的哈希值不同。以會(huì)話密鑰application_key為例,以整個(gè)握手階段的報(bào)文作為輸入,計(jì)算四次HKDF導(dǎo)出最終使用的密鑰。?
同時(shí),當(dāng)加密的報(bào)文達(dá)到一定長(zhǎng)度后,雙方發(fā)送KU報(bào)文重新計(jì)算application_key。
post-authentication機(jī)制
ost-authentication機(jī)制方便用戶確認(rèn)是否向服務(wù)端提供自己的身份信息。
TLS 1.3支持服務(wù)端在握手結(jié)束之后再對(duì)客戶端發(fā)起身份的校驗(yàn)。?
CH報(bào)文中有一個(gè)擴(kuò)展字段post_handshake_anth。如果客戶端發(fā)送了此字段,則允許服務(wù)端在握手階段結(jié)束后再發(fā)起Certificate Request,客戶端會(huì)在收到CR之后再發(fā)送CT、 CV報(bào)文給服務(wù)端進(jìn)行身份認(rèn)證。?
p
Part 4-record子協(xié)議
TLS發(fā)送的報(bào)文由record層處理:
TLS 1.3協(xié)議定義了一系列規(guī)則,大致有幾點(diǎn):?
- 每一個(gè)record的長(zhǎng)度有一定限制。?
- 使用不同密鑰的消息不能在一個(gè)record中。所有可能提示key即將變更的握手信息都必須單獨(dú)發(fā)送(如:KU/SH/FI)。?
- 對(duì)不同種類的報(bào)文有不同的處理方式:?
- HM(handshake message):不能為空,不能在傳遞一連串的HM record時(shí)夾雜其他類型的信息。?
- alert:每個(gè)alert報(bào)文都必須完整發(fā)送,不得分片。?
- application data:對(duì)TLS協(xié)議不可見(jiàn),所以沒(méi)有對(duì)應(yīng)的處理規(guī)則。
AEADEncrypted = AEAD-Encrypt(write_key(即加密密鑰), nonce, plaintext)
雙方維護(hù)一個(gè)64位的sequence number,連接建立和每一次密鑰變更時(shí),sequence number置0,此后隨傳遞的字節(jié)數(shù)增加?
加密時(shí)將sequence擴(kuò)充到write_iv(也是由write_key導(dǎo)出的一個(gè)初始向量)的長(zhǎng)度,再與write_iv做異或計(jì)算得到nonce
最后將數(shù)據(jù)傳遞出去時(shí),record層會(huì)在密文頭部附加一小段明文信息來(lái)標(biāo)識(shí)解密后明文長(zhǎng)度等信息。
對(duì)方的record層收到該消息后,通過(guò)逆過(guò)程解密密文后轉(zhuǎn)發(fā)給上層協(xié)議。
3. TLS 1.3允許TLS對(duì)消息報(bào)文填充來(lái)阻止攻擊者獲知傳送消息的長(zhǎng)度等信息。
填充時(shí)在末尾附上八個(gè)字節(jié)整數(shù)倍的全為0的二進(jìn)制數(shù)據(jù),對(duì)方收到該消息后,解密后從末尾 開(kāi)始去掉0,當(dāng)搜索到第一個(gè)不全為0的八字節(jié)數(shù)據(jù),則結(jié)束。
Part 5-alert子協(xié)議
alert層負(fù)責(zé)處理TLS連接過(guò)程中的各種異常情況,對(duì)每種情況發(fā)送一個(gè)alert報(bào)文,報(bào)文中附加一些錯(cuò)誤處理需要的必要信息,TLS 1.3中定義了30種alert報(bào)文。?
舉例來(lái)講:alert層的close_notify報(bào)文標(biāo)志發(fā)送方打算關(guān)閉TLS連接,不再使用該加密信道傳遞任何信息,bad_record_mac可能表示AEAD解密時(shí)完整性校驗(yàn)失敗。
Part 6-總結(jié)
TLS 1.3使用了復(fù)雜的密鑰導(dǎo)出過(guò)程,增強(qiáng)了最終使用的密鑰的安全性。同時(shí)簡(jiǎn)化了所使用的加密算法,廢棄了RC4、3DES、MD5、SHA1、AES-CBC等加密算法,刪除了壓縮、重協(xié)商等具有漏洞的機(jī)制,大大精簡(jiǎn)了協(xié)議。?
因此,TLS 1.3如果能夠得到普及,網(wǎng)絡(luò)數(shù)據(jù)的傳遞將會(huì)變得更加安全、隱秘,TLS 1.3的推廣需要每一位開(kāi)發(fā)者、運(yùn)營(yíng)者的認(rèn)可和支持。?
目前TLS 1.3雖然還在草案階段,但是其基本原理和思想已經(jīng)應(yīng)用在了實(shí)際生活中,chrome等瀏覽器都已準(zhǔn)備好了對(duì)其的支持,期待TLS 1.3正式成為一個(gè)協(xié)議規(guī)范的那一天。
附錄:參考讀物
以下讀物可以幫助讀者對(duì)TLS 1.3有一些更深的理解?
1.?寫(xiě)的很好的一篇博文,介紹了TLS協(xié)議的歷史和核心思想?
2.?微信基于TLS?1.3較早期草案設(shè)計(jì)的mmtls協(xié)議概述?
3.?cloud flare公司對(duì)TLS?1.3的介紹博文合集(英文)?
4.?TLS?1.3草案合集,可以從這里檢索到最新版的TLS1.3草案(英文)?
5.?16年NDSS會(huì)議研究TLS?1.3的論文合集(英文)
總結(jié)
以上是生活随笔為你收集整理的TLS 1.3科普——新特性与协议实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 移位寄存器及其应用
- 下一篇: 情人节 玫瑰花表白源码