Algorithms

  • Hash

    A cryptographic hash function is a mathematical algorithm which is designed to also be a one-way function, that is, a function which is infeasible to invert.

    MD5

    The MD5 algorithm is intended for digital signature applications, where a large file must be "compressed" in a secure manner before being encrypted with a private (secret) key under a public-key cryptosystem such as RSA.

    SHA1

    The Secure Hash Algorithm 1 is called secure because it is computationally infeasible to find a message which corresponds to a given message digest, or to find two different messages which produce the same message digest.

    SHA224, SHA256, SHA384, SHA512

    The Secure Hash Algorithms; namely SHA-224, SHA-256, SHA-384, and SHA-512; specified in this document are called secure because it is computationally infeasible to (1) find a message that corresponds to a given message digest, or (2) find two different messages that produce the same message digest.

    SHA3

    The standard specifies the Secure Hash Algorithm-3 family of functions on binary data. Each of the SHA-3 functions is based on an instance of the KECCAK algorithm that NIST selected as the winner of the SHA-3 Cryptographic Hash Algorithm Competition.

  • Cyclic Redundancy Checks

    A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data

    CRC32

    The CRC32 algorithm is a variant of CRC with 33 bits. The CRCTable is a memoization of a calculation that would have to be repeated for each byte of the message.

    CSR16

    The CRC16 algorithm has nineteen conflicting definitions for 17 bits CRC-16.

  • Ciphers

    A cipher is an algorithm for performing encryption or decryption—a series of well-defined steps that can be followed as a procedure.

    AES-128, AES-192, AES0256

    The Advanced Encryption Standard algorithm specifies a FIPS-approved cryptographic algorithm that can be used to protect electronic data. The AES algorithm is a symmetric block cipher that can encrypt (encipher) and decrypt (decipher) information.

    ChaCha20

    The ChaCha family of stream ciphers, a variant of the Salsa20 family. The Salsa20/20 stream cipher expands a 256-bit key into 264 randomly accessible streams, each containing 264 randomly accessible 64-byte blocks.

    Rabbit

    The Rabbit Stream Cipher Algorithm is a stream cipher algorithm with a 128-bit key and 64-bit initialization vector (IV). Its high performance makes it particularly suited for the use with Internet protocols where large amounts of data have to be processed.

    Blowfish

    The Blowfish Encryption Algorithm is a symmetric block cipher that can be used as a drop-in replacement for DES or IDEA. It takes a variable-length key, from 32 bits to 448 bits, making it ideal for both domestic and exportable use. Blowfish was designed in 1993 by Bruce Schneier as a fast, free alternative to existing encryption algorithms.

  • Message Authenticators

    A Message Authenticator is a way to check the integrity of information transmitted over or stored in an unreliable medium.

    Poly1305

    The Poly1305-AES algorithm is very close to the security of AES and can be computed at extremely high speed.

    HMAC MD5, SHA1, SHA256

    The HMAC: Keyed-Hashing for Message Authentication algorithm provides a way to check the integrity of information transmitted over or stored in an unreliable medium is a prime necessity in the world of open computing and communications.

  • Cipher Block Mode

    A block cipher mode of operation is an algorithm that uses a block cipher to provide an information service such as confidentiality or authenticity.

    Electronic codebook (ECB)

    The Electronic codebook algorithm is the simplest of the encryption modes, named after conventional physical codebooks.

    Cipher-block chaining (CBC)

    With the Cipher Block Chaining algorithm invented in 1976, each block of plaintext is XORed with the previous ciphertext block before being encrypted. This way, each ciphertext block depends on all plaintext blocks processed up to that point. To make each message unique, an initialization vector must be used in the first block.

    Propagating Cipher Block Chaining (PCBC)

    The Propagating Cipher Block Chaining Algorithm or plaintext cipher-block chaining mode was designed to cause small changes in the ciphertext to propagate indefinitely when decrypting, as well as when encrypting.

    Cipher feedback (CFB)

    The Cipher Feedback Algorithm is a close relative of CBC, makes a block cipher into a self-synchronizing stream cipher. Operation is very similar; in particular, CFB decryption is almost identical to CBC encryption performed in reverse.

    Output Feedback (OFB)

    The Output Feedback Algorithm makes a block cipher into a synchronous stream cipher. It generates keystream blocks, which are then XORed with the plaintext blocks to get the ciphertext.

    Counter (CTR)

    The Counter mode turns a block cipher into a stream cipher. It generates the next keystream block by encrypting successive values of a "counter".

  • Password-Based Key Derivation Functions

    A key derivation function's goal is to take some source of initial keying material and derive from it one or more cryptographically strong secret keys.

    PBKDF1

    The Password-Based Key Derivation Function 1 algorithm applies a hash function, which shall be MD2, MD5 or SHA-1, to derive keys.

    PBKDF2

    The Password-Based Key Derivation Function 2 algorithm applies a pseudorandom function to derive keys. The length of the derived key is essentially unbounded.

    HKDF

    The HMAC-based Extract-and-Expand Key Derivation Function algorithm is intended to support a wide range of applications and requirements, and is conservative in its use of cryptographic hash functions.

  • Data Padding

    Padding is typically the first step of a two-step padding scheme used in many hash functions including MD5 and SHA.

    PKCS#5, PKCS#7

    The PKCS algorithm maps an arbitrary string of octets (the data) to another string of octets (the ciphertext) under control of a content-encryption key.

    Zero padding

    With the Zero Padding algorithm all the bytes that are required to be padded are padded with zero.

    No padding

    No padding is applied.

