國鑰SM3的Java程序實現(xiàn)_第1頁
國鑰SM3的Java程序實現(xiàn)_第2頁
國鑰SM3的Java程序實現(xiàn)_第3頁
國鑰SM3的Java程序實現(xiàn)_第4頁
國鑰SM3的Java程序實現(xiàn)_第5頁
已閱讀5頁,還剩47頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

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

教你如何保護電腦一、每天關機前要做的清洗:

雙擊“我的電腦”—

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

二、隨時要進行的清理

:

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

三、一星期進行的盤的垃圾清理

:

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

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

1.關閉"休眠"

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

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

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

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

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

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

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

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

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

方法:...[系統(tǒng)還原]-選擇一個"可用驅動器"-[設置]-調整"要使用的磁盤空間"

3.關閉"遠程管理"

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

溫馨提示

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

評論

0/150

提交評論