kitura/bluecryptor
Swift cross-platform crypto library derived from [IDZSwiftCommonCrypto](https://github.com/iosdevzone/IDZSwiftCommonCrypto).
Prerequisites
Swift
- Swift Open Source
swift-5.1-RELEASEtoolchain (Minimum REQUIRED for latest release) - Swift Open Source
swift-5.4-RELEASEtoolchain (Recommended) - Swift toolchain included in Xcode Version 11.0 or higher.
macOS
- macOS 10.14.6 (Mojave) or higher.
- Xcode Version 11.0 or higher using one of the above toolchains.
- Xcode Version 12.5 or higher using the included toolchain (Recommended).
- CommonCrypto is provided by macOS.
iOS
- iOS 10.0 or higher
- Xcode Version 11.0 or higher using one of the above toolchains.
- Xcode Version 12.5 or higher using the included toolchain (Recommended).
- CommonCrypto is provided by iOS.
Linux
- Ubuntu 16.04 (or 16.10 but only tested on 16.04) and 18.04.
- One of the Swift Open Source toolchain listed above.
- OpenSSL is provided by the distribution. Note: 1.0.x, 1.1.x and later releases of OpenSSL are supported.
- The appropriate libssl-dev package is required to be installed when building.
Build
To build Cryptor from the command line:
% cd <path-to-clone>
% swift buildTesting
To run the supplied unit tests for Cryptor from the command line:
% cd <path-to-clone>
% swift build
% swift testGetting started
Including in your project
Swift Package Manager
To include BlueCryptor into a Swift Package Manager package, add it to the dependencies attribute defined in your Package.swift file. You can select the version using the majorVersion and minor parameters. For example:
dependencies: [
.Package(url: "https://github.com/Kitura/BlueCryptor.git", majorVersion: <majorVersion>, minor: <minor>)
]Carthage
To include BlueCryptor in a project using Carthage, add a line to your Cartfile with the GitHub organization and project names and version. For example:
github "Kitura/BlueCryptor" ~> <majorVersion>.<minor>CocoaPods
To include BlueCryptor in a project using CocoaPods, you just add BlueCryptor to your Podfile, for example:
platform :ios, '10.0'
target 'MyApp' do
use_frameworks!
pod 'BlueCryptor'
endBefore starting
The first thing you need to do is import the Cryptor framework. This is done by the following:
import CryptorAPI
Cryptor
The following code demonstrates encryption and decryption using AES single block CBC mode using optional chaining.
let key = CryptoUtils.byteArray(fromHex: "2b7e151628aed2a6abf7158809cf4f3c")
let iv = CryptoUtils.byteArray(fromHex: "00000000000000000000000000000000")
let plainText = CryptoUtils.byteArray(fromHex: "6bc1bee22e409f96e93d7e117393172a")
var textToCipher = plainText
if plainText.count % Cryptor.Algorithm.aes.blockSize != 0 {
textToCipher = CryptoUtils.zeroPad(byteArray: plainText, blockSize: Cryptor.Algorithm.aes.blockSize)
}
do {
let cipherText = try Cryptor(operation: .encrypt, algorithm: .aes, options: .none, key: key, iv: iv).update(byteArray: textToCipher)?.final()
print(CryptoUtils.hexString(from: cipherText!))
let decryptedText = try Cryptor(operation: .decrypt, algorithm: .aes, options: .none, key: key, iv: iv).update(byteArray: cipherText!)?.final()
print(CryptoUtils.hexString(from: decryptedText!))
} catch let error {
guard let err = error as? CryptorError else {
// Handle non-Cryptor error...
return
}
// Handle Cryptor error... (See Status.swift for types of errors thrown)
}Digest
The following example illustrates generating an MD5 digest from both a String and an instance of NSData.
let qbfBytes : [UInt8] = [0x54,0x68,0x65,0x20,0x71,0x75,0x69,0x63,0x6b,0x20,0x62,0x72,0x6f,0x77,0x6e,0x20,0x66,0x6f,0x78,0x20,0x6a,0x75,0x6d,0x70,0x73,0x20,0x6f,0x76,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x6c,0x61,0x7a,0x79,0x20,0x64,0x6f,0x67,0x2e]
let qbfString = "The quick brown fox jumps over the lazy dog."
// String...
let md5 = Digest(using: .md5)
md5.update(string: qfbString)
let digest = md5.final()
// NSData using optional chaining...
let qbfData = CryptoUtils.data(from: qbfBytes)
let digest = Digest(using: .md5).update(data: qbfData)?.final()HMAC
The following demonstrates generating an SHA256 HMAC using byte arrays for keys and data.
let myKeyData = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
let myData = "4869205468657265"
let key = CryptoUtils.byteArray(fromHex: myKeyData)
let data : [UInt8] = CryptoUtils.byteArray(fromHex: myData)
let hmac = HMAC(using: HMAC.Algorithm.sha256, key: key).update(byteArray: data)?.final()Key Derivation
The following illustrates generating a key using a password, salt, number of rounds and a specified derived key length using the SHA1 algorithm. Then it shows how to generate a String from resultant key.
let password = "password"
let salt = salt
let rounds: UInt = 2
let derivedKeyLen = 20
do {
let key = PBKDF.deriveKey(fromPassword: password, salt: salt, prf: .sha1, rounds: rounds, derivedKeyLength: derivedKeyLen)
let keyString = CryptoUtils.hexString(from: key)
} catch let error {
guard let err = error as? CryptorError else {
// Handle non-Cryptor error...
return
}
// Handle Cryptor error... (See Status.swift for types of errors thrown)
}Random Byte Generation
The following demonstrates generating random bytes of a given length.
let numberOfBytes = 256*256
do {
let randomBytes = try Random.generate(byteCount: numberOfBytes)
} catch {
print("Error generating random bytes")
}Utilities
Cryptor also provides a set of data manipulation utility functions for conversion of data from various formats:
- To byteArray (
[UInt8])
- From hex string - From UTF8 string
- To
Data
- From hex string - From byte array ([UInt8])
- To
NSData
- From hex string - From byte array ([UInt8])
- To
NSString
- From byte array ([UInt8])
- To hexList (
String)
- From byte array ([UInt8])
Also provided are an API to pad a byte array ([UInt8]) such that it is an integral number of block size in bytes long.
- ``
func zeroPad(byteArray: [UInt8], blockSize: Int) -> [UInt8]`` - ``
func zeroPad(string: String, blockSize: Int) -> [UInt8]``
Restrictions
The following algorithm is not available on Linux since it is not supported by OpenSSL.
- Digest: MD2
In all cases, use of unsupported APIs or algorithms will result in a Swift fatalError(), terminating the program and should be treated as a programming error.
Community
We love to talk server-side Swift and Kitura. Join our Slack to meet the team!
License
This library is licensed under Apache 2.0. Full license text is available in LICENSE.
Package Metadata
Repository: kitura/bluecryptor
Default branch: master
README: README.md