國(guó)鑰SM3的Java程序?qū)崿F(xiàn)_第1頁(yè)
國(guó)鑰SM3的Java程序?qū)崿F(xiàn)_第2頁(yè)
國(guó)鑰SM3的Java程序?qū)崿F(xiàn)_第3頁(yè)
國(guó)鑰SM3的Java程序?qū)崿F(xiàn)_第4頁(yè)
國(guó)鑰SM3的Java程序?qū)崿F(xiàn)_第5頁(yè)
已閱讀5頁(yè),還剩47頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

摘要SM3算法是我國(guó)自主研發(fā)的hash算法。本文將對(duì)SM3算法的加密原理及各個(gè)過程進(jìn)行解析,并使用java語言設(shè)計(jì)程序?qū)崿F(xiàn)SM3算法,將SM3算法的各個(gè)流程通過java函數(shù)進(jìn)行實(shí)現(xiàn),包括數(shù)據(jù)填充,分組和迭代壓縮等。在這個(gè)過程中,通過SM3加密過程中存儲(chǔ)數(shù)據(jù)所使用的java數(shù)據(jù)類型不同,設(shè)計(jì)出兩種不同的SM3算法java實(shí)現(xiàn):SM3-String方式,SM3-BigInteger方式。并對(duì)兩種方式的優(yōu)缺點(diǎn)進(jìn)行分析。最后將設(shè)計(jì)出來的SM3加密程序與java語言自帶的其他雜湊算法(MD5,SHA-256)實(shí)現(xiàn)進(jìn)行對(duì)比,比較它們的運(yùn)行效率?!娟P(guān)鍵詞】hash算法;國(guó)鑰SM3;java程序設(shè)計(jì);AbstractSM3algorithmisahashalgorithmindependentlydevelopedinChina.ThispaperwillanalyzetheencryptionprincipleandeachprocessofSm3algorithm,andusejavalanguagetodesignprogramstorealizeSM3algorithm,andimplementeachprocessofSm3algorithmthroughJavafunctions,includingdatafilling,groupinganditerativecompression.Inthisprocess,throughthedifferentJavadatatypesusedtostoredataintheSM3encryptionprocess,twodifferentSM3algorithmjavaimplementationsaredesigned:SM3stringmodeandSM3BigIntegermode.Theadvantagesanddisadvantagesofthetwomethodsareanalyzed.Finally,theSM3encryptionprogramdesignediscomparedwithotherhashalgorithms(MD5,SHA-256)ofJavalanguage,andtheirrunningefficiencyiscompared.[Keywords]hashalgorithm;nationalkeySM3;Javaprogramming;目錄目錄第一章緒論 第一章緒論研究背景與意義哈希(Hash)算法,也叫散列函數(shù)或雜湊函數(shù)。它最大的特點(diǎn)是能將所有長(zhǎng)度的信息轉(zhuǎn)換成固定長(zhǎng)度的哈希值,而且只能加密不能解密(只能單向運(yùn)算)。是密碼學(xué)里十分重要的分支,在數(shù)字簽名、密碼協(xié)議、完整性認(rèn)證、消息鑒別、等領(lǐng)域起到了十分巨大的作用。哈希算法的種類與發(fā)展:MD2:1989年,RonaldL.Rivest開發(fā)出了MD2算法。MD2算法把需要加密的消息,先進(jìn)行填充,使消息的字節(jié)長(zhǎng)度是16的倍數(shù),然后在末尾添加一個(gè)16位的校驗(yàn)和,然后進(jìn)行運(yùn)算,得出128位散列值(哈希值)。MD4:1990年,Rivest繼MD2后又開發(fā)了更安全的MD4算法,MD4算法對(duì)消息的填充方式與MD2不同,它使填充后消息長(zhǎng)度mod512=448,再將一個(gè)表示消息原來長(zhǎng)度的64位二進(jìn)制數(shù)填充到消息末尾。然后將消息按512比特一組進(jìn)行分組,最后對(duì)每個(gè)分組進(jìn)行三個(gè)不同步驟的處理,得出散列值(哈希值)長(zhǎng)度與MD2相同。MD5:1991年,Rivest開發(fā)出技術(shù)上更為趨近成熟的MD5算法。MD5由MD4、MD2改進(jìn)而來。雖然MD5的復(fù)雜度要比MD4大一些,但卻更為安全。在MD5算法中,對(duì)消息進(jìn)行填充分組的處理,和產(chǎn)生的散列值(哈希值)的長(zhǎng)度與MD4相同。SHA-0和SHA-1:SHA系列的算法,由美國(guó)國(guó)家安全局(NSA)所設(shè)計(jì),美國(guó)國(guó)家標(biāo)準(zhǔn)與技術(shù)研究院(NIST)發(fā)布,是美國(guó)的政府標(biāo)準(zhǔn)。1993年NSA發(fā)布了SHA-0,因?yàn)槠浯嬖诎踩珕栴},發(fā)布之后很快就被NSA撤回,在1995年NSA發(fā)布SHA-0的改進(jìn)版SHA-1,SHA-1和SHA-0的算法只在壓縮函數(shù)的訊息轉(zhuǎn)換部分差了一個(gè)位元的循環(huán)位移。SHA-0和SHA-1可將一個(gè)最大為264的消息,處理成160比特的散列值(哈希值)。無論是MD2,MD4,MD5,還是SHA-1,他們生成的散列值(哈希值)都比較短,如MD5能生成的散列值(哈希值)只有128比特,這就意味著他們生成的散列值(哈希值)只有2128種,一旦加密的消息超過2128種,就必定會(huì)出現(xiàn)重復(fù)的散列值(哈希值)。這些算法安全性越來越滿足不了時(shí)代的發(fā)展,也開始逐漸被更先進(jìn)的hash算法取代。SHA-2:NSA于2001年發(fā)布SHA-2,其下又可再分為六個(gè)不同的算法標(biāo)準(zhǔn),包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。其中較為常見的是SHA-256和SHA-512,分別能生成256比特于512比特的散列值(哈希值)。國(guó)鑰SM3:國(guó)鑰算法也稱國(guó)密算法,是指國(guó)家密碼局認(rèn)定的國(guó)產(chǎn)商用密碼算法。而國(guó)鑰SM3是國(guó)鑰算法中唯一的散列算法(哈希算法),是王小云等人進(jìn)行設(shè)計(jì)的,由國(guó)家密碼局于2010年12月17日發(fā)布。SM3算法也會(huì)對(duì)消息進(jìn)行填充分組處理,該過程與MD5,SHA-256一致,最終生成256位的散列值(哈希值)。因此,國(guó)鑰SM3在安全性方面高于MD5,SHA-1,與SHA-256相當(dāng)。SHA-2與國(guó)鑰SM3都是目前安全性較高哈希算法,越來越的人根據(jù)這些算法研究開發(fā)出各種軟件和硬件,并應(yīng)用于各個(gè)行業(yè)和領(lǐng)域中。本文也是針對(duì)其中之一的國(guó)鑰SM3算法進(jìn)行編程實(shí)現(xiàn)。本文的總體內(nèi)容本文主要使用java編程語言設(shè)計(jì)出能夠進(jìn)行SM3算法加密的程序,以下是本文的結(jié)構(gòu)第一章 :緒論,主要概述本論文相關(guān)技術(shù)的研究背景與意義。介紹文章結(jié)構(gòu)第二章 :對(duì)SM3算法的工作過程進(jìn)行介紹與解析。第三章 :SM3算法的java程序?qū)崿F(xiàn)。第四章 :對(duì)本文進(jìn)行總結(jié)。第二章SM3算法過程解析2.1SM3算法簡(jiǎn)述SM3雜湊算法可將長(zhǎng)度小于264比特的消息經(jīng)過填充、反復(fù)的消息擴(kuò)展和壓縮,生成長(zhǎng)度為256比特的雜湊值。2.2SM3算法具體過程消息填充:其原理是在填充一個(gè)1,若干個(gè)0,和一個(gè)64位的消息二進(jìn)制長(zhǎng)度,其中有65位是固定填充的,而填充0的個(gè)數(shù)用于保證填充后的消息長(zhǎng)度是512的倍數(shù)。假設(shè)輸入的消息m的長(zhǎng)度為L(zhǎng)比特。假設(shè)消息m的二進(jìn)制為10101010,其長(zhǎng)度為8,通過公式計(jì)算8+1+k≡448mod512,需要填充的0的個(gè)數(shù)k=439.所以最終進(jìn)行的填充是:(1) 在消息m的末尾填充一個(gè)1(2) 在消息m的末尾填充439個(gè)0(3) 將8的二進(jìn)制值1000,拓展到64位,填充到消息m的末尾圖2-1為填充過程圖解:圖2-1填充過程迭代壓縮:將m’按每組512比特進(jìn)行分組:m’=B(0)B(1)…B(n-1),其中n=(l+k+65)/512.然后對(duì)m’按下列方式迭代:FORi=0TOn-1V(i+1)=CF(V(i),B(i))ENDFOR其中CF是壓縮函數(shù),v(0)為256bit初始值IV,值為0x7380166f,0x4914b2b9,0x172442d7,0xda8a0600,0xa96f30bc,0x163138aa,0xe38dee4d,0xb0fb0e4eB(i)為填充后的消息分組,迭代壓縮的結(jié)果為V(n)消息拓展:在上一步迭代壓縮中,每一步的for循環(huán)我們都會(huì)將一個(gè)512比特的分組B(i)傳入壓縮函數(shù)CF中,在CF中B(i)會(huì)進(jìn)行以下的操作來拓展生成132個(gè)字W0,W1,…,W67,W’0,W’1,…,W’63,用于壓縮函數(shù)CF的下一步操作:1. 生成W0-W16:將消息分組B(i)的二進(jìn)制每32位劃分為一個(gè)字,最終劃分出16個(gè)字,作為W0-W16。2. 生成W16-W67:FORj=16TO67Wj←P1(Wj-16⊕Wj-9⊕Wj-3<<<15))⊕(Wj-13<<<7)⊕Wj-6ENDFOR3. 生成W’0-W’63:FORj=0TO63W’j=Wj⊕Wj+4ENDFOR壓縮函數(shù)CF:A,B,C,D,E,F,G,H為能夠存儲(chǔ)32為比特的字寄存器,SS1,SS2,TT1,TT2為中間變量,其中存儲(chǔ)的也是32為比特,壓縮函數(shù)Vi+1=CF(V(i),B(i)),0≤i≤n-1。計(jì)算過程如下:ABCDEFGH←V(i)FORj=0TO63SS1←((A<<<12)+E+(Tj<<<j))<<<7SS2←SS1⊕(A<<<12)TT1←FFj(A,B,C)+D+SS2+Wj’TT2←GGj(E,F,G)+H+SS1+WjD←CC←B<<<9B←AA←TT1H←GG←F<<<19F←EE←P0(TT2)ENDFORV(i+1)←ABCDEFGH⊕Vi雜湊值(哈希值):ABCDEFGH←V(n)輸出256比特的雜湊值y=ABCDEFGH。第三章SM3的java實(shí)現(xiàn)3.1程序核心方法SM3() //sm3核心方法,用String存儲(chǔ) privatestaticStringsm3(Stringm){ //調(diào)用填充函數(shù) Stringm2=padding(m); //調(diào)用分組函數(shù) int[][]m3=fenzu(m2); //調(diào)用壓縮函數(shù) int[]m4=diedaiyasuo(m3); Stringsm3hash=""; for(inti:m4){ sm3hash+=Integer.toHexString(i); } returnsm3hash; }sm3()方法就是整個(gè)sm3程序的主干,sm3算法的填充,分組,迭代壓縮三個(gè)部分每部分都用一個(gè)獨(dú)立的方法實(shí)現(xiàn),sm3()核心方法的工作就是調(diào)用這些方法,之后將結(jié)果轉(zhuǎn)換成16進(jìn)制字符串的形式返回。sm3()方法使整個(gè)sm3算法的架構(gòu)較為清晰,一定程度上降低了程序的耦合度。在測(cè)試階段更容易定位問題的位置,日后若要對(duì)代碼進(jìn)行改進(jìn)也更方便。3.2填充函數(shù)padding()填充函數(shù)的作用就是在消息后面填充一個(gè)1,若干個(gè)0,和一個(gè)64位的消息二進(jìn)制長(zhǎng)度,最終得出長(zhǎng)度為512倍數(shù)的填充消息。整個(gè)填充過程,消息m都是用java的String字符串進(jìn)行存儲(chǔ),一個(gè)String字符串由多個(gè)char字符組成,在填充時(shí)是以8比特的字符為單位對(duì)消息m進(jìn)行填充 //sm3填充函數(shù) privatestaticStringpadding(Stringm){ //mLen為信息m二進(jìn)制的長(zhǎng)度,sm3能處理消息長(zhǎng)度最長(zhǎng)為2的64次方bit,因此需要用java里長(zhǎng)度為64位的long類型存儲(chǔ) longmLen=m.length()*8; //f是需要填充的0的個(gè)數(shù) intf=(int)(512-(mLen+1+64)%512); //以字符為單位填充1和0 //0x80等于一個(gè)1和7個(gè)0 m+=(char)0x80; for(inti=0;i<(f-7)/8;i++){ m+=(char)0x00; } m+=longToString(mLen); returnm; }longToString()方法:由于sm3能處理的消息長(zhǎng)度最大為264,所以用long來存儲(chǔ)消息m的二進(jìn)制長(zhǎng)度mLen,方便計(jì)算需要填充0的個(gè)數(shù),在運(yùn)算完之后,需要填充mLen時(shí),就需要把mLen的存儲(chǔ)類型從long轉(zhuǎn)為String,所以需要設(shè)計(jì)一個(gè)longToString()方法來完成類型轉(zhuǎn)換。longToString()方法的思路就是對(duì)64位的long類型,通過java的位運(yùn)算符,從高位到低位將每8位轉(zhuǎn)成一個(gè)char字符,并拼接成字符串。longToString()方法的結(jié)果就是傳入的long類型變量將轉(zhuǎn)換成一個(gè)8字符的String字符串。如值為0110000101100010011000110110010001100101011001100110011101101000的long類型,通過該方法轉(zhuǎn)換為String類型后為“abcdefgh”。//long類型轉(zhuǎn)String類型 privatestaticStringlongToString(longnum){ Strings=""; for(inti=7;i>=0;i--){ s+=(char)((num>>i*8)&0xff); } returns; }測(cè)試填充結(jié)果:假設(shè)消息m為“usb”,其二進(jìn)制為:011101010111001101100010,長(zhǎng)度mlen=24,需要填充0的個(gè)數(shù)f=512-011101010111001101100010100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011000前文提到過,該程序的填充,分組,迭代壓縮都用獨(dú)立的函數(shù)實(shí)現(xiàn),所以可以編寫一段代碼單獨(dú)調(diào)用填充函數(shù)來測(cè)試結(jié)果是否正確//測(cè)試填充函數(shù)publicstaticvoidtextpadding(){ Stringm="usb";//調(diào)用填充函數(shù) Stringm2=padding(m); //打印填充結(jié)果的二進(jìn)制 System.out.println("填充結(jié)果為:"); for(inti=0;i<m2.length();i++){ Stringm3=Integer.toBinaryString((int)(m2.charAt(i))); //由于java會(huì)自動(dòng)略高位的0,所以手動(dòng)補(bǔ)齊 while(8-m3.length()>0){ m3='0'+m3; } System.out.print(""+m3); if((i+1)%8==0){ System.out.println(); } }}輸出結(jié)果與猜想一致,如圖3-1.1:圖3-1測(cè)試函數(shù)運(yùn)行結(jié)果以字符為單位填充1和0,填充二進(jìn)制位0x80代表一個(gè)1和7個(gè)0,之后的0每8個(gè)用二進(jìn)制0x00進(jìn)行填充,因?yàn)樘畛淝暗南是字符串,字符串由字符組成,字符的存儲(chǔ)最小單位是字節(jié)(8比特),所以消息m二進(jìn)制長(zhǎng)度必定為8的倍數(shù),填充后的消息二進(jìn)制長(zhǎng)度是512的倍數(shù),是8的倍數(shù),最后填充的消息長(zhǎng)度固定是64位,也是8的倍數(shù)。因此填充中間的1和若干個(gè)0的一定也是的二進(jìn)制長(zhǎng)度也必定為8的倍數(shù),由此證明用字符為單位進(jìn)行1和0的填充并不會(huì)出現(xiàn)不滿或溢出的情況,如圖3-2所示:圖3-2證明圖解3.3分組函數(shù)fenzu()分組函數(shù)的作用是將填充后的消息按512比特為一組進(jìn)行分組。在上一節(jié)填充里,填充后的消息是用String字符串進(jìn)行存儲(chǔ)的,根據(jù)一個(gè)字符8比特,分組后每一組都是一個(gè)長(zhǎng)度為64的字符串。JavaString類的substring()方法可以獲取到字符串的子串,分組函數(shù)就是同過該方法每獲取消息的64長(zhǎng)度的子串,并進(jìn)行存儲(chǔ),以此實(shí)現(xiàn)分組的功能。為了方便后面迭代壓縮的運(yùn)算,設(shè)計(jì)出StringToIntArray()方法來將每組64長(zhǎng)度的字符串轉(zhuǎn)換成為一個(gè)長(zhǎng)度為16的int數(shù)組。//分組函數(shù) privatestaticint[][]fenzu(Stringm2){ //num:分組數(shù),因java數(shù)組限制,分組數(shù)用32位的int存儲(chǔ) intnum=m2.length()/64; //將String轉(zhuǎn)換成int[num][16],每個(gè)int[16]存儲(chǔ)512bit, int[][]m3=newint[num][16]; for(inti=0;i<num;i++){ m3[i]=StringToIntArray(m2.substring(i*64,i*64+64)); } returnm3;}stringToIntArray()方法:為了方便后面迭代壓縮的運(yùn)算,設(shè)計(jì)出StringToIntArray()方法來將每組64長(zhǎng)度的字符串轉(zhuǎn)換成為一個(gè)長(zhǎng)度為16的int數(shù)組。//將512bit的字符串轉(zhuǎn)換為int[16]數(shù)組 privatestaticint[]StringToIntArray(Strings){ byte[]b; int[]a=newint[16]; try{ b=s.getBytes("ISO-8859-1"); for(inti=0;i<16;i++){ //byte[4]轉(zhuǎn)int //&0xff是為了char變int時(shí)只取低八位,因?yàn)殚_頭為1的byte數(shù)變int時(shí)高位會(huì)自動(dòng)補(bǔ)1 a[15-i]=(int)((b[i*4]&0xff)<<24)|((b[i*4+1]&0xff)<<16)|((b[i*4+2]&0xff)<<8)|(b[i*4+3]&0xff); } }catch(UnsupportedEncodingExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returna; }StringToIntArray()方法的思路是先用String類的getBytes()方法將String字符串轉(zhuǎn)換為一個(gè)byte類型的數(shù)組,該數(shù)組每一個(gè)值都是一個(gè)8位的byte類型,而這里由于需要操作的字符串已經(jīng)固定為512比特,也就是能轉(zhuǎn)換為16個(gè)int值。因此循環(huán)16次,每次循環(huán)將char數(shù)組里的4個(gè)字符轉(zhuǎn)換為一個(gè)int值。4個(gè)byte類型轉(zhuǎn)換為1個(gè)int類型的思路如下:例如某一次循環(huán)中,b[j*4],b[j*4+1],b[j*4+2],b[j*4+3]在內(nèi)存中的二進(jìn)制值分別為01111111,00111111,00011111,00001111。將其分別左移24,16,8,0位得到:01111111000000000000000000000000001111110000000000000000000111110000000000001111將4個(gè)數(shù)進(jìn)行或(|)運(yùn)算,得到一個(gè)32位int類型的值:01111111001111110001111100001111“&0xff”的作用:在進(jìn)行或運(yùn)算時(shí),進(jìn)行了一次“&0xff”操作,0xff的值是11111111,理論上來所一個(gè)同樣是8位的char類型的值對(duì)11111111進(jìn)行&運(yùn)算應(yīng)該都為自己本身,那為什么還要進(jìn)行這個(gè)操作?其實(shí)“&0xff”操作修改的并不是低8位,而是高位。在上述4個(gè)數(shù)或運(yùn)算的過程中,可以發(fā)現(xiàn)這4個(gè)數(shù)的位數(shù)是不一樣的,分別是32位,24位,16位和8位,為了成功進(jìn)行或運(yùn)算,計(jì)算機(jī)會(huì)自動(dòng)將低位擴(kuò)展成高位,因此實(shí)際進(jìn)行或運(yùn)算的四個(gè)數(shù)是:01100001000000000000000000000000000000000110001000000000000000000000000000000000011000110000000000000000000000000000000001100100而問題就在于低位拓展為高位這里,如果將第四個(gè)數(shù)改成10000000,因?yàn)橛?jì)算機(jī)內(nèi)存采用的是二進(jìn)制的補(bǔ)碼,為了保證拓展后的原碼的值一致,最高位為1的數(shù)高位都是1而不是0,所以拓展后的數(shù)為111111111111111111111111100000000。但對(duì)于sm3算法來說數(shù)據(jù)就被修改了,正確的應(yīng)該是00000000000000000000000010000000,因?yàn)閟m3算法中并不會(huì)關(guān)心這個(gè)數(shù)原碼的值是什么,而只關(guān)注它的二進(jìn)制機(jī)器數(shù)。&0xff可以保證一個(gè)數(shù)從低位拓展為高位之后,其機(jī)器值不會(huì)發(fā)生改變。字符串編碼的問題:在前面我們提到過這個(gè)程序用字符串來存儲(chǔ)數(shù)據(jù)用于并進(jìn)行填充與分組,但用字符串存儲(chǔ)會(huì)因?yàn)樽址幋a產(chǎn)生一些問題,為什么在這一章節(jié)講,因?yàn)镾tringToIntArray方法中調(diào)用的getBytes()方法有一個(gè)字符編碼的過程,而程序字符串編碼產(chǎn)生的問題會(huì)在這里展現(xiàn)出來。在這里涉及到一些知識(shí):char類型在java中占用多少個(gè)字節(jié),其實(shí)與字符是中英文還有使用的編碼集有關(guān),如utf-8編碼中文占3個(gè)字節(jié),英文占1個(gè)字節(jié),在ISO-8859-1編碼下字符都占用1字節(jié),因此ISO-8859-1編碼的字符較少,無法編碼中文等許多其他字符。char類型和String類型在內(nèi)存中使用編碼是Unicode。編碼和解碼實(shí)質(zhì)是字符和二進(jìn)制數(shù)的轉(zhuǎn)換。在上文中經(jīng)常提到的用一個(gè)char類型存儲(chǔ)8比特的數(shù)據(jù),其實(shí)該char字符在內(nèi)存中占用可能不是8比特,只是對(duì)該char字符進(jìn)行編碼后能得到一個(gè)8比特的值。在StringToIntArray()方法中,使用了“b=s.getBytes("ISO-8859-1");”來對(duì)字符串進(jìn)行編碼轉(zhuǎn)換成byte數(shù)組。為什么使用“ISO-8859-1”編碼,而不使用其他編碼,這其實(shí)與填充時(shí)填充的字符有關(guān),下面用一段代碼進(jìn)行說明: publicstaticvoidmain(String[]args){ //TODOAuto-generatedmethodstub Strings=""; s+=(char)0x80; byte[]b,b1; try{ b=s.getBytes("ISO-8859-1"); //s.getBytes()默認(rèn)使用當(dāng)前平臺(tái)的字符編碼 b1=s.getBytes(); System.out.println("b:"+b[0]+"\nb1:"+b1[0]); }catch(UnsupportedEncodingExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); }運(yùn)行結(jié)果如圖3-3:圖3-3運(yùn)行結(jié)果和填充過程類型,向字符串中填入0x80,其二進(jìn)制的值為二進(jìn)制為10000000,通過運(yùn)行結(jié)果發(fā)現(xiàn)與使用“ISO-8859-1”編碼的輸出b的二進(jìn)制符合,但使用平臺(tái)默認(rèn)編碼的輸入b1不同,63(十進(jìn)制)的二進(jìn)制為00111111。其中的原因就是0x80在內(nèi)存中解碼成unicode字符,然后通過s.getBytes()編碼時(shí)同一個(gè)字符被不同的編碼集編碼出了不同的二進(jìn)制數(shù)。使用“ISO-8859-1”編碼為了防止這種情況出現(xiàn),但也會(huì)因此產(chǎn)生其他缺點(diǎn),就如第1個(gè)知識(shí)點(diǎn)所說的,“ISO-8859-1”編碼是單字節(jié)編碼,其能編碼的字符數(shù)相比其他編碼方式要少得多,對(duì)于不能識(shí)別的字符,編碼都會(huì)將改為‘?’字符。因此該程序只能對(duì)英文數(shù)字等字符進(jìn)行sm3算法加密。3.4迭代壓縮函數(shù)這里與sm3算法的偽代碼部分基本一致,將分組后的消息迭代放入壓縮函數(shù)CF中執(zhí)行。//sm3迭代壓縮函數(shù) privatestaticint[]diedaiyasuo(int[][]m3){ int[]v={0x7380166f,0x4914b2b9,0x172442d7,0xda8a0600,0xa96f30bc,0x163138aa,0xe38dee4d,0xb0fb0e4e}; for(inti=0;i<m3.length;i++){ v=CF(v,m3[i]); } returnv; }消息拓展函數(shù):該函數(shù)的作用是將消息分組拓展成生成132個(gè)消息字w0,w1,…w67,w’1,…w’63,,用于壓縮函數(shù)CF中,這里消息字的定義是32比特的串,因此用java的int類型進(jìn)行存儲(chǔ),其中w0,w1,…w67存儲(chǔ)在w1數(shù)組中,w’1,…w’63存儲(chǔ)在w2數(shù)組中。之后再將w1,w2兩個(gè)數(shù)組打包成一個(gè)二維數(shù)組返回。//sm3消息拓展 privatestaticint[][]tuozhan(int[]tzm){ int[]w1=newint[68]; int[]w2=newint[64]; //前16位存儲(chǔ)的是信息m for(inti=0;i<16;i++){ w1[i]=tzm[15-i]; } //后52位是拓展 for(inti=16;i<68;i++){ w1[i]=p1(w1[i-16]^w1[i-9]^left(w1[i-3],15))^left(w1[i-13],7)^w1[i-6]; } for(inti=0;i<64;i++){ w2[i]=w1[i]^w1[i+4]; } //將拓展出來的兩個(gè)數(shù)組w1,w2用一個(gè)二維數(shù)組打包起來返回 int[][]w={w1,w2}; returnw; }壓縮函數(shù)CF壓縮函數(shù)CF中,八個(gè)字寄存器A,B,C,D,E,F,G,H,與中間變量ss1,ss2,tt1,tt2里的值都是32比特,因此都使用int類型進(jìn)行存儲(chǔ)。//壓縮函數(shù)CF privatestaticint[]CF(int[]v,int[]b){ //常量tj intTj; //調(diào)用拓展函數(shù) int[][]w=tuozhan(b); //定義各個(gè)寄存器 intA=v[0]; intB=v[1]; intC=v[2]; intD=v[3]; intE=v[4]; intF=v[5]; intG=v[6]; intH=v[7]; intss1; intss2; inttt1; inttt2; for(inti=0;i<64;i++){ if(i>=0&&i<=15){ Tj=0x79cc4519; } else{ Tj=0x7a879d8a; } ss1=left(left(A,12)+E+left(Tj,i),7); ss2=ss1^left(A,12); tt1=FFj(A,B,C,i)+D+ss2+w[1][i]; tt2=GGj(E,F,G,i)+H+ss1+w[0][i]; D=C; C=left(B,9); B=A; A=tt1; H=G; G=left(F,19); F=E; E=p(tt2); } //得到新的v int[]v1={A,B,C,D,E,F,G,H}; for(inti=0;i<8;i++){ v1[i]=v1[i]^v[i]; } returnv1; }布爾函數(shù)FFj與GGj:用于壓縮函數(shù)CF中,代碼如下://布爾函數(shù)privatestaticintFFj(intx,inty,intz,inti){ if(i>=0&&i<=15){ returnx^y^z; } else{ return((x&y)|(x&z)|(y&z)); } }privatestaticintGGj(intx,inty,intz,inti){ if(i>=0&&i<=15){ returnx^y^z; } else{ return((x&y)|(~x&z)); } }置換函數(shù)p,p1:p用于壓縮函數(shù)CF中,p1用于消息拓展中,代碼如下://sm3消息拓展中用到的置換函數(shù)p1 privatestaticintp1(intx){ returnx^left(x,15)^left(x,23); } //sm3壓縮函數(shù)中用到的置換函數(shù)p privatestaticintp(intx){ returnx^left(x,9)^left(x,17); }循環(huán)左移函數(shù)left():在壓縮函數(shù)CF中,需要用到循環(huán)左移的操作,即在左移的時(shí)候,超出左端的數(shù)后移動(dòng)到最右端,如00001000,進(jìn)行5次8比特位的循環(huán)左移的結(jié)果位00000001。由于java只提供了位移操作符只有左移(<<),右移(>>)與無符號(hào)右移(>>>),并沒有提供循環(huán)位移,因此要自己實(shí)現(xiàn)。思路就是將左移后會(huì)在左端溢出的值通過無符號(hào)右移位移到最右端。還是上面的例子,00001000進(jìn)行5次8比特位的循環(huán)左移,等于將其左移5次:00000000,與無符號(hào)右移3次:00000001,進(jìn)行與操作。代碼如下://32位循環(huán)左移 privatestaticintleft(inta,intb){ returna<<b|a>>>(32–b%32); }3.5程序main方法main方法是java程序的入口,我們需要在main方法內(nèi)接收需要進(jìn)行處理的字符串,調(diào)用sm3()方法進(jìn)行SM3加密,并輸出加密結(jié)果。代碼如下: publicstaticvoidmain(String[]args){ //TODOAuto-generatedmethodstub System.out.println("輸入需要加密的數(shù)據(jù):\n"); Scannerinput=newScanner(System.in); Stringm=input.nextLine(); //m=sm3two(m); m=sm3(m); System.out.println(m);}程序運(yùn)行結(jié)果如圖3-4圖3-4運(yùn)行結(jié)果3.6程序存在的問題與改進(jìn)在對(duì)本文中的程序完成后,我也回過頭整個(gè)對(duì)程序進(jìn)行審查,收集在設(shè)計(jì)與開發(fā)過程中的不足與問題。目前程序存在的問題主要有以下兩點(diǎn):1.SM3算法在設(shè)計(jì)上是能處理最多長(zhǎng)度為264-1比特的消息,但在該程序的開發(fā)中,許多地方由于java數(shù)據(jù)類型的限制(如java數(shù)組最多只能存儲(chǔ)232個(gè)元素),并不能對(duì)264-1比特的消息進(jìn)行處理,目前程序只能保證處理長(zhǎng)度在232比特以下的消息。2.也就是本文在分組函數(shù)一節(jié)中提到過該程序存在的問題:無法對(duì)“ISO-8859-1”編碼集外的字符進(jìn)行sm3加密。對(duì)于第一個(gè)問題,需要對(duì)程序多個(gè)地方的數(shù)據(jù)存儲(chǔ)類型進(jìn)行修改,根據(jù)算法分析出其所需要承受的數(shù)據(jù)量,再尋找更為合適的java數(shù)據(jù)結(jié)構(gòu)進(jìn)行存儲(chǔ),本文目前沒有對(duì)該問題的解決方案。對(duì)于第二個(gè)問題,想要解決,就得從根源出發(fā):不使用字符串在填充分組過程中存儲(chǔ)消息。因此,本文也探索了一些其他的方法來實(shí)現(xiàn)這些功能,使用BigInteger來存儲(chǔ)消息。BigInteger是java一個(gè)類,它的實(shí)例用于存儲(chǔ)任意精度的整型,可以理解為沒有長(zhǎng)度限制的int類型,BigInteger自帶許多用于數(shù)學(xué)計(jì)算的方法,幾乎java整型能夠進(jìn)行的所有數(shù)學(xué)計(jì)算,BigInteger也都能夠進(jìn)行。使用BigInteger實(shí)現(xiàn)填充函數(shù)padding()://sm3填充函數(shù)2 privatestaticBigIntegerpadding2(Stringm){ BigIntegerm2=newBigInteger(m.getBytes()); //信息m的長(zhǎng)度,sm3能處理消息長(zhǎng)度最長(zhǎng)為2的64次方bit,因此需要用long類型存儲(chǔ) longmLen=m.length()*8; //f是需要填充的0的個(gè)數(shù) intf=(int)(512-(mLen+1+64)%512); //用位移填充:左移1位,填充1,再左移f+64位,填充信息長(zhǎng)度mlen m2=m2.shiftLeft(1).add(BigInteger.ONE).shiftLeft(f+64).add(BigInteger.valueOf(mLen)); returnm2; }先把輸入的消息m從字符串轉(zhuǎn)換成BigInteger類型,再用BigInteger的位移函數(shù)實(shí)現(xiàn)消息填充,邏輯較為簡(jiǎn)單,左移1位,填充1,再左移f+64位,填充信息長(zhǎng)度mlen(f是需要填充0的個(gè)數(shù))。使用BigInteger實(shí)現(xiàn)分組函數(shù): //sm3分組函數(shù)2 privatestaticint[][]fenzu2(BigIntegerm2){ //num:分組數(shù),因java數(shù)組限制,分組數(shù)用32位的int存儲(chǔ) //bitLength()計(jì)算出的bit數(shù)不算符號(hào)位,所以要+1 intnum=(int)((m2.bitLength()+1)/512); //將bigInteger轉(zhuǎn)換成int[][16],每個(gè)int[16]存儲(chǔ)512bit, int[][]m3=newint[num][16]; //生成一個(gè)值為0xffffffff的BigInteger byte[]b={(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff}; BigIntegera=newBigInteger(b); //i:num-0 //j:0-16 for(inti=num;i>0;i--){ for(intj=0;j<16;j++){//與0x0xffffffff相與,得到后32位,并進(jìn)行存儲(chǔ) m3[i-1][j]=m2.and(a).intValue(); //將原數(shù)右移32位,去掉已存儲(chǔ)的部分。 m2=m2.shiftRight(32); } } returnm3; }將填充后的BigInteger分組。先生成一個(gè)值為0xffffffff的BigInteger,與存儲(chǔ)消息的BigInteger相與,消息的后32位比特?cái)?shù),轉(zhuǎn)換位int進(jìn)行存儲(chǔ),循環(huán)16次后,得到存儲(chǔ)512bit消息的int[16]。最終獲得一個(gè)int類型的二維數(shù)組。兩種方式優(yōu)缺點(diǎn):測(cè)試兩種方式加密得到的哈希值,測(cè)試結(jié)果如表3.5.1,表3.5.2所示表3.5.1String方式輸入256位雜湊值運(yùn)行時(shí)間(納秒)abc66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0730400nsefg7e0d11e6455eaabda193edefcbc8f7a5ae68193e5ec4d27aa2fad0b11c8e5245645300ns中心7fe10270de421704761d2d713296def351af99c1a7fd1861108bb73872a07b2440400ns一個(gè)7fe10270de421704761d2d713296def351af99c1a7fd1861108bb73872a07b2373300ns暴風(fēng)雨c51238da672a707d2e6da79280634d0bac110d60eb5a40fbd99ffabcd7f8b7ed711800ns長(zhǎng)頸鹿c51238da672a707d2e6da79280634d0bac110d60eb5a40fbd99ffabcd7f8b7ed384900nsabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd(去掉回車)debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732868100ns表3.5.2Biginteger方式輸入256位雜湊值運(yùn)行時(shí)間(納秒)abc66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0908800nsefg7e0d11e6455eaabda193edefcbc8f7a5ae68193e5ec4d27aa2fad0b11c8e5245968100ns中心3b453bf1b95ee032db763624ff0c5012bfc9d2d59d0b8a44aa3c2379834279e993100ns一個(gè)a06c32ca76ec69343ac0db93452e339d1746c68c6afe51e02ed28acff2dfc00e1413500ns暴風(fēng)雨8a4c508c5496c59de17ba814ed86ff10cd80d286ada7cef895fd25691ccd9ba893400ns長(zhǎng)頸鹿525b6b76c26e4eb7e899af154d3b19441e67351a94ac305a86f2c89e4621a87a968600nsabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd(去掉回車)debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c57321660800ns結(jié)論:由表可以發(fā)現(xiàn),String方式確實(shí)會(huì)出現(xiàn)中文等字符全部被替換成了‘?’而導(dǎo)致加密錯(cuò)誤,Biginteger雖然中英文都能夠成功加密,但在單次加密中相比String方式加密效率更慢。與java內(nèi)的其他哈希算法進(jìn)行效率對(duì)比:Java中的可以通過MessageDigest類進(jìn)行各種信息摘要算法(哈希算法)加密,包括MD5,SHA-256算法。本節(jié)把實(shí)現(xiàn)的javaSM3加密程序與MessageDigest類的MD5,SHA-256加密進(jìn)行效率對(duì)比。對(duì)比方式:三個(gè)算法對(duì)字符串“abc”迭代加密1000次,即對(duì)abc進(jìn)行加密,把得到的hash值作為字符串再次進(jìn)行加密,循環(huán)1000次。將三者的運(yùn)行時(shí)間作對(duì)比。以下是代碼: //MessageDigest類的MD5加密 privatestaticStringmd5(Stringm){ Strings=""; try{ MessageDigestmd5hash=MessageDigest.getInstance("md5"); md5hash.update(m.getBytes()); //byte數(shù)組轉(zhuǎn)16進(jìn)制字符串 s=byteToHexString(md5hash.digest()); }catch(NoSuchAlgorithmExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returns; } //MessageDigest類的SHA-256加密privatestaticStringSHA256(Stringm){ Strings=""; try{ MessageDigestmd5hash=MessageDigest.getInstance("SHA-256"); md5hash.update(m.getBytes()); s=byteToHexString(md5hash.digest()); }catch(NoSuchAlgorithmExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returns; } //byte數(shù)組轉(zhuǎn)16進(jìn)制字符串 privatestaticStringbyteToHexString(byte[]m){ char[]hexChar={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; StringhexString=""; for(bytei:m){ hexString=hexString+hexChar[i>>>4&0xf]+hexChar[i&0xf]; } returnhexString; }md5()和SHA256()分別是調(diào)用MessageDigest類的MD5加密,SHA-256加密,加密的結(jié)果是byte[]類型的數(shù)組,byteToHexString()方法用于將byte數(shù)組轉(zhuǎn)換為16進(jìn)制字符串。//主方法 publicstaticvoidmain(String[]args){ //TODOAuto-generatedmethodstub longstartTime=System.nanoTime();//納秒 Strings="abc"; for(inti=1;i<1000;i++){ s=md5(s); //s=SHA256(s); //s=sm3(s);//String //s=sm3two(s);//bigInteger } longendTime=System.nanoTime(); System.out.println("程序運(yùn)行時(shí)間:"+(endTime-startTime)+"ns"); }迭代加密1000次,打印運(yùn)行時(shí)間運(yùn)行結(jié)果如圖3-5:圖3-5迭代加密運(yùn)行結(jié)果結(jié)論:MessageDigest類的MD5、SHA-256與SM3-String方式的加密效率相近,而SM3-BigInteger方式雖然在上一節(jié)的比較中單次加密效率不及SM3-String方式,但連續(xù)加密多次效率卻反而比前三者更優(yōu),這可能與java語言的底層原理有關(guān)系。第四章總結(jié)這本文中,我最終也完成了目標(biāo),成功將SM3算法使用java實(shí)現(xiàn)。在這個(gè)過程中,我也遇到了許多困難。最開始接觸到SM3算法的時(shí)候,由于本人數(shù)學(xué)功底一般,看著算法中各種字母,公式,符號(hào),直感覺暈頭轉(zhuǎn)向。為了完全理解SM3算法的過程,我也是惡補(bǔ)了一下自己的數(shù)學(xué)知識(shí),同時(shí),通過網(wǎng)上查找到的c語言代碼,一邊學(xué)習(xí)c語言的同時(shí)一邊通過代碼理解SM3算法的過程,同時(shí)學(xué)習(xí)其編程思路來為即將進(jìn)行的java程序設(shè)計(jì)做準(zhǔn)備。在對(duì)SM3算法java程序開發(fā)中,也遇到過不少難題,比如遇到一些之前沒有使用過的java類,這使得我必須通過反復(fù)查閱java文檔,并編寫測(cè)試程序來理解這些方法和類的作用。還有一些對(duì)內(nèi)存的操作,由于java沒有提供對(duì)應(yīng)的方法或接口,需要自己實(shí)現(xiàn)。這次的論文課題,也是對(duì)我數(shù)學(xué)理解能力和java編程能力的一次鍛煉。在“3.5程序存在的問題與改進(jìn)”章節(jié)中提到的String和BigInteger兩種實(shí)現(xiàn)方式。在設(shè)計(jì)最開始對(duì)“使用什么數(shù)據(jù)類型存儲(chǔ)消息?”這個(gè)問題無從下手時(shí),我通過java文檔查找到了這個(gè)類,發(fā)現(xiàn)能滿足我的需求,于是,就設(shè)計(jì)出了用BigInteger存儲(chǔ)的方式。事實(shí)上BigInteger方式才是我最先開發(fā)出來的方式,后來我再通過網(wǎng)上查閱資料,也發(fā)現(xiàn)一些其他的SM3算法java實(shí)現(xiàn),通過比較,我發(fā)現(xiàn)BigInteger方式的運(yùn)行速度確實(shí)太慢,于是,我學(xué)習(xí)了他人的思路,在原來的代碼架構(gòu)中進(jìn)行修改,這才有了String方式。當(dāng)然之后我也發(fā)現(xiàn)這種方式依然存在缺點(diǎn),于是將兩個(gè)版本的代碼都放入文中。既然兩種方式都有其缺點(diǎn),那有沒有更好的方式來實(shí)現(xiàn)?這個(gè)問題我也有思考過,比如使用byte[]數(shù)組或java集合類,又或者自己寫一個(gè)數(shù)據(jù)結(jié)構(gòu)。但由于本人的編程能力有限,這些想法也許會(huì)在以后我有更加深厚的功底后來實(shí)現(xiàn)。參考文獻(xiàn)[1]梁勇,戴開宇,Java語言程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)[M],機(jī)械工業(yè)出版社,2018.8[2]鄧建球等,基于改進(jìn)國(guó)密算法與區(qū)塊鏈的數(shù)據(jù)登記系統(tǒng)[J],兵器裝備工程學(xué)報(bào),2019.9[3]陳小松,密碼學(xué)及信息安全基礎(chǔ)[M].清華大學(xué)出版社.2018.10[4]周明華等,國(guó)密算法JSSE密碼套件的設(shè)計(jì)與實(shí)現(xiàn)[J],網(wǎng)絡(luò)安全技術(shù)與應(yīng)用,2019.7[5]YeYUAN等,針對(duì)一種基于SM3算法的消息驗(yàn)證碼的相關(guān)能量攻擊(英文)[J],F(xiàn)rontiersofInformationTechnology&ElectronicEngineering,2019.7[6]趙宇亮等,國(guó)家商用密碼算法綜述,2016電力行業(yè)信息化年會(huì)論文集,2016.9[7]申延召,SM3密碼雜湊算法分析[D],東華大學(xué),2013.1[8]李芳芳,國(guó)產(chǎn)密碼行業(yè)應(yīng)用的初步研究和探索[J],金融科技時(shí)代,2016.9[9]尹文琪,基于國(guó)密算法的SSLVPN的設(shè)計(jì)與實(shí)現(xiàn)[D],西安電子科技大學(xué),2015.12[10]田椒陵,SM3算法界面設(shè)計(jì)及安全性分析[J],網(wǎng)絡(luò)空間安全,2014.5[11]張長(zhǎng)澤,SM3算法在硬件加密模塊中的實(shí)現(xiàn)與應(yīng)用[J],信息通信,2019.9[12]姚鍵,國(guó)產(chǎn)商用密碼算法研究及性能分析[J],計(jì)算機(jī)應(yīng)用與軟件,2019.6[13]趙軍等,國(guó)產(chǎn)與國(guó)外常用雜湊算法的比較分析[J],網(wǎng)絡(luò)新媒體技術(shù),2018.9[14]劉麗敏等,商用密碼算法國(guó)際標(biāo)準(zhǔn)提案研究[J],信息技術(shù)與標(biāo)準(zhǔn)化,2018.5[15]鄒劍等,對(duì)縮減輪數(shù)SM3散列函數(shù)改進(jìn)的原像與偽碰撞攻擊[J],通信學(xué)報(bào),2018.1致謝這次畢業(yè)設(shè)計(jì)與畢業(yè)論文能夠順利完成,我衷心的感謝我的論文指導(dǎo)老師陳小松教授,在課堂上傳授了許多知識(shí)給我,私底下也是十分平易近人,總會(huì)耐心的解答我們的問題。在這次的畢業(yè)設(shè)計(jì)中,除了為我解答了許多學(xué)術(shù)上的難題,也在論文選題、查閱文獻(xiàn)、以及后期論文的修改與格式調(diào)整上給予了我許多幫助。同時(shí)我也要感謝我的其他老師,同學(xué),朋友和家人,他們陪伴我度過了大學(xué)的四年時(shí)光,在這臨近畢業(yè),即將步入社會(huì)的時(shí)期,也是我人生中的一個(gè)重要的關(guān)口,他們給了我許多心理上的安慰與動(dòng)力,給了我向上的動(dòng)力。再次對(duì)他們所有人致以真摯的感謝?。?!附錄SM3算法java程序完整代碼java實(shí)現(xiàn)sm3算法完整代碼:importjava.io.UnsupportedEncodingException;importjava.math.BigInteger;importjava.util.Scanner;publicclasssm3two{ //sm3核心方法,用String存儲(chǔ) privatestaticStringsm3(Stringm){ //調(diào)用填充函數(shù) Stringm2=padding(m); //調(diào)用分組函數(shù) int[][]m3=fenzu(m2); //調(diào)用壓縮函數(shù) int[]m4=diedaiyasuo(m3); Stringsm3hash=""; for(inti:m4){ sm3hash+=Integer.toHexString(i); } returnsm3hash; } //sm3主方法2,用bigInteger存儲(chǔ) privatestaticStringsm3two(Stringm){ //調(diào)用填充函數(shù) BigIntegerm2=padding2(m); //調(diào)用分組函數(shù) int[][]m3=fenzu2(m2); //調(diào)用壓縮函數(shù) int[]m4=diedaiyasuo(m3); Stringsm3hash=""; for(inti:m4){ sm3hash+=Integer.toHexString(i); } returnsm3hash; } //sm3填充函數(shù)2 privatestaticBigIntegerpadding2(Stringm){ BigIntegerm2=newBigInteger(m.getBytes()); //信息m的長(zhǎng)度,sm3能處理消息長(zhǎng)度最長(zhǎng)為2的64次方bit,因此需要用long類型存儲(chǔ) longmLen=m.length()*8; //f是需要填充的0的個(gè)數(shù) intf=(int)(512-(mLen+1+64)%512); //用位移填充:左移1位,填充1,再左移f+64位,填充信息長(zhǎng)度mlen m2=m2.shiftLeft(1).add(BigInteger.ONE).shiftLeft(f+64).add(BigInteger.valueOf(mLen)); returnm2; } //sm3填充函數(shù) privatestaticStringpadding(Stringm){ //信息m的長(zhǎng)度 longmLen=m.length()*8; //f是需要填充的0的個(gè)數(shù) intf=(int)(512-(mLen+1+64)%512); //以字符為單位填充1和0 //0x80等于一個(gè)1和7個(gè)0 m+=(char)0x80; for(inti=0;i<(f-7)/8;i++){ m+=(char)0x00; } m+=longToString(mLen); returnm; } //sm3分組函數(shù) privatestaticint[][]fenzu2(BigIntegerm2){ //num:分組數(shù),因java數(shù)組限制,分組數(shù)用32位的int存儲(chǔ) //bitLength()計(jì)算出的bit數(shù)不算符號(hào)位,所以要+1 intnum=(int)((m2.bitLength()+1)/512); //將bigInteger轉(zhuǎn)換成int[][16],每個(gè)int[16]存儲(chǔ)512bit, int[][]m3=newint[num][16]; //生成一個(gè)值為0xffffffff的BigInteger byte[]b={(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff,(byte)0xff}; BigIntegera=newBigInteger(b); //i:num-0 //j:0-16 for(inti=num;i>0;i--){ for(intj=0;j<16;j++){ //與0x0xffffffff相與,得到后32位,并進(jìn)行存儲(chǔ) m3[i-1][j]=m2.and(a).intValue(); //用位移分組:右移32位,左移32位,可以將后32位置0,再拿原數(shù)相減,得到后32位的數(shù)據(jù),存儲(chǔ) //m3[i-1][j]=m2.subtract(m2.shiftRight(32).shiftLeft(32)).intValue(); //將原數(shù)右移32位,去掉已存儲(chǔ)的部分。 m2=m2.shiftRight(32); } } returnm3; } //分組函數(shù) privatestaticint[][]fenzu(Stringm2){ //num:分組數(shù),因java數(shù)組限制,分組數(shù)用32位的int存儲(chǔ) intnum=m2.length()/64; //將String轉(zhuǎn)換成int[num][16],每個(gè)int[16]存儲(chǔ)512bit, int[][]m3=newint[num][16]; for(inti=0;i<num;i++){ m3[i]=StringToIntArray(m2.substring(i*64,i*64+64)); } returnm3; } //sm3迭代壓縮函數(shù) privatestaticint[]diedaiyasuo(int[][]m3){ int[]v={0x7380166f,0x4914b2b9,0x172442d7,0xda8a0600,0xa96f30bc,0x163138aa,0xe38dee4d,0xb0fb0e4e}; for(inti=0;i<m3.length;i++){ v=CF(v,m3[i]); } returnv; } //sm3消息拓展 privatestaticint[][]tuozhan(int[]tzm){ int[]w1=newint[68]; int[]w2=newint[64]; //前16位存儲(chǔ)的是信息m for(inti=0;i<16;i++){ w1[i]=tzm[15-i]; } //后52位是拓展 for(inti=16;i<68;i++){ w1[i]=p1(w1[i-16]^w1[i-9]^left(w1[i-3],15))^left(w1[i-13],7)^w1[i-6]; } for(inti=0;i<64;i++){ w2[i]=w1[i]^w1[i+4]; } //將拓展出來的兩個(gè)數(shù)組w1,w2用一個(gè)二維數(shù)組打包起來返回 int[][]w={w1,w2}; returnw; } //sm3消息拓展中用到的置換函數(shù)p1 privatestaticintp1(intx){ returnx^left(x,15)^left(x,23); } //sm3壓縮函數(shù)中用到的置換函數(shù)p privatestaticintp(intx){ returnx^left(x,9)^left(x,17); } //壓縮函數(shù)CF privatestaticint[]CF(int[]v,int[]b){ //常量tj intTj; //調(diào)用拓展函數(shù) int[][]w=tuozhan(b); //定義各個(gè)寄存器 intA=v[0]; intB=v[1]; intC=v[2]; intD=v[3]; intE=v[4]; intF=v[5]; intG=v[6]; intH=v[7]; intss1; intss2; inttt1; inttt2; for(inti=0;i<64;i++){ if(i>=0&&i<=15){ Tj=0x79cc4519; } else{ Tj=0x7a879d8a; } ss1=left(left(A,12)+E+left(Tj,i),7); ss2=ss1^left(A,12); tt1=FFj(A,B,C,i)+D+ss2+w[1][i]; tt2=GGj(E,F,G,i)+H+ss1+w[0][i]; D=C; C=left(B,9); B=A; A=tt1; H=G; G=left(F,19); F=E; E=p(tt2); } //得到新的v int[]v1={A,B,C,D,E,F,G,H}; for(inti=0;i<8;i++){ v1[i]=v1[i]^v[i]; } returnv1; } //32位循環(huán)左移 privatestaticintleft(inta,intb){ returna<<b|a>>>(32-b%32); } //布爾函數(shù) privatestaticintFFj(intx,inty,intz,inti){ if(i>=0&&i<=15){ returnx^y^z; } else{ return((x&y)|(x&z)|(y&z)); } } privatestaticintGGj(intx,inty,intz,inti){ if(i>=0&&i<=15){ returnx^y^z; } else{ return((x&y)|(~x&z)); } } //long類型轉(zhuǎn)String類型 privatestaticStringlongToString(longnum){ Strings=""; for(inti=7;i>=0;i--){ s+=(char)((num>>i*8)&0xff); } returns; } //將512bit的字符串轉(zhuǎn)換為int[16]數(shù)組 privatestaticint[]StringToIntArray(Strings){ byte[]b; int[]a=newint[16]; try{ b=s.getBytes("ISO-8859-1"); for(inti=0;i<16;i++){ //byte[4]轉(zhuǎn)int //&0xff是為了char變int時(shí)只取低八位,因?yàn)殚_頭為1的byte數(shù)變int時(shí)高位會(huì)自動(dòng)補(bǔ)1 a[15-i]=(int)((b[i*4]&0xff)<<24)|((b[i*4+1]&0xff)<<16)|((b[i*4+2]&0xff)<<8)|(b[i*4+3]&0xff); } }catch(UnsupportedEncodingExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returna; } publicstaticvoidmain(String[]args){ //TODOAuto-generatedmethodstub System.out.println("輸入需要加密的數(shù)據(jù):\n"); Scannerinput=newScanner(System.in); Stringm=input.nextLine(); //m=sm3two(m); m=sm3(m); System.out.println(m); } //測(cè)試填充函數(shù)publicstaticvoidtextpadding(){ Stringm=""; //填充函數(shù) Stringm2=padding(m); //打印填充結(jié)果的二進(jìn)制 System.out.println("填充結(jié)果為:"); for(inti=0;i<m2.length();i++){ Stringm3=Integer.toBinaryString((int)(m2.charAt(i))); //由于java會(huì)自動(dòng)略高位的0,所以手動(dòng)補(bǔ)齊 while(8-m3.length()>0){ m3='0'+m3; } System.out.print(""+m3); if((i+1)%8==0){ System.out.println(); } }}}

