Envelope

OpenSSL-compatible file encryption in Swift


Keywords
aes, cipher, commoncrypto, cryptography, encryption, ios, openssl, rsa, security, swift
License
MIT
Install
pod try Envelope

Documentation

Envelope

Platforms Cocoapods Carthage Travis CI Swift License

OpenSSL-compatible file encryption in Swift

Envelope is a hybrid cryptosystem that encrypts files efficiently and securely, supporting most symmetric and public-key ciphers. Envelope uses AES256-CBC and RSA-2048 by default, and supports externally created (ie. OpenSSL) public-keys.

Envelope is used in TunnelBear as a fallback method to send app logs via email when servers are unreachable.

Hybrid Encryption | Features | Installation | Usage | License

Hybrid Encryption

Public-key ciphers (ie. RSA) are generally slow, inefficient, and have a plaintext size limit. Symmetric ciphers (ie. AES) require secure key exchange, which may not always be possible. Hybrid cryptosystems use both types of ciphers in tandem to efficiently encrypt plaintext, without requiring secure key exchange.

Envelope removes the need for developers to import big cryptography frameworks like CryptoSwift and SwiftyRSA just to encrypt files using a single symmetric/public-key cipher pair.

Features

  • No third-party dependencies
  • Supports externally created public-key, by importing an X.509 certificate
  • Supports many public-key ciphers
  • Lightweight implementation of AES256-CBC with automatic salt + IV randomization, key generation
  • Supports custom symmetric cipher implementations
  • Easy integration into existing projects
  • Cryptography logic derived from Apple's reliable CommonCrypto library

Installation

Envelope can be installed using Cocoapods, Carthage or by embedding the framework directly into your app from the latest GitHub release.

Cocoapods

pod 'Envelope'

Carthage

github "george-lim/envelope"

Once installed, you'll need to import an X.509 certificate into your app.

To create a new RSA-2048 public-key + certificate, execute the following in Terminal:

openssl req -newkey rsa:2048 -nodes -keyout privateKey.pem -x509 -out certificate.pem
openssl x509 -outform der -in certificate.pem -out certificate.der

Then drag and drop certificate.der into your app, making sure to check off Copy items if needed and select Create groups.

Usage

Envelope Encryption

// Uses `password` and a random 32-character salt for key generation, and random IV
let defaultEnvelope = try Envelope(derNamed: "certificate", password: "some AES password")

// Support for custom bundle where certificate is stored, public-key algorithm, random salt length, and AES keygen runtime (in ms)
let customEnvelope = try Envelope(derNamed: "certificate",
                                  in: Bundle.main,
                                  algorithm: .rsaEncryptionPKCS1,
                                  password: "some AES password",
                                  randomSaltLength: 8,
                                  runtime: 1000)

// Support for `String` or `Data` plaintext
let ciphertext = try defaultEnvelope.encrypt("Hello world!")

// Send ciphertext.key and ciphertext.data to server for decryption
print(ciphertext.key)
print(ciphertext.data)

Envelope Decryption

Assuming you have a folder with privateKey.pem, ciphertext.key and ciphertext.data inside, execute the following in Terminal:

set -- $(openssl rsautl -decrypt -inkey privateKey.pem -in ciphertext.key)
openssl aes-256-cbc -K $1 -iv $2 -d -in ciphertext.data out plaintext

AES256-CBC Crypt Operations

Because Envelope includes an AES256-CBC implementation, it can be used to perform crypt operations on String or Data plaintext as well.

let aes = try AES256CBC(password: "some AES password")
let ciphertext = try aes.encrypt("Hello world!")
if let plaintext: String = try aes.decrypt(ciphertext) {
  print(plaintext) // Hello world!
}

Custom Symmetric Cipher

Envelope supports custom symmetric ciphers through the SymmetricCipher protocol.

Example:

class CustomCipher: SymmetricCipher {
  var sharedSecret: CFData {
    return ...
  }

  func encrypt(_ plaintext: Data) throws -> Data {
    ...
  }

  func decrypt(_ ciphertext: Data) throws -> Data {
    ...
  }
}

let symmetricCipher = CustomCipher()
let envelope = try Envelope(derNamed: "certificate", symmetricCipher: symmetricCipher)
let ciphertext = try envelope.encrypt("Hello world!")

License

This project is copyrighted under the MIT license. Complete license can be found here: https://github.com/george-lim/envelope/blob/master/LICENSE