麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

RSA算法及其在iOS中的使用

2019-11-14 18:50:28
字體:
供稿:網(wǎng)友
因?yàn)轫?xiàng)目中需要傳輸用戶密碼,為了安全需要用RSA加密,所以就學(xué)習(xí)了下RSA加密在iOS中的應(yīng)用。
關(guān)于RSA的歷史及原理,下面的兩篇文章講的很清楚了:
 
簡(jiǎn)單來說,RSA建立在一個(gè)數(shù)學(xué)難題之上,就是大數(shù)分解:將兩個(gè)大素?cái)?shù)相乘十分容易,但是想要對(duì)其乘積進(jìn)行因式分解卻極其困難。至于為什么難,難在哪里那就是數(shù)學(xué)家的事了。。。
明白了這個(gè)就可以大致知道RSA的原理:非對(duì)稱加密
(1)乙方生成兩把密鑰(公鑰和私鑰)。公鑰是公開的,任何人都可以獲得,私鑰則是保密的。
(2)甲方獲取乙方的公鑰,然后用它對(duì)信息加密。
(3)乙方得到加密后的信息,用私鑰解密。
 
就好比有一套特殊的鎖和鑰匙,鎖是公開的,誰都可以拿這個(gè)鎖來鎖住他的東西,只有有鑰匙的人可以打開。
那么問題來了,既然鎖是公開的,難道不能通過鎖的結(jié)構(gòu)來倒推出鑰匙的形狀嗎?
答案是:不能!因?yàn)檫@個(gè)鎖是特殊的,它就特殊在很難倒推。(這個(gè)倒不是絕對(duì)的,也許將來某一天大數(shù)分解的數(shù)學(xué)難題解決了,這種算法就不安全了,詳見開頭鏈接)
 
