簡介
基本信息
安全散列算法SHA(SecureHashAlgorithm,SHA)是美國國家標準技術研究所發布的國家標準FIPSPUB180,最新的標準已經於2008年更新到FIPSPUB180-3。其中規定了SHA-1,SHA-224,SHA-256,SHA-384,和SHA-512這幾種單向散列算法。SHA-1,SHA-224和SHA-256適用於長度不超過2^64二進制位的訊息。SHA-384和SHA-512適用於長度不超過2^128二進制位的訊息。散列算法
散列是信息的提煉,通常其長度要比信息小得多,且為一個固定長度。加密性強的散列一定是不可逆的,這就意味著通過散列結果,無法推出任何部分的原始信息。任何輸入信息的變化,哪怕僅一位,都將導致散列結果的明顯變化,這稱之為雪崩效應。散列還應該是防衝突的,即找不出具有相同散列結果的兩條信息。具有這些特性的散列結果就可以用於驗證信息是否被修改。單向散列函式一般用於產生訊息摘要,密鑰加密等,常見的有:
lMD5(MessageDigestAlgorithm5):是RSA數據安全公司開發的一種單向散列算法。
lSHA(SecureHashAlgorithm):可以對任意長度的數據運算生成一個160位的數值;
SHA-1
在1993年,安全散列算法(SHA)由美國國家標準和技術協會(NIST)提出,並作為聯邦信息處理標準(FIPSPUB180)公布;1995年又發布了一個修訂版FIPSPUB180-1,通常稱之為SHA-1。SHA-1是基於MD4算法的,並且它的設計在很大程度上是模仿MD4的。現在已成為公認的最安全的散列算法之一,並被廣泛使用。
原理
SHA-1是一種數據加密算法,該算法的思想是接收一段明文,然後以一種不可逆的方式將它轉換成一段(通常更小)密文,也可以簡單的理解為取一串輸入碼(稱為預映射或信息),並把它們轉化為長度較短、位數固定的輸出序列即散列值(也稱為信息摘要或信息認證代碼)的過程。單向散列函式的安全性在於其產生散列值的操作過程具有較強的單向性。如果在輸入序列中嵌入密碼,那么任何人在不知道密碼的情況下都不能產生正確的散列值,從而保證了其安全性。SHA將輸入流按照每塊512位(64個位元組)進行分塊,並產生20個位元組的被稱為信息認證代碼或信息摘要的輸出。
該算法輸入報文的長度不限,產生的輸出是一個160位的報文摘要。輸入是按512位的分組進行處理的。SHA-1是不可逆的、防衝突,並具有良好的雪崩效應。
通過散列算法可實現數字簽名實現,數字簽名的原理是將要傳送的明文通過一種函式運算(Hash)轉換成報文摘要(不同的明文對應不同的報文摘要),報文摘要加密後與明文一起傳送給接受方,接受方將接受的明文產生新的報文摘要與傳送方的發來報文摘要解密比較,比較結果一致表示明文未被改動,如果不一致表示明文已被篡改。
MAC(信息認證代碼)就是一個散列結果,其中部分輸入信息是密碼,只有知道這個密碼的參與者才能再次計算和驗證MAC碼的合法性。
SHA-1與MD5的比較
因為二者均由MD4導出,SHA-1和MD5彼此很相似。相應的,他們的強度和其他特性也是相似,但還有以下幾點不同:
l對強行攻擊的安全性:最顯著和最重要的區別是SHA-1摘要比MD5摘要長32位。使用強行技術,產生任何一個報文使其摘要等於給定報摘要的難度對MD5是2^128數量級的操作,而對SHA-1則是2^160數量級的操作。這樣,SHA-1對強行攻擊有更大的強度。
l對密碼分析的安全性:由於MD5的設計,易受密碼分析的攻擊,SHA-1顯得不易受這樣的攻擊。
l速度:在相同的硬體上,SHA-1的運行速度比MD5慢。
算法套用
計算MD5或sha-1加密哈希值的檔案當您將哈希算法套用於任意數量的如一個二進制檔案的數據時結果將是一個哈希或訊息摘要。此哈希具有固定的大小。MD5是創建一個128位的哈希值的哈希算法。sha-1是創建一個160位哈希值的哈希算法。
檔案校驗和完整性驗證程式(FCⅣ)實用程式可以用於計算MD5或sha-1加密哈希值的檔案。若要計算在MD5和檔案的sha-1哈希值,請在命令行鍵入以下命令:
FCⅣ-md5-sha1path\filename.ext
例如對於計算Shdocvw.dll檔案%Systemroot%\System32資料夾中的MD5和sha-1哈希值,鍵入以下命令:
FCⅣ-md5-sha1c:\windows\system32\shdocvw.dll
SHA-1Java實現源碼
----------------------------------------------------------------------------------------------------
/*安全散列算法SHA(SecureHashAlgorithm,SHA)*/
publicclassSHA1{
privatefinalint[]abcde={0x67452301,0xefcdab89,0x98badcfe,
0x10325476,0xc3d2e1f0};
//摘要數據存儲數組
privateint[]digestInt=newint;
//計算過程中的臨時數據存儲數組
privateint[]tmpData=newint;
//計算sha-1摘要
privateintprocess_input_bytes(byte[]bytedata){
//初試化常量
System.arraycopy(abcde,0,digestInt,0,abcde.length);
//格式化輸入位元組數組,補10及長度數據
byte[]newbyte=byteArrayFormatData(bytedata);
//獲取數據摘要計算的數據單元個數
intMCount=newbyte.length/64;
//循環對每個數據單元進行摘要計算
for(intpos=0;pos<MCount;pos++){
//將每個單元的數據轉換成16個整型數據,並保存到tmpData的前16個數組元素中
for(intj=0;j<16;j++){
tmpData[j]=byteArrayToInt(newbyte,(pos*64)+(j*4));
摘要計算函式
encrypt();
return20;
//格式化輸入位元組數組格式
privatebyte[]byteArrayFormatData(byte[]bytedata){
//補0數量
intzeros=0;
//補位後總位數
intsize=0;
//原始數據長度
intn=bytedata.length;
//模64後的剩餘位數
intm=n%64;
//計算添加0的個數以及添加10後的總長度
if(m<56){
zeros=55-m;
size=n-m+64;
}elseif(m==56){
zeros=63;
size=n+8+64;
}else{
zeros=63-m+56;
size=(n+64)-m+64;
//補位後生成的新數組內容
byte[]newbyte=newbyte[size];
//複製數組的前面部分
System.arraycopy(bytedata,0,newbyte,0,n);
//獲得數組Append數據元素的位置
intl=n;
//補1操作
newbyte[l++]=(byte)0x80;
//補0操作
for(inti=0;i<zeros;i++){
newbyte[l++]=(byte)0x00;
//計算數據長度,補數據長度位共8位元組,長整型
longN=(long)n*8;
byteh8=(byte)(N&0xFF);
byteh7=(byte)((N>>8)&0xFF);
byteh6=(byte)((N>>16)&0xFF);
byteh5=(byte)((N>>24)&0xFF);
byteh4=(byte)((N>>32)&0xFF);
byteh3=(byte)((N>>40)&0xFF);
byteh2=(byte)((N>>48)&0xFF);
byteh1=(byte)(N>>56);
newbyte[l++]=h1;
newbyte[l++]=h2;
newbyte[l++]=h3;
newbyte[l++]=h4;
newbyte[l++]=h5;
newbyte[l++]=h6;
newbyte[l++]=h7;
newbyte[l++]=h8;
returnnewbyte;
privateintf1(intx,inty,intz){
return(x&y)|(~x&z);
privateintf2(intx,inty,intz){
returnx^y^z;
privateintf3(intx,inty,intz){
return(x&y)|(x&z)|(y&z);
privateintf4(intx,inty){
return(x<<y)|x>>>(32-y);
單元摘要計算函式
privatevoidencrypt(){
for(inti=16;i<=79;i++){
tmpData[i]=f4(tmpData[i-3]^tmpData[i-8]^tmpData[i-14]
^tmpData[i-16],1);
int[]tmpabcde=newint;
for(inti1=0;i1<tmpabcde.length;i1++){
tmpabcde[i1]=digestInt[i1];
for(intj=0;j<=19;j++){
inttmp=f4(tmpabcde,5)
+f1(tmpabcde,tmpabcde,tmpabcde)+tmpabcde
+tmpData[j]+0x5a827999;
tmpabcde=tmpabcde;
tmpabcde=tmpabcde;
tmpabcde=f4(tmpabcde,30);
tmpabcde=tmpabcde;
tmpabcde=tmp;
for(intk=20;k<=39;k++){
inttmp=f4(tmpabcde,5)
+f2(tmpabcde,tmpabcde,tmpabcde)+tmpabcde
+tmpData[k]+0x6ed9eba1;
tmpabcde=tmpabcde;
tmpabcde=tmpabcde;
tmpabcde=f4(tmpabcde,30);
tmpabcde=tmpabcde;
tmpabcde=tmp;
for(intl=40;l<=59;l++){
inttmp=f4(tmpabcde,5)
+f3(tmpabcde,tmpabcde,tmpabcde)+tmpabcde
+tmpData[l]+0x8f1bbcdc;
tmpabcde=tmpabcde;
tmpabcde=tmpabcde;
tmpabcde=f4(tmpabcde,30);
tmpabcde=tmpabcde;
tmpabcde=tmp;
for(intm=60;m<=79;m++){
inttmp=f4(tmpabcde,5)
+f2(tmpabcde,tmpabcde,tmpabcde)+tmpabcde
+tmpData[m]+0xca62c1d6;
tmpabcde=tmpabcde;
tmpabcde=tmpabcde;
tmpabcde=f4(tmpabcde,30);
tmpabcde=tmpabcde;
tmpabcde=tmp;
for(inti2=0;i2<tmpabcde.length;i2++){
digestInt[i2]=digestInt[i2]+tmpabcde[i2];
for(intn=0;n<tmpData.length;n++){
tmpData[n]=0;
//4位元組數組轉換為整數
privateintbyteArrayToInt(byte[]bytedata,inti){
return((bytedata[i]&0xff)<<24)|((bytedata[i+1]&0xff)<<16)
|((bytedata[i+2]&0xff)<<8)|(bytedata[i+3]&0xff);
//整數轉換為4位元組數組
privatevoidintToByteArray(intintValue,byte[]byteData,inti){
byteData[i]=(byte)(intValue>>>24);
byteData[i+1]=(byte)(intValue>>>16);
byteData[i+2]=(byte)(intValue>>>8);
byteData[i+3]=(byte)intValue;
//將位元組轉換為十六進制字元串
privatestaticStringbyteToHexString(byteib){
char[]Digit={'0','1','2','3','4','5','6','7','8','9','A',
'B','C','D','E','F'};
char[]ob=newchar;
ob=Digit[(ib>>>4)&0X0F];
ob=Digit[ib&0X0F];
Strings=newString(ob);
returns;
//將位元組數組轉換為十六進制字元串
privatestaticStringbyteArrayToHexString(byte[]bytearray){
StringstrDigest="";
for(inti=0;i<bytearray.length;i++){
strDigest+=byteToHexString(bytearray[i]);
returnstrDigest;
//計算sha-1摘要,返回相應的位元組數組
publicbyte[]getDigestOfBytes(byte[]byteData){
process_input_bytes(byteData);
byte[]digest=newbyte;
for(inti=0;i<digestInt.length;i++)
intToByteArray(digestInt[i],digest,i*4);
returndigest;
//計算sha-1摘要,返回相應的十六進制字元串
publicStringgetDigestOfString(byte[]byteData){
returnbyteArrayToHexString(getDigestOfBytes(byteData));
測試
publicstaticvoidmain(String[]args){
Stringparam="wxzzs";
System.out.println("加密前:"+param);
Stringdigest=newSHA1().getDigestOfString(param.getBytes());
System.out.println("加密後:"+digest);
其他含義
定義
SHA雙方承擔,匯款費用承擔的一種方式。相關信息
SHA雙方承擔OUR匯款人承擔
BEN收款人承擔
城市三字代碼
SHA是上海的城市三字代碼,該代碼一般用於航空等業務
機場三字代碼
上海虹橋機場代碼