iOS中使用RSA對數據進行加密解密

RSA算法是一種非對稱加密算法,常被用于加密數據傳輸.如果配合上數字摘要算法, 也可以用于文件簽名.

本文將討論如何在iOS中使用RSA傳輸加密數據.

本文環境

RSA基本原理

RSA使用"秘匙對"對數據進行加密解密.在加密解密數據前,需要先生成公鑰(public key)和私鑰(private key).

  • 公鑰(public key): 用于加密數據. 用于公開, 一般存放在數據提供方, 例如iOS客戶端.
  • 私鑰(private key): 用于解密數據. 必須保密, 私鑰泄露會造成安全問題.

iOS中的Security.framework提供了對RSA算法的支持.這種方式需要對密匙對進行處理, 根據public key生成證書, 通過private key生成p12格式的密匙.
除了Secruty.framework, 也可以將openssl庫編譯到iOS工程中, 這可以提供更靈活的使用方式.

本文使用Security.framework的方式處理RSA.

使用openssl生成密匙對

Github Gist: https://gist.github.com/lvjian700/635368d6f1e421447680

#!/usr/bin/env bash
echo "Generating RSA key pair ..."
echo "1024 RSA key: private_key.pem"
openssl genrsa -out private_key.pem 1024

echo "create certification require file: rsaCertReq.csr"
openssl req -new -key private_key.pem -out rsaCertReq.csr

echo "create certification using x509: rsaCert.crt"
openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt

echo "create public_key.der For IOS"
openssl x509 -outform der -in rsaCert.crt -out public_key.der

echo "create private_key.p12 For IOS. Please remember your password. The password will be used in iOS."
openssl pkcs12 -export -out private_key.p12 -inkey private_key.pem -in rsaCert.crt

echo "create rsa_public_key.pem For Java"
openssl rsa -in private_key.pem -out rsa_public_key.pem -pubout
echo "create pkcs8_private_key.pem For Java"
openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt

echo "finished."    

Tips:

  • 在創建證書的時候, terminal會提示輸入證書信息. 根據wizard輸入對應信息就OK.
  • 在創建p12密匙時, 會提示輸入密碼, 此時的密碼必須記住, 之后會用到.
  • 如果上面指令有問題,請參考最新的openssl官方文檔, 以官方的為準. 之前在網上搜索指令, 被坑了一圈之后, 還是會到啃官方文檔上. 每條指令文檔在最后都會有幾個sample,參考sample即可.

iOS如何加載使用證書

將下面代碼添加到項目中:
https://gist.github.com/lvjian700/204c23226fdffd6a505d

代碼依賴Base64編碼庫, 如果使用cocoapods, 可以講下面依賴添加到Podfile:

pod 'Base64nl', '~> 1.2'    

加密數據

RSAEncryptor *rsa = [[RSAEncryptor alloc] init];

NSLog(@"encryptor using rsa");
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"];
NSLog(@"public key: %@", publicKeyPath);
[rsa loadPublicKeyFromFile:publicKeyPath];

NSString *securityText = @"hello ~";
NSString *encryptedString = [rsa rsaEncryptString:securityText];
NSLog(@"encrypted data: %@", encryptedString);  

[rsa rsaEncryptString:securityText]會返回decrypted base64編碼的字符串:

encrypted data: I1Mnu33cU7QcgaC9uo2bxV0vyfJSqAwyC3DZ+p8jm0G2EmcClarrR5R2xLDdXqvtKj+UJbES7TT+AgkK1NDoQvOJBY+jkmrpAchmRbV2jvi3cEZYQG955jrdSAu21NzQe8xWtEc3YzP+TACPdP4B3Cyy0u8N2RcSFWyxu0YKPXE=    

解密數據

在iOS下解碼需要先加載private key, 之后在對數據解碼. 解碼的時候先進行Base64 decode, 之后在用private key decrypt加密數據.