我遇到的應(yīng)用場(chǎng)景是,客戶端有服務(wù)器的公鑰,客戶端要把用戶的密碼用公鑰加密上后上傳到服務(wù)器,服務(wù)器可以用私鑰解密。
所以客戶端要做的是,將需要加密的內(nèi)容用服務(wù)器給的公鑰進(jìn)行RSA加密。
iOS上并沒有直接的RSA加密API,所以需要折騰一下。
gitHub上的代碼大同小異,主要是三個(gè)方法(抄自https://github.com/ideawu/Objective-C-RSA
注意代碼里有個(gè)kSecPaddingPKCS1是作者寫死的,而我們的項(xiàng)目中需要傳kSecPaddingNone才行!!!
 
+ (NSData *)stripPublicKeyHeader:(NSData *)d_key{// Skip ASN.1 public key headerif (d_key == nil) return(nil);unsigned long len = [d_key length];if (!len) return(nil);unsigned char *c_key = (unsigned char *)[d_key bytes];unsigned int  idx    = 0;if (c_key[idx++] != 0x30) return(nil);if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;else idx++;// PKCS #1 rsaEncryption szOID_RSA_RSAstatic unsigned char seqiod[] ={ 0x30,   0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,0x01, 0x05, 0x00 };if (memcmp(&c_key[idx], seqiod, 15)) return(nil);idx += 15;if (c_key[idx++] != 0x03) return(nil);if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;else idx++;if (c_key[idx++] != '/0') return(nil);// Now make a new NSData from this bufferreturn([NSData dataWithBytes:&c_key[idx] length:len - idx]);}

 

 
 
+ (SecKeyRef)addPublicKey:(NSString *)key{NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];if(spos.location != NSNotFound && epos.location != NSNotFound){NSUInteger s = spos.location + spos.length;NSUInteger e = epos.location;NSRange range = NSMakeRange(s, e-s);key = [key substringWithRange:range];}key = [key stringByReplacingOccurrencesOfString:@"/r" withString:@""];key = [key stringByReplacingOccurrencesOfString:@"/n" withString:@""];key = [key stringByReplacingOccurrencesOfString:@"/t" withString:@""];key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];// This will be base64 encoded, decode it.NSData *data = base64_decode(key);data = [RSA stripPublicKeyHeader:data];if(!data){return nil;}NSString *tag = @"what_the_fuck_is_this";NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];// Delete any old lingering key with the same tagNSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];[publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];[publicKey setObject:d_tag forKey:(__bridge id)kSecAttrapplicationTag];SecItemDelete((__bridge CFDictionaryRef)publicKey);// Add persistent version of the key to system keychain[publicKey setObject:data forKey:(__bridge id)kSecValueData];[publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)kSecAttrKeyClass];[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];CFTypeRef persistKey = nil;OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);if (persistKey != nil){CFRelease(persistKey);}if ((status != noErr) && (status != errSecDuplicateItem)) {return nil;}[publicKey removeObjectForKey:(__bridge id)kSecValueData];[publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];// Now fetch the SecKeyRef version of the keySecKeyRef keyRef = nil;status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);if(status != noErr){return nil;}return keyRef;}

 

 
 1 + (NSString *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{ 2 if(!data || !pubKey){ 3 return nil; 4 } 5 SecKeyRef keyRef = [RSA addPublicKey:pubKey]; 6 if(!keyRef){ 7 return nil; 8 } 9 10 const uint8_t *srcbuf = (const uint8_t *)[data bytes];11 size_t srclen = (size_t)data.length;12 13 size_t outlen = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);14 if(srclen > outlen - 11){15 CFRelease(keyRef);16 return nil;17 }18 void *outbuf = malloc(outlen);19 20 OSStatus status = noErr;21 status = SecKeyEncrypt(keyRef,22   kSecPaddingNone, //原作者寫的是kSecPaddingPKCS1,經(jīng)春哥研究這里寫成kSecPaddingNone才符合我們使用23   srcbuf,24   srclen,25   outbuf,26   &outlen27   );28 NSString *ret = nil;29 if (status != 0) {30 //NSLog(@"SecKeyEncrypt fail. Error Code: %ld", status);31 }else{32 NSData *data = [NSData dataWithBytes:outbuf length:outlen];33 ret = base64_encode_data(data);34 }35 free(outbuf);36 CFRelease(keyRef);37 return ret;38 }

 

 
還有一篇文章可以參考:http://blog.iamzsx.me/show.html?id=155002
 
 
簽名機(jī)制
僅僅加密某個(gè)參數(shù)是不夠的,還需要保證請(qǐng)求沒有被篡改,所以簽名機(jī)制就很有必要。
比較簡(jiǎn)單和常用就是md5簽名:
拿到待簽名的字符串A(比如某個(gè)url),將其與服務(wù)器約定好的密鑰拼成新的字符串B,對(duì)B進(jìn)行MD5算法得到簽名C,
然后將C作為A的簽名一起發(fā)送到服務(wù)器。
服務(wù)器收到請(qǐng)求后,對(duì)A用與客戶端約定好的密鑰進(jìn)行相同的算法得到C’,如果C==C’,那就說明改請(qǐng)求沒有被篡改過,
否則驗(yàn)證不通過
 
當(dāng)然也可以做RSA簽名
這個(gè)要比MD5簽名要稍微麻煩一點(diǎn),因?yàn)樾枰蛻舳松晒€私鑰對(duì),基本流程也和MD5簽名一樣
拿到待簽名的字符串A(比如某個(gè)url),將其用私鑰加密得到的字符串B,然后將B和原數(shù)據(jù)A還有自己的公鑰一起發(fā)送給服務(wù)器,
服務(wù)器收到請(qǐng)求,用公鑰解密得到B',如果B==B',則說明原數(shù)據(jù)沒有被篡改過,否則驗(yàn)證不通過。
 
也有說這里得到B以后,需要再用服務(wù)器的公鑰加密一遍得到C,將C和原數(shù)據(jù)和自己的公鑰一起發(fā)送給服務(wù)器,
服務(wù)器收到之后,現(xiàn)需要用自己的私鑰解密一遍得到C',然后再用客戶端公鑰解密得到B',然后同上。。。
 
RSA簽名及驗(yàn)證我還沒用到,所以具體怎么實(shí)現(xiàn)的還需要研究下,待補(bǔ)充!!!
 
 
HTTPS
https算是對(duì)RSA加密的一個(gè)典型應(yīng)用吧,不過這個(gè)服務(wù)器的公鑰私鑰不是自己生產(chǎn)的,而是CA頒發(fā)的。
具體原理網(wǎng)上很多,其中一個(gè):http://jingyan.baidu.com/article/2fb0ba4048e15500f3ec5f7e.html
 
 

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: av免费在线网站 | 视频在线色 | 久久成人免费网 | 国产精品一区二区免费在线观看 | 久久久一区二区精品 | 久久亚洲网 | 亚洲午夜免费 | 粉嫩粉嫩一区二区三区在线播放 | 国产成人精品免高潮在线观看 | 密室逃脱第一季免费观看完整在线 | 免费看污视频在线观看 | 日日摸夜夜骑 | 一级成人黄色片 | 99欧美视频| 最新精品在线 | 毛片免费视频 | 一级毛片真人免费播放视频 | 一区www| 一区二区三区在线播放视频 | 日韩一级片免费 | 免费看一级毛片欧美 | 国产三级国产精品国产普男人 | 久久最新网址 | 久久蜜桃香蕉精品一区二区三区 | 亚洲一区二区网址 | 福利一区二区三区视频在线观看 | 国产精品视频一区二区三区四 | 免费观看又色又爽又黄的崩锅 | 欧美成人精品一级 | 亚欧在线免费观看 | 27xxoo无遮挡动态视频 | 日日爱99| 99久久婷婷国产综合精品青牛牛 | 久久久久久久亚洲精品 | 成人18免费观看 | 国产精品一品二区三区四区18 | 看中国一级毛片 | 日产精品久久久一区二区开放时间 | 国产精品久久久久久久亚洲按摩 | 干一夜综合| 久久影院免费观看 |