SecrecySwift實現 Swift 下的摘要方法/AES/RSA加密和簽名

jopen 9年前發布 | 58K 次閱讀 Apple Swift開發 SecrecySwift

SecrecySwift ,通過包裝CommonCrypto和Security.framework,實現 Swift 下的摘要方法/AES/RSA加密和簽名。

特性

  • 摘要算法 (Digest/HMAC):MD2/MD4/MD5/SHA1/SHA224/SHA384/SHA512;
  • AES 加密和解密:EBC/CBC模式;
  • RSA 加密/解密以及簽名和驗證算法:MD2/MD5/SHA1/SHA224/SHA384;

安裝

使用 Carthage 安裝

Carthage是一個去中心化的包管理工具。

安裝 Carthage

$ brew update
$ brew install carthage

集成 SecrecySwift 到 iOS 項目

  1. 在項目中創建Cartfile文件,并添加下面內容

    git "git@github.com:adow/SecrecySwift.git" == 0.3.1
  2. 運行Carthage update, 獲取 SecrecySwift;

  3. 拖動Carthage/Build/iOS下面的Secrecy.framwork到項目Targets,General設置標簽的Linked Frameworks and Linraries中;
  4. 在Targes的Build Phases設置中,點擊+按鈕,添加New Run Script Phase來添加腳本:

    /usr/local/bin/carthage copy-frameworks

    同時在下面的Input Files中添加:

    $(SRCROOT)/Carthage/Build/iOS/Secrecy.framework

手動安裝

通過 Git Submodule

通過 Submodule 將 SecrecySwift 作為 Embedded Framework 添加到項目中。

  1. 首先確保項目已經在 git 倉庫中;
  2. 添加SecrecySwift作為 Submodule:

    git submodule add git@github.com:adow/SecrecySwift.git
  3. 在 Xcode 中打開項目,將 SecrecySwift.xcodeproj 拖放到你的項目的根目錄下;

  4. 在你的項目下,選擇Targets,General中添加Embedded Binaries, 選擇Secrecy.framework, 確保Build Phases中的Link Binary with Libraries中有Secrecy.framework;

項目中直接部署源代碼 (兼容iOS7)

  1. 復制SecrecySwift目錄下的這些文件到項目中

    • AES.swift
    • Digest.swift
    • HMAC.swift
    • RSA.swift
    • SecrecyExtension.swift
  2. 在項目根目錄下建立一個 CommonCrypto, 并建立一個 module.map 文件

module CommonCrypto [system] {
    header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h"
    link "CommonCrypto"
    export *
}

  1. 在項目 Targets 的Build Settings中添加Import Paths中添加CommonCrypto。

  2. 在Targets中Build Phases的Link Binary with Libraries中添加Security.framework和SystemConfiguration.framework。

這樣就不需要import Secrecy, 直接使用里面的函數了;

為什么沒有 Cocoapods

我嘗試了好多次使用Cocoapods發布,但是實在沒有制作 Cocoapods 的經驗,好像是由于需要鏈接CommonCrypto的緣故,我參考了很多人寫的 podspec 文件,仍然無法正確的鏈接CommonCrypto,pod lib lint一直都失敗。如果您知道如何正確的為這個項目寫一個podspec,請一定要發一個 Pull Request 給我。

使用

摘要和 HMAC

只要方法來自 SwiftSSL 項目: https://github.com/SwiftP2P/SwiftSSL

支持以下的摘要方法

  • MD2;
  • MD4;
  • MD5;
  • SHA1;
  • SHA224;
  • SHA256;
  • SHA384;
  • SHA512;

摘要方法:

NSData/String 的digestHex/digestBase64支持將摘要輸出為 hex 和 base64 字符串;

    let raw = "abc123"
    print(raw.digestHex(DigestAlgorithm.MD5))
    print(raw.digestBase64(DigestAlgorithm.MD5))

HMAC 簽名方法

NSData/String 的signHex/signBase64方法支持簽名輸出為 hex 和 base64 字符串;

    let raw = "abc123"
    print(raw.signHex(HMACAlgorithm.SHA1, key: "abc"))
    print(raw.signBase64(HMACAlgorithm.SHA1, key: "abc"))
    print(raw.signBase64(HMACAlgorithm.SHA1, key: "你好"))

AES

支持 AES 模式 :

  • EBC;
  • CBC:

** 只支持 PKCSPaddding7 的補齊方式;**

根據提供的 Key 的長度,支持以下的加密方法

  • AES128: 16位
  • AES192: 24位;
  • AES256: 32位;

EBC 模式

  • aesEBCEncrypt進行EBC模式加密,
  • aesEBCDecryptFromHex從 hex 字符串進行EBC模式解密
  • aesEBCDecryptBase64從 base64 字符串進行EBC解密

    let key = "0000000000000000"
    let raw = "0123456789abcdef"
    let encrypt_1 = raw.aesEBCEncrypt(key)
    print(encrypt_1!.hexString)
    print(encrypt_1!.hexString.aesEBCDecryptFromHex(key))
    print(encrypt_1!.base64String)
    print(encrypt_1!.base64String.aesEBCDecryptFromBase64(key))