NSLog(@"decryptor using rsa");
[rsa loadPrivateKeyFromFile:[[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"p12"] password:@"123456"];
NSString *decryptedString = [rsa rsaDecryptString:encryptedString];
NSLog(@"decrypted data: %@", decryptedString);  

之后會輸出解密后的數據:

decryptor using rsa
decrypted data: hello ~ 

在服務器端解碼數據(Java)

在Java中解碼需要使用下述指令生成的pkcs8 private key:

openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt

具體解碼步驟:

  1. 加載pkcs8 private key:
    1. 讀取private key文件
    2. 去掉private key頭尾的"-----BEGIN PRIVATE KEY-----"和"-----BEGIN PRIVATE KEY-----"
    3. 刪除private key中的換行
    4. 對處理后的數據進行Base64解碼
    5. 使用解碼后的數據生成private key.
  2. 解密數據:
    1. 對數據進行Base64解碼
    2. 使用RSA decrypt數據.

這里我們將iOS中"hello ~"加密的數據在Java中進行解碼:

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

import static java.lang.String.format;

public class Encryptor {

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        PrivateKey privateKey = readPrivateKey();

        String message = "AFppaFPTbmboMZD55cjCfrVaWUW7+hZkaq16Od+6fP0lwz/yC+Rshb/8cf5BpBlUao2EunchnzeKxzpiPqtCcCITKvk6HcFKZS0sN9wOhlQFYT+I4f/CZITwBVAJaldZ7mkyOiuvM+raXMwrS+7MLKgYXkd5cFPxEsTxpMSa5Nk=";
        System.out.println(format("- decrypt rsa encrypted base64 message: %s", message));
        // hello ~,  encrypted and encoded with Base64:
        byte[] data = encryptedData(message);
        String text = decrypt(privateKey, data);
        System.out.println(text);
    }

    private static String decrypt(PrivateKey privateKey, byte[] data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedData = cipher.doFinal(data);

        return new String(decryptedData);
    }

    private static byte[] encryptedData(String base64Text) {
        return Base64.getDecoder().decode(base64Text.getBytes(Charset.forName("UTF-8")));
    }

    private static PrivateKey readPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] privateKeyData = Files.readAllBytes(
                Paths.get("/Users/twer/macspace/ios_workshop/Security/SecurityLogin/tools/pkcs8_private_key.pem"));

        byte[] decodedKeyData = Base64.getDecoder()
                .decode(new String(privateKeyData)
                        .replaceAll("-----\\w+ PRIVATE KEY-----", "")
                        .replace("\n", "")
                        .getBytes());

        return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decodedKeyData));
    }
}   

直行成功后控制臺會輸出"hello ~".

總結

這種加密傳輸方式會被用在網銀類App中.雖然網銀會采用全站https方案, 但是在安全登錄這塊會使用另一個證書對登錄信息加密, 這樣可以雙層確保數據安全.

基于RSA加密解密算法, 還可以將其運用在數字簽名場景.以后有空在聊如何使用RSA算法實現對文件的數字簽名.

參考資料

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容

  • /**ios常見的幾種加密方法: 普通的加密方法是講密碼進行加密后保存到用戶偏好設置( [NSUserDefaul...
    彬至睢陽閱讀 2,960評論 0 7
  • RSA算法是一種非對稱加密算法,常被用于加密數據傳輸.如果配合上數字摘要算法, 也可以用于文件簽名. 本文將討論如...
    totzcc閱讀 3,194評論 0 9
  • 最愛多肉 不僅喜歡種,也喜歡畫 愛上多肉,愛上簡筆畫,萌萌噠小多肉,萌化了我的心?·??·???????????
    我的ID是長興小堂客閱讀 91評論 0 0
  • 獻給3004班,也獻給2017屆所有為圓夢高考而奮力拼搏的學子。 昨日白雪覆樹端, ...
    美夢圓中華閱讀 592評論 0 0
  • ——讀《山泉在上》有感 書,是討來的,厚厚一大本,作者是新邵縣委常務副部長蕭克寒。 這么大一部頭,會不會又是那種又...
    夢里李大俠閱讀 313評論 0 1