項目也快兩年了,項目這么長時間下來經歷了各種加解密算法,坑也踩過不少.現在把項目中使用過一些常用的加解密算法總結一下,有些也只是功能實現沒有深究里面的原理。
一、項目中主要使用到的的有
1.MD5
2.sha1
3.MD5大文件校驗
4.AES
5.RSA
6.大文件加解密和中間遇到的一些坑
</br>
這是所有算法的github庫 Demo地址 下載地址,
</br>
二、基礎篇主要內容<strong>md5,sha1,AES,RSA</strong>,下面會一個一個介紹。隨后會有一篇提升篇會講一下大文件的加解密<寫著寫著突然發現還是一篇寫一種方式好了...要不然會很長很長看起來也很亂
</br>
三、MD5加密算法
1.先從度娘那找一點名詞性解釋,MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于確保信息傳輸完整一致。是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現。將數據(如漢字)運算為另一固定長度值,是雜湊算法的基礎原理,MD5的前身有MD2、MD3和MD4。
MD5算法具有以下特點:
1、壓縮性:任意長度的數據,算出的MD5值長度都是固定的。
2、容易計算:從原數據計算出MD5值很容易。
3、抗修改性:對原數據進行任何改動,哪怕只修改1個字節,所得到的MD5值都有很大區別。
4、強抗碰撞:已知原數據和其MD5值,想找到一個具有相同MD5值的數據(即偽造數據)是非常困難的。
MD5的作用是讓大容量信息在用數字簽名軟件簽署私人密鑰前被"壓縮"成一種保密的格式(就是把一個任意長度的字節串變換成一定長的十六進制數字串)。除了MD5以外,其中比較有名的還有sha-1、RIPEMD以及Haval等。
2.因為md5加密算法只有加密算法沒有解密算法和易計算性,通常用作對用戶名和密碼加密之后再進行用戶登陸驗證的請求,避免用戶信息在傳輸途中被攔截解密。雖然看上去無懈可擊的樣子但是道高一尺魔高一丈,如果密碼設置過于簡單對于一下解密網站通過群舉比對還是很容易直接破解出來的。那有什么好的方法可以預防這些潛在的風險呢?
3.因為他的抗修改性和強抗碰撞,MD5又通常用作文件傳輸的完整性驗證的用途。
4.上述兩種使用場景的具體實現方式,算法的實現其實沒有什么難度,可以寫一個NSString的分類
包含頭文件 <code></br>#import <CommonCrypto/CommonDigest.h></code>
<code>#import "NSString+MD5.h"</code>
<code>- (NSString *)md5String{
const char *cstring = self.UTF8String;
unsigned char bytes[CC_MD5_DIGEST_LENGTH];
CC_MD5(cstring, (CC_LONG)strlen(cstring), bytes);
// 拼接
NSMutableString *md5String = [NSMutableString string];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[md5String appendFormat:@"%02x", bytes[i]];
}
return md5String;
}
</code>
5.2的遺留問題,如何避免被別人暴力破解
- 不推薦的方法
1.多次md5加密,別人群舉保存在數據庫中的也是有多次md5后的值,而且每天都在群舉字符串更新到數據庫中 國內的一個連接:http://pmd5.com,應該也是調用國外服務器的接口吧破解的吧。
2.讓用戶設置復雜的密碼組合或者保證密碼長度,一切和用戶過不去的設定都是反人類設計。用戶畢竟是上帝.但是簡單長度限制和字母數字的組合還是稍稍有點必要的。
</br> - 常用的方法
1.一般常用的方式是加Salt,就是在加密前自己生成一段長度較長的字符加載用戶填的密碼前后然后在Md5加密傳輸。這對于MD5群舉來說沒增添一個字符群舉的難度都是成幾何倍數增長,更別說你給他加個幾十個甚至上百個字符了。只要和服務端實現約定一個字符串兩邊同時做驗證就可以了。
2.其實我就知道這一種...,歡迎補充!
四、MD5大文件加密
1.文件的MD5加密是最常用的文件完整性驗證的算法.如果下載完成的文件的MD5值和原先的不一樣,要么下載的文件不完整 要么,中間被別人串改。15年xcode被別人下了木馬,很多大的互聯網公司都接連中招,就是在原先的xcode安裝文件植入了木馬之后再提供額外鏈接給別人下載。很多開發者也沒有去做MD5驗證。
2.因為我們項目中進場下載一些較大的文件,少則30 50MB,多則3 400MB的,當時服務端直接將文件加載到內存然后整體MD5加密,然后把值給我讓我去做驗證....我當時的內心是奔潰的...我們移動端內存小剛不住這么大的文件整體計算啊。最后和服務端討論了下然后分段加密,當然這也是我網上Copy來小改了下的...-_-#
重要的是約定一個分段的長度大小 我們定的是10MB一分段 就是參數:readingDataLength后傳的值:10 * 1024 * 1024
<code>
+(NSString)fileMD5withFilePath:(NSString)path readingDataLength:(NSInteger)dataLength
{
return (__bridge_transfer NSString *)FileMD5HashCreateWithPath((__bridge CFStringRef)path, dataLength);
}
CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,size_t chunkSizeForReadingData) {
// Declare needed variables
CFStringRef result = NULL;
CFReadStreamRef readStream = NULL;
// Get the file URL
CFURLRef fileURL =
CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
(CFStringRef)filePath,
kCFURLPOSIXPathStyle,
(Boolean)false);
if (!fileURL) goto done;
// Create and open the read stream
readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
(CFURLRef)fileURL);
if (!readStream) goto done;
bool didSucceed = (bool)CFReadStreamOpen(readStream);
if (!didSucceed) goto done;
// Initialize the hash object
CC_MD5_CTX hashObject;
CC_MD5_Init(&hashObject);
// Make sure chunkSizeForReadingData is valid
if (!chunkSizeForReadingData) {
chunkSizeForReadingData = chunkSizeForReadingData;
}
// Feed the data to the hash object
bool hasMoreData = true;
while (hasMoreData) {
uint8_t buffer[chunkSizeForReadingData];
CFIndex readBytesCount = CFReadStreamRead(readStream,(UInt8 *)buffer,(CFIndex)sizeof(buffer));
if (readBytesCount == -1) break;
if (readBytesCount == 0) {
hasMoreData = false;
continue;
}
CC_MD5_Update(&hashObject,(const void *)buffer,(CC_LONG)readBytesCount);
}
// Check if the read operation succeeded
didSucceed = !hasMoreData;
// Compute the hash digest
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5_Final(digest, &hashObject);
// Abort if the read operation failed
if (!didSucceed) goto done;
// Compute the string result
char hash[2 * sizeof(digest) + 1];
for (size_t i = 0; i < sizeof(digest); ++i) {
snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i]));
}
result = CFStringCreateWithCString(kCFAllocatorDefault,(const char *)hash,kCFStringEncodingUTF8);
done:
if (readStream) {
CFReadStreamClose(readStream);
CFRelease(readStream);
}
if (fileURL) {
CFRelease(fileURL);
}
return result;
}
</code>
五.Sha1算法
1.度娘說:安全哈希算法(Secure Hash Algorithm)主要適用于數字簽名標準 (Digital Signature Standard DSS)里面定義的數字簽名算法(Digital Signature Algorithm DSA)。對于長度小于2^64位的消息,SHA1會產生一個160位的消息摘要。當接收到消息的時候,這個消息摘要可以用來驗證數據的完整性。在傳輸的過程中,數據很可能會發生變化,那么這時候就會產生不同的消息摘要。 SHA1有如下特性:不可以從消息摘要中復原信息;兩個不同的消息不會產生同樣的消息摘要,(但會有1x10 ^ 48分之一的機率出現相同的消息摘要,一般使用時忽略)。
2.用途和MD5有很多相似的地方這里就不在累述了
3.實現
<code>#import <CommonCrypto/CommonDigest.h>
<code>- (NSString*)sha1
{
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData data = [NSData dataWithBytes:cstr length:self.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (int)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;
}
</code>