IDZSwiftCommonCrypto 0.16.1

IDZSwiftCommonCrypto 0.16.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最后发布2023年8月
SPM支持 SPM

iOSDevZone 维护。



IDZSwiftCommonCrypto

Carthage compatible Build Status Coverage Status

IDZSwiftCommonCrypto 是 Apple 的 CommonCrypto 库的 Swift 封装。

IDZSwiftCommonCrypto 可以与 CocoaPods 和 Cathage 一起使用。有关如何将其安装到项目的详细信息,请参阅 INSTALL.md

如果您正在使用 CocoacaPods,您必须在升级 Xcode 后运行 pod cache clean IDZSwiftCommonCrypto --all。这是为了避免使用 CocoaPods 缓存中过时的模块映射,简单地删除 Podfile.lock 和 Pods 文件夹是不够的。

IDZSwiftCommonCrypto 提供以下类:

  • 用于计算消息摘要的 Digest
  • 用于计算基于哈希的消息认证码的 HMAC
  • 用于加密和解密固定缓冲区的 Cryptor
  • 用于加密和解密流信息的 StreamCryptor
  • 用于从密码或密语中推导密钥材料的 PKBDK

使用哪个版本

您使用的版本取决于您当前使用的 Xcode 和 Swift 版本。请参考下表:

  • 0.7.4 -- Xcode 7.3.1, Swift 2.2
  • 0.8.0 -- Xcode 7.3.1, Swift 2.2,增加了针对 CCMode 的额外 API
  • 0.8.3 -- Xcode 8.0, Swift 2.3
  • 0.9.x -- Xcode 8.0, Swift 3.0
  • 0.10.x -- Xcode 9.0, Swift 4.0
  • 0.11.x -- Xcode 10.0, Swift 4.2
  • 0.12.x -- Xcode 10.2, Swift 5.0
  • 0.13.x -- Xcode 11.0, Swift 5.1, iOS 13.0

使用Digest

要计算消息摘要,你需要创建一个Digest实例,对将被计算摘要的数据调用update一次或多次,最后调用final以获得摘要本身。

update方法可以接受一个String

let  s = "The quick brown fox jumps over the lazy dog."
var md5s2 : Digest = Digest(algorithm:.MD5)
md5s2.update(s)
let digests2 = md5s2.final()

// According to Wikipedia this should be
// e4d909c290d0fb1ca068ffaddf22cbd0
hexStringFromArray(digests2)
assert(digests2 == arrayFromHexString("e4d909c290d0fb1ca068ffaddf22cbd0"))

或一个包含UInt8元素的数组

let b : [UInt8] = 
[0x54,0x68,0x65,0x20,0x71,0x75,0x69,0x63,
0x6b,0x20,0x62,0x72,0x6f,0x77,0x6e,0x20,
0x66,0x6f,0x78,0x2e]
var md5s1 : Digest = Digest(algorithm:.MD5)
md5s1.update(b)
let digests1 = md5s1.final()

如果你只有一个缓冲区,你可以简单写出

  var digests3 = Digest(algorithm: .md5).update(b)?.final() // digest is of type [UInt8]?

或者

  var digests4 = Digest(algorithm: .md5).update(s)?.final() // digest is of type [UInt8]?

支持算法

Digest类支持以下算法

  • md2
  • md4
  • md5
  • sha1
  • sha224
  • sha256
  • sha384
  • sha512

使用HMAC

计算密钥散列消息认证码(HMAC)与计算消息摘要非常类似,只是初始化程序现在还需要一个密钥和一个算法参数。

var keys5 = arrayFrom(hexString: "0102030405060708090a0b0c0d0e0f10111213141516171819")
var datas5 : [UInt8] = Array(count:50, repeatedValue:0xcd)
var expecteds5 = arrayFrom(hexString: "4c9007f4026250c6bc8414f9bf50c86c2d7235da")
var hmacs5 = HMAC(algorithm:.sha1, key:keys5).update(datas5)?.final()

// RFC2202 says this should be 4c9007f4026250c6bc8414f9bf50c86c2d7235da
let expectedRFC2202 = arrayFrom(hexString: "4c9007f4026250c6bc8414f9bf50c86c2d7235da")
assert(hmacs5! == expectedRFC2202)

支持算法

  • md5
  • sha1
  • sha224
  • sha256
  • sha384
  • sha512

使用Cryptor

var key = arrayFrom(hexString: "2b7e151628aed2a6abf7158809cf4f3c")
var plainText = "The quick brown fox jumps over the lazy dog. The fox has more or less had it at this point."

