利用BBRSACryptor實現iOS端的RSA加解密

jopen 8年前發布 | 15K 次閱讀 iOS開發 移動開發

背景

RSA這種非對稱加密被廣泛的運用于網絡數據的傳輸,但其在iOS上很那直接實現,BBRSACryptor框架通過移植openssl實現了iOS端的RSA,本文將介紹如何使用BBRSACryptor生成證書,加載公鑰,以及后端如何用php讀取證書,加載私鑰。

iOS加密

新建工程并集成BBRSACryptor

這個框架自帶的demo將工程文件與框架放在了同一目錄,因此在配置Header Search Paths時沒有包含工程文件夾,一定注意,下面新建的工程將框架放在了工程文件夾內,因此頭文件尋找路徑需要包含上工程目錄。詳細步驟如下。
1. 新建一個iOS工程,將BBRSACryptor、GTMBase64、OpenSSL三個文件夾拖入工程,目錄結構如下。
工程目錄結構

2.在Build Settings中配置Header Search Pathes。
頭文件搜索路徑
注意最前面的文件夾名稱要和自己的工程名相同

3.打開BBRSACryptor.m文件,修改存儲證書的目錄和文件路徑,默認的是隱藏目錄(前加點),為了方便查看與復制證書,建議將路徑前面的點去掉,例如:

#define OpenSSLRSAKeyDir [DocumentsDir stringByAppendingPathComponent:@"openssl_rsa"]
#define OpenSSLRSAPublicKeyFile [OpenSSLRSAKeyDir stringByAppendingPathComponent:@"publicKey.pem"]
#define OpenSSLRSAPrivateKeyFile [OpenSSLRSAKeyDir stringByAppendingPathComponent:@"privateKey.pem"]

4.打開ViewController.m,導入BBRSACryptor.h和GTMBase64.h,使用下面的代碼生成證書。

BBRSACryptor *rsaCryptor = [[BBRSACryptor alloc] init]; [rsaCryptor generateRSAKeyPairWithKeySize:1024];

運行后,在控制臺會打印出證書路徑,進入路徑后,可以看到公鑰和私鑰證書。
證書

5.使用TextEdit打開公鑰證書,將—–BEGIN PUBLIC KEY—–和—–END PUBLIC KEY—–之間的部分復制,然后在工程中新建一個宏,來保存這個公鑰,以便后續讀取。

#define PublicKey \
@"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjYyZoASYgT+MIc/5YkSJngRbNYEQEI3UF7RVijF0STcMs93pH0qhjLJIQnsvUn2ghEVM4X+S+tQ0XhS+7tmL1UMEFgDgYwG/xr/ZjUozgQyvqeUejA08pbun0E0/Yx9WuBQfCpCc5vNka/ENDZEy/2PbEO5KD3hgsnH1JyNqNnwIDAQAB"

客戶端僅保存公鑰即可,私鑰放在服務器上。使用php可以直接讀取證書。

6.在客戶端加載公鑰與進行加密
前面已經創建了宏,以后通過宏即可加載公鑰。如下:

BBRSACryptor *rsaCryptor = [[BBRSACryptor alloc] init]; // PublicKey是從公鑰證書中復制的內容創建的宏,見上文。 [rsaCryptor importRSAPublicKeyBase64:PublicKey]; NSData *data = [rsaCryptor encryptWithPublicKeyUsingPadding:RSA_PADDING_TYPE_PKCS1 plainData:[@"客戶端加密的內容" dataUsingEncoding:NSUTF8StringEncoding]];
NSString *baseStr = [GTMBase64 stringByEncodingData:data];
NSLog(@"%@",baseStr);

先加載公鑰,然后把要加密的內容轉換成NSData,加密后的內容先進行base64編碼后再傳輸。為了驗證能夠解密,最后對base64編碼的加密內容進行了打印,將這個內容先復制到剪貼板,后面貼在php中進行解密。

php解密

為了方便,將按照上文方法生成的私鑰證書復制到服務器的某個目錄,并在這個目錄下創建一個php文件,并添加如下代碼:

