你好,歡迎來到IOS教程網

 Ios教程網 >> IOS使用技巧 >> IOS7技巧 >> Swift 使用RSA算法進行數據加密,解密以及數字簽名

Swift 使用RSA算法進行數據加密,解密以及數字簽名

編輯:IOS7技巧
在做手機開發時也會到有加密簽名功能了,下面我們來看一個Swift 使用RSA算法進行數據加密,解密以及數字簽名的例子.

RSA算法是一種非對稱加密算法,要了解RSA算法,首先要知道什麼是對稱加密算法,什麼是非對稱加密算法。

1,對稱加密算法

密鑰只有一個,發收信雙方都使用這個密鑰對數據進行加密和解密。
特點:算法公開、計算量小、加密速度快、加密效率高特點。但交易雙方都使用同樣鑰匙,安全性得不到保證。
具體算法有:DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法。

2,非對稱加密算法

非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。
特點:由於有兩種密鑰,其中一個是公開的,這樣就消除了最終用戶交換密鑰的需要,更安全。但由於算法復雜,加密解密速度沒有對稱加密解密的速度快。
主要算法有:RSA、Elgamal、背包算法、Rabin、D-H、ECC(橢圓曲線加密算法)。

3,RSA算法

(1)RSA算法是第一個能同時用於加密和數字簽名的算法。
(2)RSA算法基於一個十分簡單的數論事實:將兩個大素數相乘十分容易,但是想要對其乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰。
(3)RSA的算法涉及三個參數,n、e1、e2。
其中,n是兩個大質數p、q的積,n的二進制表示時所占用的位數,就是所謂的密鑰長度。
e1和e2是一對相關的值,e1可以任意取,但要求e1與(p-1)*(q-1)互質;再選擇e2,要求(e2*e1)mod((p-1)*(q-1))=1。
(n,e1),(n,e2)就是密鑰對。其中(n,e1)為公鑰,(n,e2)為私鑰。
RSA加解密的算法完全相同,設A為明文,B為密文,則:A=B^e2 mod n;B=A^e1 mod n;(公鑰加密體制中,一般用公鑰加密,私鑰解密)
e1和e2可以互換使用,即:
A=B^e1 mod n;B=A^e2 mod n;
(4)由於RSA的安全性依賴於大數分解,為保證安全,目前來說RSA密鑰(即n)長度至少要為1024位。
(5)由於RSA算法進行的都是大數計算,使得RSA最快的情況也比DES慢上好幾倍。

4,RSA加密內容長度限制的問題

通常1024位key的最多只能加密127位數據,要解決這個問題有兩種辦法:
(1)自己把數據變成N個117字節的數據段來分別加密,解密也需要自己一個個解密再完成字節拼裝
(2)加密的時候:使用對稱加密(AES/DES etc)加密數據,然後用RSA公鑰加密對稱加密的密鑰。
解密的時候:用RSA的私鑰解密得到對稱加密的密鑰,然後完成反向操作得到明文。 (推薦這種方式)

5,RSA的使用場合

1,用於加密數據:比如我是公司領導,我希望員工A,B,C給我發消息的時候能夠加密。那麼我這邊可以生成一對密鑰,把公鑰給ABC。A把消息使用公鑰加密後發給我,我收到後使用私鑰即可解密。這過程中如果加密消息被BC攔截了,雖然他們有一樣的公鑰,但是無法解密的。
2,用於數字簽名:比如我要給A,B,C發送一段數據,但為了保證這個是我發送的,而不是別人偽造的,那麼我可以附上我的數字簽名。做法是對數據進行MD5之類的運算以取得數據的"指紋",再對"指紋"進行加密,加密將使用密鑰對中的不公開的私鑰。A,B,C收到數據後,用同樣的運算獲得數據指紋,再用公鑰對加密指紋進行解密,比較解密結果與他自己計算出來的指紋是否一致,即可確定數據是否的確是我發送的、以及在傳輸過程中是否被篡改。

6,好用的RSA封裝庫 - Heimdall

Heimdall是一個Swift寫的RSA封裝類,使用它我們可以很方便進行數據加密,解密,數字簽名,簽名驗證等操作。
地址是:GitHub/Heimdall

7,Heimdall的配置

(1)由於Heimdall使用到了CommonCrypto,所以首先要建立橋接頭文件bridge.h並把CommonCrypto引入(頭文件記得配置)

#import <CommonCrypto/CommonCrypto.h>

(2)把Heimdall.swift添加到項目裡,如果有import CommonCrypto,將其去掉

//import CommonCrypto

8,使用Heimdall進行數據加密,解密

由於RSA對加密數據長度有限制,所以Heimdall實際上是混合了AES和RSA這兩種加密方式。
加密時:先生成一個隨機的AES密鑰,用這個密鑰以AES方式加密數據。再用RSA的公鑰加密AES密鑰。整個加密生成的數據實際上包含兩部分:前半部分是用RSA的公鑰加密後的AES密鑰,後半部分是使用AES加密的原始數據。
解密時:先使用RSA私鑰把前面部分的AES密鑰給解出來,再用這個AES密鑰把後半部分的真實數據給解出來。

