RSA演算法及其在iOS中的使用,RSA演算法iOS使用

來源:互聯網
上載者:User

RSA演算法及其在iOS中的使用,RSA演算法iOS使用
因為項目中需要傳輸使用者密碼,為了安全需要用RSA加密,所以就學習了下RSA加密在iOS中的應用。關於RSA的曆史及原理,下面的兩篇文章講的很清楚了: http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html   http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html  簡單來說,RSA建立在一個數學難題之上,就是大數分解:將兩個大素數相乘十分容易,但是想要對其乘積進行因式分解卻極其困難。至於為什麼難,難在哪裡那就是數學家的事了。。。明白了這個就可以大致知道RSA的原理:非對稱式加密(1)乙方產生兩把密鑰(公開金鑰和私密金鑰)。公開金鑰是公開的,任何人都可以獲得,私密金鑰則是保密的。(2)甲方擷取乙方的公開金鑰,然後用它對資訊加密。(3)乙方得到加密後的資訊,用私密金鑰解密。 就好比有一套特殊的鎖和鑰匙,鎖是公開的,誰都可以拿這個鎖來鎖住他的東西,只有有鑰匙的人可以開啟。那麼問題來了,既然鎖是公開的,難道不能通過鎖的結構來反向推算出鑰匙的形狀嗎?答案是:不能!因為這個鎖是特殊的,它就特殊在很難反向推算。(這個倒不是絕對的,也許將來某一天大數分解的數學難題解決了,這種演算法就不安全了,詳見開頭連結) 我遇到的應用情境是,用戶端有伺服器的公開金鑰,用戶端要把使用者的密碼用公開金鑰加密上後上傳到伺服器,伺服器可以用私密金鑰解密。所以用戶端要做的是,將需要加密的內容用伺服器給的公開金鑰進行RSA加密。iOS上並沒有直接的RSA加密API,所以需要折騰一下。gitHub上的代碼大同小異,主要是三個方法(抄自https://github.com/ideawu/Objective-C-RSA)注意代碼裡有個kSecPaddingPKCS1是作者寫死的,而我們的項目中需要傳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,經春哥研究這裡寫成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  簽名機制僅僅加密某個參數是不夠的,還需要保證請求沒有被篡改,所以簽名機制就很有必要。比較簡單和常用就是MD5簽名:拿到待簽名的字串A(比如某個url),將其與伺服器約定好的密鑰拼成新的字串B,對B進行MD5演算法得到簽名C,然後將C作為A的簽名一起發送到伺服器。伺服器收到請求後,對A用與用戶端約定好的密鑰進行相同的演算法得到C’,如果C==C’,那就說明改請求沒有被篡改過,否則驗證不通過 當然也可以做RSA簽名這個要比MD5簽名要稍微麻煩一點,因為需要用戶端產生公開金鑰私密金鑰對,基本流程也和MD5簽名一樣拿到待簽名的字串A(比如某個url),將其用私密金鑰加密得到的字串B,然後將B和原資料A還有自己的公開金鑰一起發送給伺服器,伺服器收到請求,用公開金鑰解密得到B',如果B==B',則說明原資料沒有被篡改過,否則驗證不通過。 也有說這裡得到B以後,需要再用伺服器的公開金鑰加密一遍得到C,將C和原資料和自己的公開金鑰一起發送給伺服器,伺服器收到之後,現需要用自己的私密金鑰解密一遍得到C',然後再用用戶端公開金鑰解密得到B',然後同上。。。 RSA簽名及驗證我還沒用到,所以具體怎麼實現的還需要研究下,待補充!!!  HTTPShttps算是對RSA加密的一個典型應用吧,不過這個伺服器的公開金鑰私密金鑰不是自己生產的,而是CA頒發的。具體原理網上很多,其中一個:http://jingyan.baidu.com/article/2fb0ba4048e15500f3ec5f7e.html  

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.