教你如何保護(hù)電腦一、每天關(guān)機(jī)前要做的清洗:

雙擊“我的電腦”—

—右鍵點(diǎn)C盤——點(diǎn)“屬性”——點(diǎn)“磁盤清理”——點(diǎn)“確定”——再點(diǎn)“是”——再點(diǎn)“確定”。清理過程中,您可看得到未經(jīng)您許可(您可點(diǎn)“查看文件”看,就知道了)進(jìn)來的“臨時(shí)文件”被清除了,盤的空間多了。對(duì)D,E,F(xiàn)盤也要用這法進(jìn)行。

二、隨時(shí)要進(jìn)行的清理

:

打開網(wǎng)頁(yè)——點(diǎn)最上面一排里的“工具”——點(diǎn)“Internet選項(xiàng)”——再點(diǎn)中間的“Internet臨時(shí)文件”中的“刪除文件”——再在“刪除所有脫機(jī)內(nèi)容”前的方框里打上勾——再點(diǎn)“確定”——清完后又點(diǎn)“確定”。這樣,可為打開網(wǎng)和空間提高速度。

三、一星期進(jìn)行的盤的垃圾清理

:

點(diǎn)“開始”——用鼠標(biāo)指著“所有程序”,再指著“附件”,再指著“系統(tǒng)工具”,再點(diǎn)“磁盤粹片整理程序”——點(diǎn)C盤,再點(diǎn)“碎片整理”(這需要很長(zhǎng)時(shí)間,最好在您去吃飯和沒用電腦時(shí)進(jìn)行。清理中您可看到您的盤里的狀況,可將清理前后對(duì)比一下)——在跳出“清理完成”后點(diǎn)“關(guān)閉”。按上述,對(duì)D,E,F(xiàn)盤分別進(jìn)行清理。