Get Involved

Contribution

Open Source

CryptoSwift is an open source project focused on making it easier to integrate cryptography into your Swift projects.

License

Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to limited restrictions.

Our Heroes

A big thanks to everyone that is using CryptoSwift and to those who were able to provide a donation without which project's like CryptoSwift wouldn't be possible.

Active Development

CryptoSwift is built by Marcin Krzyżanowski, using his extensive experience in using Internet security, to power corporate and private applications.

Getting Started

Installation of CryptoSwift

You can install CryptoSwift, by downloading the latest release as either as zip or tar.gz file, or alternatively add it as a submodule to your project (a top level project directory).

Performance Consideration

  • We recommend that you enable Whole-Module Optimization to improve performance.
  • Non-optimized builds will perform significantly worse.
  • Embedded Framework


    Embedded frameworks require a minimum deployment target of iOS 8 or OS X Mavericks (10.9).

    • Drag the CryptoSwift.xcodeproj file into your Xcode project, and add appropriate framework as a dependency to your target.
    • Now select your App and choose the General tab for the app target.
    • Find Embedded Binaries and press "+", then select CryptoSwift.framework (iOS, OS X, watchOS or tvOS)
    Embedded Framework
  • iOS, macOS, watchOS, tvOS


    In the project, you'll find single scheme for all platforms:

    • CryptoSwift
  • Swift Versions Support


    • Swift 1.2: branch swift12 version <= 0.0.13
    • Swift 2.1: branch swift21 version <= 0.2.3
    • Swift 2.2, 2.3: branch swift2 version <= 0.5.2
    • Swift 3.1, branch swift3 version <= 0.6.9
    • Swift 3.2, branch swift32 version = 0.7.0
    • Swift 4.0, branch master version >= 0.7.1
  • Cocoapods


    CryptoSwift also supports Cocoapods.

    • platform :ios, '8.0'
      use_frameworks!
      
      target 'MyApp' do
      pod 'CryptoSwift'
      end

    Alternatively you can obtain the latest version with this branch of code:

    • pod 'CryptoSwift', :git => "https://github.com/krzyzanowskim/CryptoSwift", :branch => "master"

    Performance Consideration

  • Carthage


    You can use Carthage by creating a cartfile that contains this:

    • github "krzyzanowskim/CryptoSwift"

    Run carthage to build the framework and drag the built CryptoSwift.framework into your Xcode project. Follow build instructions.

    Common Issues

    Review the following commonly reported issues.

  • Swift Package Manager


    You can use Swift Package Manager and specify the CryptoSwift dependency in Package.swift by adding this:.

    • dependencies: [
          .package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "0.8.0"))
      ]

    or more strictly with this:

    • dependencies: [
          .package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", from: "0.8.0")
      ]

    If you need more details

    Refer to this manual on Swift Package Manager.