<?php
    header("Content-type:text/html; charset=utf-8");
    /** * 密鑰文件的路徑 */
    $privateKeyFilePath = 'privateKey.pem';
    /** * 公鑰文件的路徑 */
    $publicKeyFilePath = 'publicKey.pem';

    extension_loaded('openssl') or die('php需要openssl擴展支持');

    (file_exists($privateKeyFilePath) && file_exists($publicKeyFilePath))
    or die('密鑰或者公鑰的文件路徑不正確');
    /** * 生成Resource類型的密鑰,如果密鑰文件內容被破壞,openssl_pkey_get_private函數返回false */
    $privateKey = openssl_pkey_get_private(file_get_contents($privateKeyFilePath));
    /** * 生成Resource類型的公鑰,如果公鑰文件內容被破壞,openssl_pkey_get_public函數返回false */
    $publicKey = openssl_pkey_get_public(file_get_contents($publicKeyFilePath));

    ($privateKey && $publicKey) or die('密鑰或者公鑰不可用');
    // 這段內容來自上面iOS端打印的加密內容的base64編碼
    $encryptData = 'J0oTqBCNbsJauVwRz+380y519sSa7ficUO1NvRKiMGKUGJF0pomOu20fHqC77NmsKle9/L4DyYNr3xDgDa4SpO0in39rA9EYXzmx3rlyI1c8iPjAkQ6XpwZk7BsThiCFB/6QmkTW5pMIo4b0axRv/4lq1Rqx/YtuIsGkXQTNntI=';
    $ee = base64_decode($encryptData);
    $decryptData ='';

    if (openssl_private_decrypt($ee, $decryptData, $privateKey)) {

        echo '解密成功,解密后數據為:', $decryptData, PHP_EOL;

    } else {
        die('解密成功');
    }
?>

訪問這個腳本,如果前面做的沒有問題,會得到解密的結果:
這里寫圖片描述

php加密

使用私鑰加密后,可以在客戶端利用公鑰解密。使用下面的代碼進行加密。

<?php
    header("Content-type:text/html; charset=utf-8");
    /** * 密鑰文件的路徑 */
    $privateKeyFilePath = 'privateKey.pem';
    /** * 公鑰文件的路徑 */
    $publicKeyFilePath = 'publicKey.pem';

    extension_loaded('openssl') or die('php需要openssl擴展支持');

    (file_exists($privateKeyFilePath) && file_exists($publicKeyFilePath))
    or die('密鑰或者公鑰的文件路徑不正確');
    /** * 生成Resource類型的密鑰,如果密鑰文件內容被破壞,openssl_pkey_get_private函數返回false */
    $privateKey = openssl_pkey_get_private(file_get_contents($privateKeyFilePath));
    /** * 生成Resource類型的公鑰,如果公鑰文件內容被破壞,openssl_pkey_get_public函數返回false */
    $publicKey = openssl_pkey_get_public(file_get_contents($publicKeyFilePath));

    ($privateKey && $publicKey) or die('密鑰或者公鑰不可用');
$originalData = '服務器加密的內容';
    /** * 加密以后的數據,用于在網路上傳輸 */
    $encryptData = '';
    echo '原數據為:', $originalData, PHP_EOL;
    ///////////////////////////////用私鑰加密////////////////////////
    if (openssl_private_encrypt($originalData, $encryptData, $privateKey)) {
        echo '加密成功,加密后數據(base64_encode后)為:', base64_encode($encryptData), PHP_EOL;

    } else {  
        die('加密失敗');  
    }
?>

訪問腳本后會打印出加密的base64編碼,將這個編碼復制到客戶端進行解密,來驗證可用性。

iOS解密

要在iOS端解密,和加密類似,先加載公鑰,然后把base64編碼的加密內容解碼,解密后轉為NSString即可。

BBRSACryptor *rsaCryptor = [[BBRSACryptor alloc] init]; [rsaCryptor importRSAPublicKeyBase64:PublicKey]; NSData *enCryptorDataBase64 = [@"aWdbPQHiQzU5CUOAIGQT3OD/MPqcqoXHXDFtYQPVRo9/Mb1S/aVcKQVHDjBpLgfzw+0mWxgHN6SuOfH8z9WobgQrTZh+pxhau3DnfukLmENGPWVMqquWMxTkEU7yCkx/RI7XEwv3jk9d4UgFOv35eqNUgYyWDq2gGatEpfnUg6U=" dataUsingEncoding:NSUTF8StringEncoding]; NSData *deCryptorData = [rsaCryptor decryptWithPublicKeyUsingPadding:RSA_PADDING_TYPE_PKCS1 cipherData:[GTMBase64 decodeData:enCryptorDataBase64]];
NSLog(@"%@",[[NSString alloc] initWithData:deCryptorData encoding:NSUTF8StringEncoding]);

不出意外的話,控制臺將會打印出解密后的內容。

來自: http://blog.csdn.net/xyt8023y/article/details/50533306

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!