var cryptor = Cryptor(operation:.encrypt, algorithm:.aes, options:.PKCS7Padding, key:key, iv:Array<UInt8>())
var cipherText = cryptor.update(plainText)?.final()

cryptor = Cryptor(operation:.decrypt, algorithm:.aes, options:.PKCS7Padding, key:key, iv:Array<UInt8>())
var decryptedPlainText = cryptor.update(cipherText!)?.final()
var decryptedString = decryptedPlainText!.reduce("") { $0 + String(UnicodeScalar($1)) }
decryptedString
assert(decryptedString == plainText)

支持算法

  • AES
  • DES
  • TripleDES
  • CAST
  • RC2
  • Blowfish

使用 StreamCryptor

要加密一个大文件或网络流,请使用 StreamCryptorStreamCryptor 类不会累积加密或解密数据,而是每个对 update 的调用都产生一个输出缓冲区。

下面的示例显示了如何使用 StreamCryptor 加密和解密图像文件。

func crypt(sc : StreamCryptor,  inputStream: NSInputStream, outputStream: NSOutputStream, bufferSize: Int)
{
    var inputBuffer = Array<UInt8>(count:1024, repeatedValue:0)
    var outputBuffer = Array<UInt8>(count:1024, repeatedValue:0)
    inputStream.open()
    outputStream.open()

    var cryptedBytes : UInt = 0    
    while inputStream.hasBytesAvailable
    {
        let bytesRead = inputStream.read(&inputBuffer, maxLength: inputBuffer.count)
        let status = sc.update(inputBuffer, byteCountIn: UInt(bytesRead), bufferOut: &outputBuffer, byteCapacityOut: UInt(outputBuffer.count), byteCountOut: &cryptedBytes)
        assert(status == Status.Success)
        if(cryptedBytes > 0)
        {
            let bytesWritten = outputStream.write(outputBuffer, maxLength: Int(cryptedBytes))
            assert(bytesWritten == Int(cryptedBytes))
        }
    }
    let status = sc.final(&outputBuffer, byteCapacityOut: UInt(outputBuffer.count), byteCountOut: &cryptedBytes)    
    assert(status == Status.Success)
    if(cryptedBytes > 0)
    {
        let bytesWritten = outputStream.write(outputBuffer, maxLength: Int(cryptedBytes))
        assert(bytesWritten == Int(cryptedBytes))
    }
    inputStream.close()
    outputStream.close()
}

let imagePath = NSBundle.mainBundle().pathForResource("Riscal", ofType:"jpg")!
let tmp = NSTemporaryDirectory()
let encryptedFilePath = tmp.stringByAppendingPathComponent("Riscal.xjpgx")
var decryptedFilePath = tmp.stringByAppendingPathComponent("RiscalDecrypted.jpg")

var imageInputStream = NSInputStream(fileAtPath: imagePath)
var encryptedFileOutputStream = NSOutputStream(toFileAtPath: encryptedFilePath, append:false)
var encryptedFileInputStream = NSInputStream(fileAtPath: encryptedFilePath)
var decryptedFileOutputStream = NSOutputStream(toFileAtPath: decryptedFilePath, append:false)

var sc = StreamCryptor(operation:.encrypt, algorithm:.aes, options:.PKCS7Padding, key:key, iv:Array<UInt8>())
crypt(sc, imageInputStream, encryptedFileOutputStream, 1024)

// Uncomment this line to verify that the file is encrypted
//var encryptedImage = UIImage(contentsOfFile:encryptedFile)

sc = StreamCryptor(operation:.decrypt, algorithm:.aes, options:.PKCS7Padding, key:key, iv:Array<UInt8>())
crypt(sc, encryptedFileInputStream, decryptedFileOutputStream, 1024)

var image = UIImage(named:"Riscal.jpg")
var decryptedImage = UIImage(contentsOfFile:decryptedFilePath)

使用 PBKDF

PBKDF 类提供了一种从用户密码派生密钥的方法。以下示例生成了一个 20 字节数组密钥

let keys6 = PBKDF.deriveKey("password", salt: "salt", prf: .SHA1, rounds: 1, derivedKeyLength: 20)
// RFC 6070 - Should derive 0c60c80f961f0e71f3a9b524af6012062fe037a6
let expectedRFC6070 = arrayFrom(hexString: "0c60c80f961f0e71f3a9b524af6012062fe037a6")
assert(keys6 == expectedRFC6070)

支持的伪随机函数

  • sha1
  • sha224
  • sha256
  • sha384
  • sha512