Usage

Examples of how to use CryptoSwift

Basics

  • import CryptoSwift

CryptoSwift uses array of bytes aka Array<UInt8> as a base type for all operations. Every data may be converted to a stream of bytes. You will find convenience functions that accept String or Data, and it will be internally converted to the array of bytes.

Working with Ciphers

ChaCha20
  • let encrypted = try ChaCha20(key: key, iv: iv).encrypt(message)
    let decrypted = try ChaCha20(key: key, iv: iv).decrypt(encrypted)
Rabbit
  • let encrypted = try Rabbit(key: key, iv: iv).encrypt(message)
    let decrypted = try Rabbit(key: key, iv: iv).decrypt(encrypted)
Blowfish
  • let encrypted = try Blowfish(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).encrypt(message)
    let decrypted = try Blowfish(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).decrypt(encrypted)
AES

Notice regarding padding

Manual padding of data is optional, and CryptoSwift is using PKCS7 padding by default. If you need manually disable/enable padding, you can do this by setting parameter for AES class

Variant of AES encryption (AES-128, AES-192, AES-256) depends on given key length:

  • AES-128 = 16 bytes
  • AES-192 = 24 bytes
  • AES-256 = 32 bytes
  • AES-256 example
  • try AES(key: [1,2,3,...,32], blockMode: .CBC(iv: [1,2,3,...,16]), padding: .pkcs7)
All at once
  • do {
      let aes = try AES(key: "passwordpassword", iv: "drowssapdrowssap") // aes128
      let ciphertext = try aes.encrypt(Array("Nullam quis risus eget urna mollis ornare vel eu leo.".utf8))
    } catch { }
Incremental updates

Incremental operations use instance of Cryptor and encrypt/decrypt one part at a time, this way you can save on memory for large files.

  • do {
      var encryptor = try AES(key: "passwordpassword", iv: "drowssapdrowssap").makeEncryptor()
    
      var ciphertext = Array<UInt8>()
      // aggregate partial results
      ciphertext += try encryptor.update(withBytes: Array("Nullam quis risus ".utf8))
      ciphertext += try encryptor.update(withBytes: Array("eget urna mollis ".utf8))
      ciphertext += try encryptor.update(withBytes: Array("ornare vel eu leo.".utf8))
      // finish at the end
      ciphertext += try encryptor.finish()
    
      print(ciphertext.toHexString())
    } catch {
      print(error)
    }

Have a look at our playground for sample code that works with streams.

Password-Based Key Derivation Functions

  • let password: Array<UInt8> = Array("s33krit".utf8)
    let salt: Array<UInt8> = Array("nacllcan".utf8)
    
    try PKCS5.PBKDF2(password: password, salt: salt, iterations: 4096, variant: .sha256).calculate()

Message Authenticators

  • // Calculate Message Authentication Code (MAC) for message
    let key:Array<UInt8> = [1,2,3,4,5,6,7,8,9,10,...]
    
    try Poly1305(key: key).authenticate(bytes)
    try HMAC(key: key, variant: .sha256).authenticate(bytes)

HMAC-based Key Derivation Function

  • let password: Array<UInt8> = Array("s33krit".utf8)
    let salt: Array<UInt8> = Array("nacllcan".utf8)
    
    try HKDF(password: password, salt: salt, variant: .sha256).calculate()

Data Types Conversion