電腦系統(tǒng)越來越慢,怎么刪除臨時(shí)文件啊

1.關(guān)閉"休眠"

方法:打開[控制面板]→[電源選項(xiàng)]→[休眠],把"啟用休眠"前面的勾去掉

說明:休眠是系統(tǒng)長(zhǎng)時(shí)間一種待機(jī)狀態(tài),使您在長(zhǎng)時(shí)間離開電腦時(shí)保存操作狀態(tài),如果您不是經(jīng)常開著電腦到別處去的話,那就把它關(guān)了吧!

☆立即節(jié)省:256M

2.關(guān)閉"系統(tǒng)還原"

方法:打開[控制面板]→[系統(tǒng)]→[系統(tǒng)還原],把"在所有驅(qū)動(dòng)器上關(guān)閉系統(tǒng)還原'勾上

說明:系統(tǒng)還原是便于用戶誤操作或產(chǎn)生軟件問題時(shí)的一種挽救手段,可以回復(fù)到誤操作以前的狀態(tài).不建議初級(jí)用戶使用.當(dāng)然,它采用的是跟蹤手段,需要記錄大量信息,所消耗的資源也要很大的.

☆立即節(jié)省:數(shù)百M(fèi)

(根據(jù)還原點(diǎn)的多少而不同)

您也可以在不關(guān)閉系統(tǒng)還原的前提下,相應(yīng)的減少系統(tǒng)還原所占的磁盤空間,這只會(huì)減少可用還原點(diǎn)的數(shù)目,一般還原點(diǎn)有一兩個(gè)就夠了吧.

方法:...[系統(tǒng)還原]-選擇一個(gè)"可用驅(qū)動(dòng)器"-[設(shè)置]-調(diào)整"要使用的磁盤空間"

3.關(guān)閉"遠(yuǎn)程管理"

方法:打開[控制面板]→[系統(tǒng)]→[遠(yuǎn)程],把

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論