Swift cross-platform crypto library derived from IDZSwiftCommonCrypto.
The current version has been updated for Swift 3.0 and includes new packaging. The API presented by this framework is NOT the same as the one presented by the original. It has been updated to conform to the Swift 3.0 API Guidelines.
This package is functionally complete and has all current relevant tests passing on both macOS and Linux.
Note: On macOS, BlueCryptor uses the Apple provided CommonCrypto library. On Linux, it uses libcrypto from OpenSSL.
- Swift Open Source
swift-3.0-RELEASE
toolchain (Minimum REQUIRED for latest release) - Swift Open Source
swift-3.0.1-PREVIEW-2
toolchain (Recommended)
- macOS 10.11.6 (El Capitan) or higher
- Xcode Version 8.0 (8A218a) or higher using one of the above toolchains (Recommended)
- Ubuntu 15.10 (or 14.04 but only tested on 15.10)
- One of the Swift Open Source toolchains listed above
To build Cryptor from the command line:
% cd <path-to-clone>
% swift build
To run the supplied unit tests for Cryptor from the command line:
% cd <path-to-clone>
% swift build
% swift test
import 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)
}
let cipherText = Cryptor(operation: .encrypt, algorithm: .aes, options: .none, key: key, iv: iv).update(byteArray: textToCipher)?.final()
print(CryptoUtils.hexString(from: cipherText!))
let decryptedText = Cryptor(operation: .decrypt, algorithm: .aes, options: .none, key: key, iv: iv).update(byteArray: cipherText!)?.final()
print(CryptoUtils.hexString(from: decryptedText!))
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()
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()
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
let key = PBKDF.deriveKey(fromPassword: password, salt: salt, prf: .sha1, rounds: rounds, derivedKeyLength: derivedKeyLen)
ley keyString = CryptoUtils.hexString(from: key)
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")
}
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]
)
- From byte array (
- To hexList (
String
)- From byte array (
[UInt8]
)
- From byte array (
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]
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.