For your convenience CryptoSwift provides two functions to easily convert array of bytes to Data and another way around:

Data from bytes:
  • let data = Data(bytes: [0x01, 0x02, 0x03])
Data to Array
  • let bytes = data.bytes                     // [1,2,3]
Hexadecimal encoding:
  • let bytes = Array<UInt8>(hex: "0x010203")  // [1,2,3]
    let hex   = bytes.toHexString()            // "010203"
Build bytes out of String
  • let bytes: Array<UInt8> = "password".bytes  // Array("password".utf8)
Base64 encoded data

Also… check out helpers that work with Base64 encoded data:

  • "aPf/i9th9iX+vf49eR7PYk2q7S5xmm3jkRLejgzHNJs=".decryptBase64ToString(cipher)
    "aPf/i9th9iX+vf49eR7PYk2q7S5xmm3jkRLejgzHNJs=".decryptBase64(cipher)
    bytes.toBase64()

Data Padding

Some content-encryption algorithms assume the input length is a multiple of k octets, where k is greater than one. For such algorithms, the input shall be padded.

  • Padding.pkcs7.add(to: bytes, blockSize: AES.blockSize)

Ciphers: Advanced Usage

AES Advanced Usaged
  • let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9]
    
    let key: Array<UInt8> = [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
    let iv: Array<UInt8> = AES.randomIV(AES.blockSize)
    
    do {
      let encrypted = try AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).encrypt(input)
      let decrypted = try AES(key: key, blockMode: .CBC(iv: iv), padding: .pkcs7).decrypt(encrypted)
    } catch {
      print(error)
    }    
AES without data padding
  • let input: Array<UInt8> = [0,1,2,3,4,5,6,7,8,9]
    let encrypted: Array<UInt8> = try! AES(key: Array("secret0key000000".utf8), blockMode: .CBC(iv: Array("0123456789012345".utf8)), padding: .noPadding).encrypt(input)
Using convenience extensions
  • let plain = Data(bytes: [0x01, 0x02, 0x03])
    let encrypted = try! plain.encrypt(ChaCha20(key: key, iv: iv))
    let decrypted = try! encrypted.decrypt(ChaCha20(key: key, iv: iv))

Calculate Digest

Hashing a data or array of bytes (aka Array<UInt8>)

  • /* Hash struct usage */
    let bytes:Array<UInt8> = [0x01, 0x02, 0x03]
    let digest = input.md5()
    let digest = Digest.md5(bytes)
    let data = Data(bytes: [0x01, 0x02, 0x03])
    
    let hash = data.md5()
    let hash = data.sha1()
    let hash = data.sha224()
    let hash = data.sha256()
    let hash = data.sha384()
    let hash = data.sha512()    
    do {
      var digest = MD5()
      let partial1 = try digest.update(withBytes: [0x31, 0x32])
      let partial2 = try digest.update(withBytes: [0x33])
      let result = try digest.finish()
    } catch { }

Hashing a String and printing result

  • let hash = "123".md5() // "123".bytes.md5()

Calculate CRC

  • bytes.crc16()
    data.crc16()
    
    bytes.crc32()
    data.crc32()

Contributing to the CryptoSwift Project

Pull Requests

If you want to contribute, please be sure to submit your pull requests against the develop branch

.

Latest Development Version

For the latest version, please check develop branch. Changes from this branch will be merged into the master branch at some point.

Donate to the CryptoSwift Project

Marcin Krzyżanowski

marcin@krzyzanowskim.com

Download CryptoSwift

Clone this project

Clone with HTTPS
Use Git or checkout with SVN using the web URL.
Clone with SSH
Use a SSH key and passphrase from account.

License

Copyright (C) 2014-2017

This software is provided 'as-is', without any express or implied warranty.

In no event will the authors be held liable for any damages arising from the use of this software.

Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:

  • The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
  • Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  • This notice may not be removed or altered from any source or binary distribution.

Crypto Swift