版本記錄
| 版本號(hào) | 時(shí)間 |
|---|---|
| V1.0 | 2017.08.20 |
前言
在這個(gè)信息爆炸的年代,特別是一些敏感的行業(yè),比如金融業(yè)和銀行卡相關(guān)等等,這都對
app的安全機(jī)制有更高的需求,很多大公司都有安全 部門,用于檢測自己產(chǎn)品的安全性,但是及時(shí)是這樣,安全問題仍然被不斷曝出,接下來幾篇我們主要說一下app的安全機(jī)制。感興趣的看我上面幾篇。
1. APP安全機(jī)制(一)—— 幾種和安全性有關(guān)的情況
2. APP安全機(jī)制(二)—— 使用Reveal查看任意APP的UI
3. APP安全機(jī)制(三)—— Base64加密
4. APP安全機(jī)制(四)—— MD5加密
5. APP安全機(jī)制(五)—— 對稱加密
6. APP安全機(jī)制(六)—— 非對稱加密
SHA算法基本了解
下面我們先對SHA算法進(jìn)行簡單的了解,以下部分內(nèi)容來自百度百科。
SHA基本了解
SHA也可以稱為安全哈希算法或者安全散列算法。
安全哈希算法(Secure Hash Algorithm)主要適用于數(shù)字簽名標(biāo)準(zhǔn)(Digital Signature Standard DSS)里面定義的數(shù)字簽名算法(Digital Signature Algorithm DSA)。對于長度小于2^64位的消息,SHA1會(huì)產(chǎn)生一個(gè)160位的消息摘要。該算法經(jīng)過加密專家多年來的發(fā)展和改進(jìn)已日益完善,并被廣泛使用。該算法的思想是接收一段明文,然后以一種不可逆的方式將它轉(zhuǎn)換成一段(通常更?。┟芪?,也可以簡單的理解為取一串輸入碼(稱為預(yù)映射或信息),并把它們轉(zhuǎn)化為長度較短、位數(shù)固定的輸出序列即散列值(也稱為信息摘要或信息認(rèn)證代碼)的過程。散列函數(shù)值可以說是對明文的一種“指紋”或是“摘要”所以對散列值的數(shù)字簽名就可以視為對此明文的數(shù)字簽名。
SHA是美國國家標(biāo)準(zhǔn)技術(shù)研究所發(fā)布的國家標(biāo)準(zhǔn)FIPS PUB 180,最新的標(biāo)準(zhǔn)已經(jīng)于2008年更新到FIPS PUB 180-3。其中規(guī)定了SHA-1,SHA-224,SHA-256,SHA-384,SHA-512這幾種單向散列算法。SHA-1,SHA-224和SHA-256適用于長度不超過2^64二進(jìn)制位的消息。SHA-384和SHA-512適用于長度不超過2^128二進(jìn)制位的消息。
下面我們看一下SHA算法目前的家族成員。

散列算法
散列是信息的提煉,通常其長度要比信息小得多,且為一個(gè)固定長度。加密性強(qiáng)的散列一定是不可逆的,這就意味著通過散列結(jié)果,無法推出任何部分的原始信息。任何輸入信息的變化,哪怕僅一位,都將導(dǎo)致散列結(jié)果的明顯變化,這稱之為雪崩效應(yīng)。散列還應(yīng)該是防沖突的,即找不出具有相同散列結(jié)果的兩條信息。具有這些特性的散列結(jié)果就可以用于驗(yàn)證信息是否被修改。
單向散列函數(shù)一般用于產(chǎn)生消息摘要,密鑰加密等,常見的有:
-
MD5(Message Digest Algorithm 5):是RSA數(shù)據(jù)安全公司開發(fā)的一種單向散列算法。 -
SHA(Secure Hash Algorithm):可以對任意長度的數(shù)據(jù)運(yùn)算生成一個(gè)160位的數(shù)值。
在1993年,安全散列算法(SHA)由美國國家標(biāo)準(zhǔn)和技術(shù)協(xié)會(huì)(NIST)提出,并作為聯(lián)邦信息處理標(biāo)準(zhǔn)(FIPS PUB 180)公布;1995年又發(fā)布了一個(gè)修訂版FIPS PUB 180-1,通常稱之為SHA-1。SHA-1是基于MD4算法的,并且它的設(shè)計(jì)在很大程度上是模仿MD4的。現(xiàn)在已成為公認(rèn)的最安全的散列算法之一,并被廣泛使用。
SHA算法基本原理
下面我們就看一下SHA算法的基本原理。
SHA-1是一種數(shù)據(jù)加密算法,該算法的思想是接收一段明文,然后以一種不可逆的方式將它轉(zhuǎn)換成一段(通常更?。┟芪?,也可以簡單的理解為取一串輸入碼(稱為預(yù)映射或信息),并把它們轉(zhuǎn)化為長度較短、位數(shù)固定的輸出序列即散列值(也稱為信息摘要或信息認(rèn)證代碼)的過程。
單向散列函數(shù)的安全性在于其產(chǎn)生散列值的操作過程具有較強(qiáng)的單向性。如果在輸入序列中嵌入密碼,那么任何人在不知道密碼的情況下都不能產(chǎn)生正確的散列值,從而保證了其安全性。SHA將輸入流按照每塊512位(64個(gè)字節(jié))進(jìn)行分塊,并產(chǎn)生20個(gè)字節(jié)的被稱為信息認(rèn)證代碼或信息摘要的輸出。
該算法輸入報(bào)文的長度不限,產(chǎn)生的輸出是一個(gè)160位的報(bào)文摘要。輸入是按512 位的分組進(jìn)行處理的。SHA-1是不可逆的、防沖突,并具有良好的雪崩效應(yīng)。
通過散列算法可實(shí)現(xiàn)數(shù)字簽名實(shí)現(xiàn),數(shù)字簽名的原理是將要傳送的明文通過一種函數(shù)運(yùn)算(Hash)轉(zhuǎn)換成報(bào)文摘要(不同的明文對應(yīng)不同的報(bào)文摘要),報(bào)文摘要加密后與明文一起傳送給接受方,接受方將接受的明文產(chǎn)生新的報(bào)文摘要與發(fā)送方的發(fā)來報(bào)文摘要解密比較,比較結(jié)果一致表示明文未被改動(dòng),如果不一致表示明文已被篡改。
MAC(信息認(rèn)證代碼)就是一個(gè)散列結(jié)果,其中部分輸入信息是密碼,只有知道這個(gè)密碼的參與者才能再次計(jì)算和驗(yàn)證MAC碼的合法性。
SHA-1與MD5的比較
因?yàn)槎呔蒑D4導(dǎo)出,都是不可逆的,SHA-1和MD5彼此很相似,都是把輸入二進(jìn)制串分成512位的塊,把二進(jìn)制串的位數(shù)存儲(chǔ)在最后64位,二者之間填充為0,依次對每個(gè)塊進(jìn)行一些列高深的數(shù)學(xué)運(yùn)算,最后得到一個(gè)160位的二進(jìn)制串。相應(yīng)的,他們的強(qiáng)度和其他特性也是相似,但還有以下幾點(diǎn)不同:
- 對強(qiáng)行攻擊的安全性:最顯著和最重要的區(qū)別是SHA-1摘要比MD5摘要長32 位。使用強(qiáng)行技術(shù),產(chǎn)生任何一個(gè)報(bào)文使其摘要等于給定報(bào)摘要的難度對MD5是2128數(shù)量級的操作,而對SHA-1則是2160數(shù)量級的操作。這樣,SHA-1對強(qiáng)行攻擊有更大的強(qiáng)度。
- 對密碼分析的安全性:由于MD5的設(shè)計(jì),易受密碼分析的攻擊,SHA-1顯得不易受這樣的攻擊。
- 速度:在相同的硬件上,SHA-1的運(yùn)行速度比MD5慢。
SHA-1停止計(jì)劃
2005年,密碼學(xué)家就證明SHA-1的破解速度比預(yù)期提高了2000倍,雖然破解仍然是極其困難和昂貴的,但隨著計(jì)算機(jī)變得越來越快和越來越廉價(jià),SHA-1算法的安全性也逐年降低,已被密碼學(xué)家嚴(yán)重質(zhì)疑,希望由安全強(qiáng)度更高的SHA-2替代它。
微軟第一個(gè)宣布了SHA-1棄用計(jì)劃,對于SSL證書和代碼簽名證書,微軟設(shè)定了不同的替換時(shí)間表。
- 所有Windows受信任的根證書頒發(fā)機(jī)構(gòu)(CA)從2016年1月1日起必須停止簽發(fā)新的SHA-1簽名算法SSL證書和代碼簽名證書;
- 對于SSL證書,Windows將于2017年1月1日起停止支持SHA1證書。也就是說:任何在之前簽發(fā)的SHA-1證書必須替換成SHA-2證書;
- 對于代碼簽名證書,Windows將于2016年1月1日停止接受沒有時(shí)間戳的SHA-1簽名的代碼和SHA-1證書。也就是說,Windows仍然接受在2016年1月1日之前使用SHA-1簽名的已經(jīng)加上RFC3161時(shí)間戳的代碼,直到微軟認(rèn)為有可能出現(xiàn)SHA-1攻擊時(shí)。
SHA加密應(yīng)用領(lǐng)域
計(jì)算MD5或sha-1加密哈希值的文件
當(dāng)您將哈希算法應(yīng)用于任意數(shù)量的如一個(gè)二進(jìn)制文件的數(shù)據(jù)時(shí)結(jié)果將是一個(gè)哈?;?a target="_blank" rel="nofollow">消息摘要。此哈希具有固定的大小。MD5 是創(chuàng)建一個(gè) 128 位的哈希值的哈希算法。sha-1 是創(chuàng)建一個(gè) 160 位哈希值的哈希算法。
文件校驗(yàn)和完整性驗(yàn)證程序(Microsoft File Checksum Integrity Verifier,簡寫為FCIV) 實(shí)用程序可以用于計(jì)算 MD5 或 SHA-1 加密哈希值的文件。
SHA加密算法的工作過程
- 附加添湊位
對信息附加添湊位以便使它的長度等于448(模512)。即使信息已經(jīng)達(dá)到需要的長度,也總是附加添湊位。因此,添湊位的長度范圍是1至512位。添湊位由單個(gè)“1”后跟必要數(shù)目的“0”組成。
- 附加長度
將一個(gè)長64位的數(shù)據(jù)塊附加到信息添湊位后,這個(gè)塊被視為一個(gè)無符號(hào)的64位整數(shù),而且包含了信息在附加添湊位之前的初始長度。
前面兩步的結(jié)果是產(chǎn)生長度為512的整數(shù)倍的信息。用數(shù)字標(biāo)記信息擴(kuò)展后的512位分組序列Y0,Y1…YL-1,于是擴(kuò)展后信息的總長度是LX512位。同樣地,結(jié)果是16個(gè)32位字的整數(shù)倍。讓M0,M1…MN-1代表結(jié)果信息字,N為16的整數(shù)倍,因此N=LX16。
- 初始化MD緩沖區(qū)
用一個(gè)160位的緩沖區(qū)存放哈希函數(shù)的中間結(jié)果和最終結(jié)果。這個(gè)緩沖區(qū)用5個(gè)32位寄存器(A,B,C,D,E)表示。這些寄存器初始化為如下的16進(jìn)制值(高8位在前):
A = 67452301
B = EFCDAB89
C = 98BADCFE
D = 10325476
E = C3D2E1FO
- 處理512位(16字)信息分組
SHA加密算法的核心是一個(gè)由80步處理組成的模塊,請注意每一層(round)的輸入是當(dāng)前正處理的512位分組YQ和值為ABCDE的160位緩沖區(qū),并在每一層修改緩沖區(qū)的內(nèi)容。再每一層中用到了一個(gè)輔助常數(shù)K1,K1只用到4個(gè)不同的常數(shù)值。總之,對分組YQ,SHA加密算法以YQ和摘要的中間值MDQ作為輸入。MDQ放在緩沖區(qū)ABCDE中,第80步的輸出與MDQ相加以產(chǎn)生MDQ+1。這個(gè)加法是利用模232加法,由緩沖區(qū)5個(gè)字中的每一個(gè)字單獨(dú)地與MDQ中相應(yīng)的字相加完成。
- 輸出
當(dāng)所有的L個(gè)512位分組處理完后,從L階段的輸出是160位的信息摘要。
SHA算法代碼實(shí)現(xiàn)
首先要注意的就是先要引入頭文件。
#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
下面看輸出結(jié)果
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
從上面這個(gè)輸出結(jié)果,大家可以看出SHA家族不同成員算法輸出位數(shù)也是不一樣的。MD5輸出128bit,SHA1輸出160bit,SHA256輸出256bit,另外還有SHA244、SHA512分別輸出244bit,512bit,其實(shí)從他們的名字上也可以看出來輸出的位數(shù)。
大家可以用網(wǎng)上的SHA算法加密工具進(jìn)行驗(yàn)證,我這里只驗(yàn)證SHA - 1的結(jié)果,下面看個(gè)圖示。

參考文章
后記
未完,待續(xù)~~
