版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.08.20 |
前言
在這個信息爆炸的年代,特別是一些敏感的行業,比如金融業和銀行卡相關等等,這都對
app
的安全機制有更高的需求,很多大公司都有安全 部門,用于檢測自己產品的安全性,但是及時是這樣,安全問題仍然被不斷曝出,接下來幾篇我們主要說一下app
的安全機制。感興趣的看我上面幾篇。
1. APP安全機制(一)—— 幾種和安全性有關的情況
2. APP安全機制(二)—— 使用Reveal查看任意APP的UI
3. APP安全機制(三)—— Base64加密
4. APP安全機制(四)—— MD5加密
5. APP安全機制(五)—— 對稱加密
6. APP安全機制(六)—— 非對稱加密
SHA算法基本了解
下面我們先對SHA算法進行簡單的了解,以下部分內容來自百度百科。
SHA基本了解
SHA
也可以稱為安全哈希算法或者安全散列算法。
安全哈希算法(Secure Hash Algorithm)
主要適用于數字簽名標準(Digital Signature Standard DSS)
里面定義的數字簽名算法(Digital Signature Algorithm DSA)
。對于長度小于2^64位的消息,SHA1會產生一個160位的消息摘要。該算法經過加密專家多年來的發展和改進已日益完善,并被廣泛使用。該算法的思想是接收一段明文,然后以一種不可逆的方式將它轉換成一段(通常更?。┟芪?,也可以簡單的理解為取一串輸入碼(稱為預映射或信息),并把它們轉化為長度較短、位數固定的輸出序列即散列值(也稱為信息摘要或信息認證代碼)的過程。散列函數值可以說是對明文的一種“指紋”或是“摘要”所以對散列值的數字簽名就可以視為對此明文的數字簽名。
SHA是美國國家標準技術研究所發布的國家標準FIPS PUB 180
,最新的標準已經于2008年更新到FIPS PUB 180-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
二進制位的消息。
下面我們看一下SHA算法目前的家族成員。
散列算法
散列是信息的提煉,通常其長度要比信息小得多,且為一個固定長度。加密性強的散列一定是不可逆的,這就意味著通過散列結果,無法推出任何部分的原始信息。任何輸入信息的變化,哪怕僅一位,都將導致散列結果的明顯變化,這稱之為雪崩效應。散列還應該是防沖突的,即找不出具有相同散列結果的兩條信息。具有這些特性的散列結果就可以用于驗證信息是否被修改。
-
MD5(Message Digest Algorithm 5)
:是RSA數據安全公司開發的一種單向散列算法。 -
SHA(Secure Hash Algorithm)
:可以對任意長度的數據運算生成一個160位的數值。
在1993年,安全散列算法(SHA)由美國國家標準和技術協會(NIST)提出,并作為聯邦信息處理標準(FIPS PUB 180)
公布;1995年又發布了一個修訂版FIPS PUB 180-1
,通常稱之為SHA-1。SHA-1是基于MD4算法的,并且它的設計在很大程度上是模仿MD4的?,F在已成為公認的最安全的散列算法之一,并被廣泛使用。
SHA算法基本原理
下面我們就看一下SHA算法的基本原理。
SHA-1是一種數據加密算法,該算法的思想是接收一段明文,然后以一種不可逆的方式將它轉換成一段(通常更?。┟芪模部梢院唵蔚睦斫鉃槿∫淮斎氪a(稱為預映射或信息),并把它們轉化為長度較短、位數固定的輸出序列即散列值(也稱為信息摘要或信息認證代碼)的過程。
單向散列函數的安全性在于其產生散列值的操作過程具有較強的單向性。如果在輸入序列中嵌入密碼,那么任何人在不知道密碼的情況下都不能產生正確的散列值,從而保證了其安全性。SHA將輸入流按照每塊512位(64個字節)進行分塊,并產生20個字節的被稱為信息認證代碼或信息摘要的輸出。
該算法輸入報文的長度不限,產生的輸出是一個160位的報文摘要。輸入是按512 位的分組進行處理的。SHA-1是不可逆的、防沖突,并具有良好的雪崩效應。
通過散列算法可實現數字簽名實現,數字簽名的原理是將要傳送的明文通過一種函數運算(Hash)轉換成報文摘要(不同的明文對應不同的報文摘要),報文摘要加密后與明文一起傳送給接受方,接受方將接受的明文產生新的報文摘要與發送方的發來報文摘要解密比較,比較結果一致表示明文未被改動,如果不一致表示明文已被篡改。
MAC
(信息認證代碼)就是一個散列結果,其中部分輸入信息是密碼,只有知道這個密碼的參與者才能再次計算和驗證MAC碼的合法性。
SHA-1與MD5的比較
因為二者均由MD4導出,都是不可逆的,SHA-1和MD5彼此很相似,都是把輸入二進制串分成512位的塊,把二進制串的位數存儲在最后64位,二者之間填充為0,依次對每個塊進行一些列高深的數學運算,最后得到一個160位的二進制串。相應的,他們的強度和其他特性也是相似,但還有以下幾點不同:
- 對強行攻擊的安全性:最顯著和最重要的區別是SHA-1摘要比MD5摘要長32 位。使用強行技術,產生任何一個報文使其摘要等于給定報摘要的難度對MD5是2128數量級的操作,而對SHA-1則是2160數量級的操作。這樣,SHA-1對強行攻擊有更大的強度。
- 對密碼分析的安全性:由于MD5的設計,易受密碼分析的攻擊,SHA-1顯得不易受這樣的攻擊。
- 速度:在相同的硬件上,SHA-1的運行速度比MD5慢。
SHA-1停止計劃
2005年,密碼學家就證明SHA-1的破解速度比預期提高了2000倍,雖然破解仍然是極其困難和昂貴的,但隨著計算機變得越來越快和越來越廉價,SHA-1算法的安全性也逐年降低,已被密碼學家嚴重質疑,希望由安全強度更高的SHA-2替代它。
微軟第一個宣布了SHA-1棄用計劃,對于SSL證書和代碼簽名證書,微軟設定了不同的替換時間表。
- 所有Windows受信任的根證書頒發機構(CA)從2016年1月1日起必須停止簽發新的SHA-1簽名算法SSL證書和代碼簽名證書;
- 對于SSL證書,Windows將于2017年1月1日起停止支持SHA1證書。也就是說:任何在之前簽發的SHA-1證書必須替換成SHA-2證書;
- 對于代碼簽名證書,Windows將于2016年1月1日停止接受沒有時間戳的SHA-1簽名的代碼和SHA-1證書。也就是說,Windows仍然接受在2016年1月1日之前使用SHA-1簽名的已經加上RFC3161時間戳的代碼,直到微軟認為有可能出現SHA-1攻擊時。
SHA加密應用領域
計算MD5或sha-1加密哈希值的文件
當您將哈希算法應用于任意數量的如一個二進制文件的數據時結果將是一個哈?;?a target="_blank" rel="nofollow">消息摘要。此哈希具有固定的大小。MD5 是創建一個 128 位的哈希值的哈希算法。sha-1 是創建一個 160 位哈希值的哈希算法。
文件校驗和完整性驗證程序(Microsoft File Checksum Integrity Verifier,簡寫為FCIV)
實用程序可以用于計算 MD5
或 SHA-1
加密哈希值的文件。
SHA加密算法的工作過程
- 附加添湊位
對信息附加添湊位以便使它的長度等于448(模512)。即使信息已經達到需要的長度,也總是附加添湊位。因此,添湊位的長度范圍是1至512位。添湊位由單個“1”后跟必要數目的“0”組成。
- 附加長度
將一個長64位的數據塊附加到信息添湊位后,這個塊被視為一個無符號的64位整數,而且包含了信息在附加添湊位之前的初始長度。
前面兩步的結果是產生長度為512的整數倍的信息。用數字標記信息擴展后的512位分組序列Y0,Y1…YL-1
,于是擴展后信息的總長度是LX512位。同樣地,結果是16個32位字的整數倍。讓M0,M1…MN-1
代表結果信息字,N為16的整數倍,因此N=LX16。
- 初始化MD緩沖區
用一個160位的緩沖區存放哈希函數的中間結果和最終結果。這個緩沖區用5個32位寄存器(A,B,C,D,E)
表示。這些寄存器初始化為如下的16進制值(高8位在前):
A = 67452301
B = EFCDAB89
C = 98BADCFE
D = 10325476
E = C3D2E1FO
- 處理512位(16字)信息分組
SHA加密算法的核心是一個由80步處理組成的模塊,請注意每一層(round)的輸入是當前正處理的512位分組YQ和值為ABCDE的160位緩沖區,并在每一層修改緩沖區的內容。再每一層中用到了一個輔助常數K1,K1只用到4個不同的常數值??傊?,對分組YQ,SHA加密算法以YQ和摘要的中間值MDQ作為輸入。MDQ放在緩沖區ABCDE中,第80步的輸出與MDQ相加以產生MDQ+1。這個加法是利用模232加法,由緩沖區5個字中的每一個字單獨地與MDQ中相應的字相加完成。
- 輸出
當所有的L個512位分組處理完后,從L階段的輸出是160位的信息摘要。
SHA算法代碼實現
首先要注意的就是先要引入頭文件。
#import <CommonCrypto/CommonDigest.h>
下面還是直接看代碼。
1. JJSHAVC.m
#import "JJSHAVC.h"
#import <CommonCrypto/CommonDigest.h>
@interface JJSHAVC ()
@end
@implementation JJSHAVC
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
//SHA1加密
NSString *sha1Result = [self sha1EncryptWithStr:@"Celin"];
NSLog(@"sha1Result = %@", sha1Result);
//SHA224加密
NSString *sha224Result = [self sha224EncryptWithStr:@"Celin"];
NSLog(@"sha224Result = %@", sha224Result);
//SHA256加密
NSString *sha256Result = [self sha256EncryptWithStr:@"Celin"];
NSLog(@"sha256Result = %@", sha256Result);
//SHA384加密
NSString *sha384Result = [self sha384EncryptWithStr:@"Celin"];
NSLog(@"sha384Result = %@", sha384Result);
//SHA512加密
NSString *sha512Result = [self sha512EncryptWithStr:@"Celin"];
NSLog(@"sha512Result = %@", sha512Result);
}
#pragma mark - Object Private Function
//SHA1加密
- (NSString *)sha1EncryptWithStr:(NSString *)str
{
const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:str.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (CC_LONG)data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
//SHA224加密
- (NSString *)sha224EncryptWithStr:(NSString *)str
{
const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:str.length];
uint8_t digest[CC_SHA224_DIGEST_LENGTH];
CC_SHA224(data.bytes, (CC_LONG)data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA224_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA224_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
//SHA256加密
- (NSString *)sha256EncryptWithStr:(NSString *)str
{
const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:str.length];
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
//SHA384加密
- (NSString *)sha384EncryptWithStr:(NSString *)str
{
const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:str.length];
uint8_t digest[CC_SHA384_DIGEST_LENGTH];
CC_SHA384(data.bytes, (CC_LONG)data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA384_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA384_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
//SHA512加密
- (NSString *)sha512EncryptWithStr:(NSString *)str
{
const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:str.length];
uint8_t digest[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(data.bytes, (CC_LONG)data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
@end
下面看輸出結果
2017-08-21 14:13:55.643371+0800 JJOC[10671:5089584] sha1Result = aed363e0fba9c78464db73d4194e5f20c3f15297
2017-08-21 14:13:55.643609+0800 JJOC[10671:5089584] sha224Result = 9b7b9632f22d940c9e078624d2accd8e25e485d05f2416d28f128d74
2017-08-21 14:13:55.643764+0800 JJOC[10671:5089584] sha256Result = 7cc6c461453b280c0385f184bcc4cde59da4f912fa3710b9a694426c5e0ac9d9
2017-08-21 14:13:55.643959+0800 JJOC[10671:5089584] sha384Result = bfd50fa8b70884477e09af76e032176c032b5f1265962cef65e9c7d38ab1abc2ee8e5f43f4452f465fecdf0986cfaa2f
2017-08-21 14:13:55.644370+0800 JJOC[10671:5089584] sha512Result = d6976712a0b6cc70b88324928196fa35135e911351e9c7d8deeee6ae00c59449b557d061125ef41abab72a2db38d3f9cf1b9ae852f47c8091856f254d321ca72
從上面這個輸出結果,大家可以看出SHA家族不同成員算法輸出位數也是不一樣的。MD5輸出128bit,SHA1
輸出160bit
,SHA256
輸出256bit
,另外還有SHA244
、SHA512
分別輸出244bit
,512bit
,其實從他們的名字上也可以看出來輸出的位數。
大家可以用網上的SHA算法加密工具進行驗證,我這里只驗證SHA - 1的結果,下面看個圖示。
參考文章
后記
未完,待續~~