CBC 模式

CBC 模式可以指定 IV,如果不指定 IV 的話將用 0 填充;

  • aesCBCEncrypt進行加密;
  • aecCBCDecryptFromHex從 hex 字符串進行解密
  • aesCBCDecryptFromBase64從 base64 字符串進行解密

    let iv = "0000000000000000"
    let encrypt = raw.aesCBCEncrypt(key,iv: iv)
    print(encrypt!.hexString)
    print(encrypt!.hexString.aesCBCDecryptFromHex(key,iv: iv))
    print(encrypt!.base64String)
    print(encrypt!.base64String.aesCBCDecryptFromBase64(key,iv: iv))

RSA

** 只支持.der文件格式的公鑰和.p12格式的私鑰 (而 PHP/Java/Python 這些平臺使用 pem 文件);只支持 PKCS1Padding 的補齊;**

使用OpenSSL生成各個證書的方法

# 生成 RSA 私鑰
openssl genrsa  -out private.pem  2048

# 從密鑰中提取公鑰
openssl rsa  -pubout  -in private.pem  -out public.pem

# 用私鑰生成證書簽名請求
openssl req -new -key private.pem -out cert.csr

# 用私鑰和證書簽名請求生成自簽名的證書
openssl x509 -req -days 3650 -in cert.csr -signkey private.pem -out cert.crt

# 將自簽名的證書轉換為 DER 格式(里面包含公鑰)
openssl x509 -outform der -in cert.crt -out cert.der

# 將私鑰和證書導出到 p12 文件中(要求輸入密碼)
openssl pkcs12 -export -inkey private.pem -in cert.crt -out cert.p12

加密和解密

使用公鑰進行加密

  • public func encrypt(data:NSData) -> NSData?

使用私鑰進行解密

  • public func decrypt(data:NSData) -> NSData?
  • public func decrypt(fromHexString hexString:String) -> NSData?
  • public func decrypt(fromBase64String base64String:String) -> NSData?

    let path_public = NSBundle.mainBundle().pathForResource("cert", ofType: "der")!
    let path_private = NSBundle.mainBundle().pathForResource("cert", ofType: "p12")!
    let raw = "0123456789abcdefg"
    let raw_data = raw.dataUsingEncoding(NSUTF8StringEncoding)!
    let rsa = RSA(filenameOfPulbicKey: path_public, filenameOfPrivateKey: path_private)
    guard let _rsa = rsa else {
        return
    }
    let encrypt_data = _rsa.encrypt(raw_data)
    let base64_string = encrypt_data!.base64String
    print(base64_string)
    let old_data = _rsa.decrypt(fromBase64String: base64_string)
    let old_string = String(data: old_data!, encoding: NSUTF8StringEncoding)
    print("old_string:\(old_string)")

簽名和驗證

支持簽名時的摘要算法:

  • MD2;
  • MD5;
  • SHA1;
  • SHA224;
  • SHA256;
  • SHA384;
  • SHA512;

使用私鑰簽名方法:

public func sign(algorithm:RSAAlgorithm,inputData:NSData) -> NSData?

使用公鑰的驗證方法:

public func verify(algorithm:RSAAlgorithm,inputData:NSData, signedData:NSData) -> Bool

let path_public = NSBundle.mainBundle().pathForResource("cert", ofType: "der")!
            let path_private = NSBundle.mainBundle().pathForResource("cert", ofType: "p12")!

    let rsa = RSA(filenameOfPulbicKey: path_public, filenameOfPrivateKey: path_private)
    guard let _rsa = rsa else {
        return
    }

    let raw = "0123456789abcdefg"
    let raw_data = raw.dataUsingEncoding(NSUTF8StringEncoding)!
    let sign_data = _rsa.sign(RSAAlgorithm.SHA1,inputData:raw_data)
    //        print(sign_data!.hexString)
    print(sign_data!.base64String)

    let raw_test = "0123456789abcdefg"
    let raw_test_data = raw_test.dataUsingEncoding(NSUTF8StringEncoding)!
    let verified = _rsa.verify(RSAAlgorithm.SHA1,inputData: raw_test_data, signedData: sign_data!)
    print("\(verified)")

擴展 NSData

  • hexString: 輸出 hex 字符串;
  • base64String: 輸出 base64 字符串
  • arrayOfBytes: 輸出[UInt8]數組;

    extension NSData {
        public var hexString : String
        public var base64String:String
        public func arrayOfBytes() -> [UInt8]
    }

擴展 String

  • dataFromHexadecimalString: 從 hex 字符串轉換到 NSData;

    extenstion String {
        func dataFromHexadecimalString() -> NSData?
    }

測試

References

項目主頁:http://www.baiduhome.net/lib/view/home/1450708333714

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