AES/RSA/MD2/MD5/SHA1/SHA128/SHA384/SHA512 in Swift
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
CommonCrypto
SecrecTestPy
SecrecySwift.xcodeproj
SecrecySwift
SecrecySwiftDemo
.gitignore
LICENSE
README-en.md
README.md
SecrecySwift.podspec

README.md

SecrecySwift

Readme in English

SecrecySwift ,通过包装 CommonCryptoSecurity.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 "https://github.com/adow/SecrecySwift.git" >= 0.3.4
    
  2. 运行 Carthage update, 获取 SecrecySwift;

  3. 拖动 Carthage/Build/iOS 下面的 Secrecy.framwork 到项目 Targets, General 设置标签的 Linked Frameworks and Linraries 中;

    secrecy-1

  4. TargesBuild Phases 设置中,点击 + 按钮,添加 New Run Script Phase 来添加脚本:

     /usr/local/bin/carthage copy-frameworks
    

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

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

    secrecy-2

手动安装

通过 Git Submodule

通过 Submodule 将 SecrecySwift 作为 Embedded Framework 添加到项目中。

  1. 首先确保项目已经在 git 仓库中;

  2. 添加 SecrecySwift 作为 Submodule:

     git submodule add https://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 *
     }
    
  3. 在项目 Targets 的 Build Settings 中添加 Import Paths 中添加 CommonCrypto, 在 Library Search Path 中添加 /usr/lib/system

  4. TargetsBuild PhasesLink Binary with Libraries 中添加 Security.frameworkSystemConfiguration.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