base64是一種基於64個可打印字符來表示二進制數據的表示方法.嚴格來講它只能算做一種編碼方式. Base64編碼之因此稱爲Base64,是由於其使用64個字符來對任意數據進行編碼,同理有Base3二、Base16編碼git
1, 因爲某些系統中只能使用ASCII字符。Base64就是用來將非ASCII字符的數據轉換成ASCII字符的一種方法. 2, 使用SMTP協議 (Simple Mail Transfer Protocol 簡單郵件傳輸協議)來發送郵件。由於這個協議是基於文本的協議,因此若是郵件中包含一幅圖片,咱們知道圖片的存儲格式是二進制數據(binary data),而非文本格式,咱們必須將二進制的數據編碼成文本格式,這時候Base 64 Encoding就派上用場了. 3, 經過base64將ASCII不可見字符轉換爲可見字符github
//編碼
- (NSString *)base64EncodedString;{
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
return [data base64EncodedStringWithOptions:0];
}
//解碼
- (NSString *)base64DecodedString{
NSData *data = [[NSData alloc]initWithBase64EncodedString:self options:0];
return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
}
複製代碼
MD5(消息摘要算法第五版)爲計算機安全領域普遍使用的一種散列函數,用以提供消息的完整性保護.算法
一、壓縮性:任意長度的數據,算出的MD5值長度都是固定的(32摘要)。 二、容易計算:從原數據計算出MD5值很容易。 三、抗修改性:對原數據進行任何改動,哪怕只修改1個字節,所獲得的MD5值都有很大區別。 四、強抗碰撞(難逆向):已知原數據和其MD5值,想找到一個具備相同MD5值的數據(即僞造數據)是很是困難的。安全
1, 數字簽名, 當咱們傳遞敏感信息時,能夠爲利用MD5+時間戳+鹽 爲消息添加惟一的數字簽名,當服務端得到數據後,用相同算法再次簽名.進行比較 若不一致 則數據遭到篡改. 2, 文件驗證, 咱們在下載文件時,因爲複雜的網絡環境,咱們下載的文件可能會有內容丟失或篡改的可能性.(例如咱們從服務器獲取的H5文件遭到了JS注入),利用MD5能夠有效防止這些事情的發生.bash
SHA-1:服務器
會產生一個160位的消息摘要,SHA-1的安全性在2000年之後已經不被大多數的加密場景所接受。2017年荷蘭密碼學研究小組CWI和Google正式宣佈攻破了SHA-1.網絡
SHA-2:app
2001年發佈,包括SHA-22四、SHA-25六、SHA-38四、SHA-5十二、SHA-512/22四、SHA-512/256。雖然至今還沒有出現對SHA-2有效的攻擊,它的算法跟SHA-1基本上仍然類似;所以有些人開始發展其餘替代的散列算法。函數
SHA-3:ui
2015年正式發佈,SHA-3並非要取代SHA-2,由於SHA-2目前並無出現明顯的弱點。因爲對MD5出現成功的破解,以及對SHA-0和SHA-1出現理論上破解的方法,NIST感受須要一個與以前算法不一樣的,可替換的加密散列算法,也就是如今的SHA-3。
這裏是對字符串的散列計算,若對文件則須要先讀取文件流再去散列. 須要: import <CommonCrypto/CommonDigest.h>
- (NSString *)md5String {
const char *str = self.UTF8String;
uint8_t buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, (CC_LONG)strlen(str), buffer);
return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
複製代碼
- (NSString *)sha1String {
const char *str = self.UTF8String;
uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(str, (CC_LONG)strlen(str), buffer);
return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
}
複製代碼
- (NSString *)sha256String {
const char *str = self.UTF8String;
uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(str, (CC_LONG)strlen(str), buffer);
return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
}
複製代碼
- (NSString *)sha512String {
const char *str = self.UTF8String;
uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(str, (CC_LONG)strlen(str), buffer);
return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
}
複製代碼
須要在github上下載keccak代碼包 :https://github.com/gvanas/KeccakCodePackage
這裏以MD5爲例:
#define FileHashDefaultChunkSizeForReadingData 4096
- (NSString *)fileMD5Hash {
//打開一個文件準備讀取
NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
if (fp == nil) {
//若路徑爲文件夾這種的(如:.framework)則會返回Null
return nil;
}
//建立MD5變量
CC_MD5_CTX hashCtx;
//初始化MD5變量
CC_MD5_Init(&hashCtx);
while (YES) {
@autoreleasepool {
//讀取文件指定長度數據,循環讀取避免一次加載到內存過大
NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
//準備MD5加密,將內容上傳
CC_MD5_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
if (data.length == 0) {
break;
}
}
}
//關閉文件
[fp closeFile];
//建立MD5結果緩衝區
uint8_t buffer[CC_MD5_DIGEST_LENGTH];
//將MD5結果寫進緩衝區
CC_MD5_Final(buffer, &hashCtx);
//原始數據轉換爲字符串
return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
- (NSString *)stringFromBytes:(uint8_t *)bytes length:(int)length {
NSMutableString *strM = [NSMutableString string];
for (int i = 0; i < length; i++) {
[strM appendFormat:@"%02x", bytes[i]];
}
return [strM copy];
}
複製代碼
對於其餘的算法文件加密方式也是這樣的,它們都是由CommonCrypto庫提供的.
HMAC是密鑰相關的哈希運算消息認證碼,HMAC運算利用哈希算法,以一個密鑰和一個消息爲輸入,生成一個消息摘要做爲輸出。 HMAC算法更象是一種加密算法,它引入了密鑰,其安全性已經不徹底依賴於所使用的HASH算法,有些相似對稱加密,可是是不可逆的那種~. 以MD5爲例:
- (NSString *)hmacMD5StringWithKey:(NSString *)key {
const char *keyData = key.UTF8String;
const char *strData = self.UTF8String;
//切換其餘散列函數替換這裏(如:CC_SHA256_DIGEST_LENGTH)
uint8_t buffer[CC_MD5_DIGEST_LENGTH];
//切換其餘散列函數替換這裏(如:kCCHmacAlgSHA256)
CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
//切換其餘散列函數替換這裏(如:CC_SHA256_DIGEST_LENGTH)
return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
複製代碼
美國國家標準技術研究所在2001年發佈了高級加密標準(AES)。 AES是基於數據塊的加密方式, 即,每次處理的數據是一塊(16字節),當數據不是16字節的倍數時填充, 這就是所謂的分組密碼(區別於基於比特位的流密碼),16字節是分組長度。
AES在軟件及硬件上都能快速地加解密,相對來講較易於實現,
在使用AES時要配置幾個加密參數,只有都一致才能使 客戶端與服務端 結果一致.
key常見的長度有三種:12八、192和256 bits
AES屬於塊加密(Block Cipher),塊加密中有CBC、ECB、CTR、OFB、CFB等幾種工做模式.
是一種基礎的加密方式,AES默認沒收,密文被分割成分組長度相等的塊(不足補齊),而後單獨一個個加密,一個個輸出組成密文.
這個模式是鏈式的,後一塊須要前一塊作基礎,第一塊須要一個須要初始化向量IV作基礎. 相同的輸入產生不一樣的輸出. 能看到的數據是「明文+IV」或「明文+前一個密文」的亂碼,因此能隱藏明文.
因此加密/解密 須要: 明文/密文 + 祕鑰 + 初始向量參數
由於AES的算法是把明文分組再處理的,他要求每一個分組(16字節)是「滿」的,即明文長度必須被16字節整除.
因此明文最後不足的16字節的要先進行數據填充,把不足16字節的最後一組補成16字節.
CFB,OFB和CTR模式因爲與key進行加密操做的是上一塊加密後的密文,所以不須要對最後一段明文進行填充. 在iOS SDK中提供了PKCS7Padding.
正如在CBC模式哪裏介紹的,開始加密時,從哪裏開始就是初始向量,如不設置則系統默認爲0;
NSString *const kInitVector = @"初始向量";
size_t const kKeySize = kCCKeySizeAES256;//祕鑰長度
+ (NSData *)encryptAES:(NSData *)content key:(NSString *)key {
NSData *contentData = content;
NSUInteger dataLength = contentData.length;
//設置加密祕鑰,因C字符串結束符爲'\0' 因此大小+1
char keyPtr[kKeySize + 1];
memset(keyPtr, 0, sizeof(keyPtr));
//應確保大小小於等於16個字節.
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
//密文長度 = 明文長度+祕鑰長度
size_t encryptSize = dataLength + kCCBlockSizeAES128;
void *encryptedBytes = malloc(encryptSize);
//密文接受指針
size_t actualOutSize = 0;
//初始向量
NSData *initVector = [kInitVector dataUsingEncoding:NSUTF8StringEncoding];
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, //是加密仍是解密
kCCAlgorithmAES, //加密/解密方式
kCCOptionPKCS7Padding, //PKCS7Padding
keyPtr, //祕鑰
kKeySize, //祕鑰大小
initVector.bytes, //初始向量
contentData.bytes, //明文/密文
dataLength, //明文/密文大小
encryptedBytes, //結果: 密文/明文緩衝區
encryptSize, //結果: 密文/明文大小
&actualOutSize); //結果指針
if (cryptStatus == kCCSuccess) {
// 成功
return [NSData dataWithBytesNoCopy:encryptedBytes length:actualOutSize];
}
//釋放
free(encryptedBytes);
return nil;
}
複製代碼
任意給定正整數n,請問在小於等於n的正整數之中,有多少個與n構成互質的數.計算這個值的函數爲 歐拉函數: 如: φ(8) = 4.
若n爲質數 則: φ(n) = n-1 原理3 若n爲質數的n次方 則: φ(p^k) = p^k - p^(k-1) 若n爲兩個互質整數之積 則: φ(p1 * p2) = φ(p1)φ(p2) 原理1 若正整數 a和n互質 則: a^φ(n) 被n除的餘數爲1 則: a^φ(n) %n=1 歐拉定理 若正整數a和質數p互質 則: a^p-1 %p=1 //費馬小定理 若正整數a和n互質,則必定能夠找到正整數b 使: ab%n=1, b爲a的模反元素. 原理2
1, 隨機生成兩個不等質數p和q 如 p=61 q=53
2, 求出pq乘積n n=p * q= 61*53=3233.
這裏n的長度即爲,祕鑰長度,如3233爲二進制12位,RSA祕鑰通常爲1024位.
3, 計算φ(n)
根據 原理1 φ(n) = φ(p)φ(q) = (p-1)(q-1) = 3120
4, 隨機選擇一個整數e 條件爲 1<e<φ(n) 且 e與φ(n)互質
假如選擇 17
5, 獲取e對於φ(n)的模反元素d
ed%φ(n)=1 ---> ed -1 = kφ(n) ---> 17d + 3120k = 1 經過擴展歐幾里德算法 可獲得一組整數解 d=2753 k=-15
6, 這裏 n和e 爲公鑰 n和d 爲私鑰
對明文信息m 加密 注意:m爲正整數,且m須小於n
m^e % n = c
這裏的c就是加密後獲得的密文 65^17 % 3233 = 2790 這裏2790就是加密後的密文
解密規則爲: c^d %n = m
由於加密過程爲: m^e % n = c ---> c = m^e - kn 若想證實解密規則成立 則等同於證實 (m^e - kn)^d % n = m 成立
(m^e - kn)^d % n = m ---> m^ed % n = m
因爲在製做公私鑰 的第5步 因此:
ed%φ(n)=1 ---> ed = hφ(n)+1
將ed代入須證實公式:
m^ed % n = m ---> m^hφ(n)+1 % n = m
m^hφ(n)+1 % n = m ---> ((m^φ(n))^h * m) % n = m
因爲歐拉定理 m^φ(n) %n=1可得 ((m^φ(n))^h * m) % n = m ---> (1^h * m) % n = m 則解密公式成立
由於製做公私鑰 的第1步 n = p * q
由於加密方法 m^e % n = c , 且因 m<n(這裏是在製做時要求的) 因此 c確定不爲0 由此可得 m 與 n 不爲互質關係.
因爲 n = pq 且 pq互質 因此 n有且只有 p q 兩個因子. 然而 m n有公因子 因此 m n 的公因子 一定爲 q或p的整數倍. 因此 m = kp 或 kq
以 m=kp爲例 由於上面描述的關係 m<n , m n不互質, n = qp 因此 k與q互質 ---> m與q互質
由歐拉定理得:
m^φ(q) % q = 1
---> 因爲q爲質數 ---> m^q-1 % q = 1
--> (kp)^q-1 % q = 1
由於 k與q互質 p與q互質 --> ((kp)^q-1 * kp)%q = kp
進一步能夠肯定該式成立: (((kp)^h(p-1)(q-1)) * kp)%q = kp
由於p爲質數 h爲任一整數
由原理1和原理3(((kp)^h(p-1)(q-1)) * kp)%q = kp
---> (kp)^hφ(n)+1 %q=kp
因爲 ed%φ(n)=1,且m=kp 因此將h匹配爲合適的值得 (kp)^ed %q = kp
---> (m)^ed = tq +m
t爲整數.
兩側同除m得: (m)^ed-1 = tq/m +1
因爲ed爲整數,m爲整數 故tq/m爲整數. 因q與m互質 因此t爲m的整數倍 --> t = yp ---> m^ed = yn+m
---> m^ed % n = m
因爲加密方式 m^e % n = c
---> c^d % n = m
若想破解RSA 則須要在已知 n e的狀況下 求 d 由於
由於 ed%φ(n)=1 因此需知道 φ(n) 由於 φ(n) = (p-1)(q-1) 因此需求得 qp 由於 qp=n 因此得將n因式分解
而因式分解是十分困難的 特別是對於 特大整數的因式分解. 因爲 名文m 需小於 祕鑰長度n 因此經常使用來加密 對稱加密的祕鑰.
參考連接:iOS中使用RSA加密 在iOS中使用RSA加密解密 須要使用到**.der** 和 .p12 後綴格式文件.
.p12 格式文件是用來加密的 私鑰 .der 格式文件用來解密的 公鑰
添加動態庫 Security.framework
具體實現太長,我彙總了一個類 github連接 感興趣能夠下下來看看 若是幫到你 點個Star鼓勵一蛤~ 本文地址 博客地址