(1)服務端這邊定義好publicTag和privateTag,這樣就可以生成一對密鑰。

為便於傳輸,我們把生成的publicKeyData用Base64編碼成publicKeyString(String類型)


//公鑰標簽
let publicKeyTag = "com.111cn.public"
//私鑰標簽
let privateKeyTag = "com.111cn.private"
        
print("****** 服務器端開始生成一對密鑰(公鑰和私鑰)******")
let localHeimdall = Heimdall(publicTag: publicKeyTag, privateTag: privateKeyTag,
    keySize: 1024)
        
var publicKeyString:String = ""
if let heimdall = localHeimdall, publicKeyData = heimdall.publicKeyDataX509() {
    publicKeyString = publicKeyData.base64EncodedStringWithOptions(
        NSDataBase64EncodingOptions(rawValue: 0))
            
    // 把/和+替換成下滑線,中劃線是為了URL安全,
    // 接收方那邊要記得轉回來
    publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("/",
        withString: "_")
    publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("+",
        withString: "-")
 
    print("\n--- publicKeyString是:\n\(publicKeyString)")
}
print("\n--- 把公鑰傳給客戶端(publicKeyTag和publicKeyString)\n\n")

(2)把publicTag和publicKeyString作為公鑰分發給客戶端,客戶端使用公鑰加密數據


print("****** 客戶端使用公鑰加密數據 ******")
//先把特殊字符轉回來
publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("_",
    withString: "/")
publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("-",
    withString: "+")
let keyData = NSData(base64EncodedString: publicKeyString ,
    options: NSDataBase64DecodingOptions(rawValue: 0))
        
var encryptedMessage:String = ""
// 創建公鑰
if let partnerHeimdall = Heimdall(publicTag: publicKeyTag, publicKeyData: keyData) {
    // 使用公鑰加密需要傳輸的數據
    let message = "我訪問過www.111cn.com"
    encryptedMessage = partnerHeimdall.encrypt(message)!
            
    print("\n--- 加密後的數據是是:\n\(encryptedMessage)")
    //print(partnerHeimdall.decrypt(encryptedMessage)) //使用公鑰無法解密
}
print("\n--- 把加密後的數據傳給服務端\n\n")
(3)服務端收到數據後使用密鑰解密數據


print("****** 服務器端收到加密數據 ******")
if let localHeimdall2 = Heimdall(publicTag: publicKeyTag, privateTag: privateKeyTag,
    keySize: 1024) {
    //開始解密
    if let decryptedMessage = localHeimdall2.decrypt(encryptedMessage) {
        print("\n--- 解密後的數據是是:\n\(decryptedMessage)")
    }
}
(4)整個流程控制台輸出如下:

原文:Swift - 使用RSA算法進行數據加密,解密以及數字簽名


9,使用Heimdall進行數字簽名和驗證

(1)服務端給消息簽名(使用的是私鑰)。把消息連同簽名發給客戶端

//公鑰標簽
let publicKeyTag = "com.111cn.public"
//私鑰標簽
let privateKeyTag = "com.111cn.private"
        
print("****** 服務器端把消息進行簽名 ******")
let localHeimdall = Heimdall(publicTag: publicKeyTag, privateTag: privateKeyTag,
    keySize: 1024)
var publicKeyString:String = ""
let message = "歡迎訪問www.111cn.com" //消息
var signString:String = ""  //簽名
if let heimdall = localHeimdall, publicKeyData = heimdall.publicKeyDataX509() {
    publicKeyString = publicKeyData.base64EncodedStringWithOptions(
        NSDataBase64EncodingOptions(rawValue: 0))
            
    // 把/和+替換成下滑線,中劃線是為了URL安全,
    // 接收方那邊要記得轉回來
    publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("/",
        withString: "_")
    publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("+",
        withString: "-")
            
    signString = localHeimdall!.sign(message)!
    print("\n--- 消息是:\n\(message)")
    print("\n--- 簽名是:\n\(signString)")
}
print("\n--- 把消息和簽名都傳給客戶端\n\n")

(2)客戶端收到後用公鑰進行驗證,確認是不是服務端發送的


print("****** 客戶端驗證消息和簽名 ******")
//先把特殊字符轉回來
publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("_",
    withString: "/")
publicKeyString = publicKeyString.stringByReplacingOccurrencesOfString("-",
    withString: "+")
let keyData = NSData(base64EncodedString: publicKeyString ,
    options: NSDataBase64DecodingOptions(rawValue: 0))
 
// 創建公鑰
if let partnerHeimdall = Heimdall(publicTag: publicKeyTag, publicKeyData: keyData) {
    //進行驗證
    let result = partnerHeimdall.verify(message, signatureBase64: signString)
    print("\n--- 驗證結果是:\n\(result)")
}
(3)整個流程控制台輸出如下:
原文:Swift - 使用RSA算法進行數據加密,解密以及數字簽名

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved