Safe and easy to use crypto for iOS and macOS

Last update: Jul 30, 2022

Swift-Sodium Build Status

Swift-Sodium provides a safe and easy to use interface to perform common cryptographic operations on macOS, iOS, tvOS and watchOS.

It leverages the Sodium library, and although Swift is the primary target, the framework can also be used in Objective-C applications.

Please help!

The current Swift-Sodium documentation is not great. Your help to improve it and make it awesome would be very appreciated!

Usage

To add Swift-Sodium as dependency to your Xcode project, select File > Swift Packages > Add Package Dependency, enter its repository URL: https://github.com/jedisct1/swift-sodium.git and import Sodium as well as Clibsodium.

Then, to use it in your source code, add:

import Sodium

The Sodium library itself doesn't have to be installed on the system: the repository already includes a precompiled library for armv7, armv7s, arm64, as well as for the iOS simulator, WatchOS and Catalyst.

The Clibsodium.xcframework framework has been generated by the dist-build/apple-xcframework.sh script.

Running this script on Xcode 12.5 (12E262) on the revision 8aedf4733884a25434b5c17c79c7e7dee27e6eb0 of libsodium generates files identical to the ones present in this repository.

Secret-key cryptography

Messages are encrypted and decrypted using the same secret key, this is also known as symmetric cryptography.

A key can be generated using the key() method, derived from a password using the Password Hashing API, or computed using a secret key and the peer's public key utilising the Key Exchange API.

Authenticated encryption for a sequence of messages

let sodium = Sodium()
let message1 = "Message 1".bytes
let message2 = "Message 2".bytes
let message3 = "Message 3".bytes

let secretkey = sodium.secretStream.xchacha20poly1305.key()

/* stream encryption */

let stream_enc = sodium.secretStream.xchacha20poly1305.initPush(secretKey: secretkey)!
let header = stream_enc.header()
let encrypted1 = stream_enc.push(message: message1)!
let encrypted2 = stream_enc.push(message: message2)!
let encrypted3 = stream_enc.push(message: message3, tag: .FINAL)!

/* stream decryption */

let stream_dec = sodium.secretStream.xchacha20poly1305.initPull(secretKey: secretkey, header: header)!
let (message1_dec, tag1) = stream_dec.pull(cipherText: encrypted1)!
let (message2_dec, tag2) = stream_dec.pull(cipherText: encrypted2)!
let (message3_dec, tag3) = stream_dec.pull(cipherText: encrypted3)!

A stream is a sequence of messages, that will be encrypted as they depart, and, decrypted as they arrive. The encrypted messages are expected to be received in the same order as they were sent.

Streams can be arbitrarily long. This API can thus be used for file encryption, by splitting files into small chunks, so that the whole file doesn't need to reside in memory concurrently.

It can also be used to exchange a sequence of messages between two peers.

The decryption function automatically checks that chunks have been received without modification, and truncation or reordering.

A tag is attached to each message, and can be used to signal the end of a sub-sequence (PUSH), or the end of the string (FINAL).

Authenticated encryption for single messages

let sodium = Sodium()
let message = "My Test Message".bytes
let secretKey = sodium.secretBox.key()
let encrypted: Bytes = sodium.secretBox.seal(message: message, secretKey: secretKey)!
if let decrypted = sodium.secretBox.open(nonceAndAuthenticatedCipherText: encrypted, secretKey: secretKey) {
    // authenticator is valid, decrypted contains the original message
}

This API encrypts a message. The decryption process will check that the messages haven't been tampered with before decrypting them.

Messages encrypted this way are independent: if multiple messages are sent this way, the recipient cannot detect if some messages have been duplicated, deleted or reordered without the sender including additional data with each message.

Optionally, SecretBox provides the ability to utilize a user-defined nonce via seal(message: secretKey: nonce:).

Public-key Cryptography

With public-key cryptography, each peer has two keys: a secret (private) key, that has to remain secret, and a public key that anyone can use to send an encrypted message to that peer. That public key can be only be used to encrypt a message. The corresponding secret is required to decrypt it.

Authenticated Encryption

let sodium = Sodium()
let aliceKeyPair = sodium.box.keyPair()!
let bobKeyPair = sodium.box.keyPair()!
let message = "My Test Message".bytes

let encryptedMessageFromAliceToBob: Bytes =
    sodium.box.seal(message: message,
                    recipientPublicKey: bobKeyPair.publicKey,
                    senderSecretKey: aliceKeyPair.secretKey)!

let messageVerifiedAndDecryptedByBob =
    sodium.box.open(nonceAndAuthenticatedCipherText: encryptedMessageFromAliceToBob,
                    senderPublicKey: aliceKeyPair.publicKey,
                    recipientSecretKey: bobKeyPair.secretKey)

This operation encrypts and sends a message to someone using their public key.

The recipient has to know the sender's public key as well, and will reject a message that doesn't appear to be valid for the expected public key.

seal() automatically generates a nonce and prepends it to the ciphertext. open() extracts the nonce and decrypts the ciphertext.

Optionally, Box provides the ability to utilize a user-defined nonce via seal(message: recipientPublicKey: senderSecretKey: nonce:).

The Box class also provides alternative functions and parameters to deterministically generate key pairs, to retrieve the nonce and/or the authenticator, and to detach them from the original message.

Anonymous Encryption (Sealed Boxes)

let sodium = Sodium()
let bobKeyPair = sodium.box.keyPair()!
let message = "My Test Message".bytes

let encryptedMessageToBob =
    sodium.box.seal(message: message, recipientPublicKey: bobKeyPair.publicKey)!

let messageDecryptedByBob =
    sodium.box.open(anonymousCipherText: encryptedMessageToBob,
                    recipientPublicKey: bobKeyPair.publicKey,
                    recipientSecretKey: bobKeyPair.secretKey)

seal() generates an ephemeral keypair, uses the ephemeral secret key in the encryption process, combines the ephemeral public key with the ciphertext, then destroys the keypair.

The sender cannot decrypt the resulting ciphertext. open() extracts the public key and decrypts using the recipient's secret key. Message integrity is verified, but the sender's identity cannot be correlated to the ciphertext.

Key exchange

let sodium = Sodium()
let aliceKeyPair = sodium.keyExchange.keyPair()!
let bobKeyPair = sodium.keyExchange.keyPair()!

let sessionKeyPairForAlice = sodium.keyExchange.sessionKeyPair(publicKey: aliceKeyPair.publicKey,
    secretKey: aliceKeyPair.secretKey, otherPublicKey: bobKeyPair.publicKey, side: .CLIENT)!
let sessionKeyPairForBob = sodium.keyExchange.sessionKeyPair(publicKey: bobKeyPair.publicKey,
    secretKey: bobKeyPair.secretKey, otherPublicKey: aliceKeyPair.publicKey, side: .SERVER)!

let aliceToBobKeyEquality = sodium.utils.equals(sessionKeyPairForAlice.tx, sessionKeyPairForBob.rx) // true
let bobToAliceKeyEquality = sodium.utils.equals(sessionKeyPairForAlice.rx, sessionKeyPairForBob.tx) // true

Public-key signatures

Signatures allow multiple parties to verify the authenticity of a public message, using the public key of the author's message.

This can be especially useful to sign software updates.

Detached signatures

The signature is generated separately to the original message.

let sodium = Sodium()
let message = "My Test Message".bytes
let keyPair = sodium.sign.keyPair()!
let signature = sodium.sign.signature(message: message, secretKey: keyPair.secretKey)!
if sodium.sign.verify(message: message,
                      publicKey: keyPair.publicKey,
                      signature: signature) {
    // signature is valid
}

Attached signatures

The signature is generated and prepended to the original message.

let sodium = Sodium()
let message = "My Test Message".bytes
let keyPair = sodium.sign.keyPair()!
let signedMessage = sodium.sign.sign(message: message, secretKey: keyPair.secretKey)!
if let unsignedMessage = sodium.sign.open(signedMessage: signedMessage, publicKey: keyPair.publicKey) {
    // signature is valid
}

Hashing

Deterministic hashing

Hashing effectively "fingerprints" input data, no matter what its size, and returns a fixed length "digest".

The digest length can be configured as required, from 16 to 64 bytes.

let sodium = Sodium()
let message = "My Test Message".bytes
let hash = sodium.genericHash.hash(message: message)
let hashOfSize32Bytes = sodium.genericHash.hash(message: message, outputLength: 32)

Keyed hashing

let sodium = Sodium()
let message = "My Test Message".bytes
let key = "Secret key".bytes
let h = sodium.genericHash.hash(message: message, key: key)

Streaming

let sodium = Sodium()
let message1 = "My Test ".bytes
let message2 = "Message".bytes
let key = "Secret key".bytes
let stream = sodium.genericHash.initStream(key: key)!
stream.update(input: message1)
stream.update(input: message2)
let h = stream.final()

Short-output hashing (SipHash)

let sodium = Sodium()
let message = "My Test Message".bytes
let key = sodium.randomBytes.buf(length: sodium.shortHash.KeyBytes)!
let h = sodium.shortHash.hash(message: message, key: key)

Random numbers generation

Random number generation produces cryptographically secure pseudorandom numbers suitable as key material.

let sodium = Sodium()
let randomBytes = sodium.randomBytes.buf(length: 1000)!
let seed = "0123456789abcdef0123456789abcdef".bytes
let stream = sodium.randomBytes.deterministic(length: 1000, seed: seed)!

Password hashing

Password hashing provides the ability to derive key material from a low-entropy password. Password hashing functions are designed to be expensive to hamper brute force attacks, thus the computational and memory parameters may be user-defined.

let sodium = Sodium()
let password = "Correct Horse Battery Staple".bytes
let hashedStr = sodium.pwHash.str(passwd: password,
                                  opsLimit: sodium.pwHash.OpsLimitInteractive,
                                  memLimit: sodium.pwHash.MemLimitInteractive)!

if sodium.pwHash.strVerify(hash: hashedStr, passwd: password) {
    // Password matches the given hash string
} else {
    // Password doesn't match the given hash string
}

if sodium.pwHash.strNeedsRehash(hash: hashedStr,
                                opsLimit: sodium.pwHash.OpsLimitInteractive,
                                memLimit: sodium.pwHash.MemLimitInteractive) {
    // Previously hashed password should be recomputed because the way it was
    // hashed doesn't match the current algorithm and the given parameters.
}

Authentication tags

The sodium.auth.tag() function computes an authentication tag (HMAC) using a message and a key. Parties knowing the key can then verify the authenticity of the message using the same parameters and the sodium.auth.verify() function.

Authentication tags are not signatures: the same key is used both for computing and verifying a tag. Therefore, verifiers can also compute tags for arbitrary messages.

let sodium = Sodium()
let input = "test".bytes
let key = sodium.auth.key()
let tag = sodium.auth.tag(message: input, secretKey: key)!
let tagIsValid = sodium.auth.verify(message: input, secretKey: key, tag: tag)

Key derivation

The sodium.keyDerivation.derive() function generates a subkey using an input (master) key, an index, and a 8 bytes string identifying the context. Up to (2^64) - 1 subkeys can be generated for each context, by incrementing the index.

let sodium = Sodium()
let secretKey = sodium.keyDerivation.keygen()!

let subKey1 = sodium.keyDerivation.derive(secretKey: secretKey,
                                          index: 0, length: 32,
                                          context: "Context!")
let subKey2 = sodium.keyDerivation.derive(secretKey: secretKey,
                                          index: 1, length: 32,
                                          context: "Context!")

Utilities

Zeroing memory

let sodium = Sodium()
var dataToZero = "Message".bytes
sodium.utils.zero(&dataToZero)

Constant-time comparison

let sodium = Sodium()
let secret1 = "Secret key".bytes
let secret2 = "Secret key".bytes
let equality = sodium.utils.equals(secret1, secret2)

Padding

let sodium = Sodium()
var bytes = "test".bytes

// make bytes.count a multiple of 16
sodium.utils.pad(bytes: &bytes, blockSize: 16)!

// restore original size
sodium.utils.unpad(bytes: &bytes, blockSize: 16)!

Padding can be useful to hide the length of a message before it is encrypted.

Constant-time hexadecimal encoding

let sodium = Sodium()
let bytes = "Secret key".bytes
let hex = sodium.utils.bin2hex(bytes)

Hexadecimal decoding

let sodium = Sodium()
let data1 = sodium.utils.hex2bin("deadbeef")
let data2 = sodium.utils.hex2bin("de:ad be:ef", ignore: " :")

Constant-time base64 encoding

let sodium = Sodium()
let b64 = sodium.utils.bin2base64("data".bytes)!
let b64_2 = sodium.utils.bin2base64("data".bytes, variant: .URLSAFE_NO_PADDING)!

Base64 decoding

let data1 = sodium.utils.base642bin(b64)
let data2 = sodium.utils.base642bin(b64, ignore: " \n")
let data3 = sodium.utils.base642bin(b64_2, variant: .URLSAFE_NO_PADDING, ignore: " \n")

Helpers to build custom constructions

Only use the functions below if you know that you absolutely need them, and know how to use them correctly.

Unauthenticated encryption

The sodium.stream.xor() function combines (using the XOR operation) an arbitrary-long input with the output of a deterministic key stream derived from a key and a nonce. The same operation applied twice produces the original input.

No authentication tag is added to the output. The data can be tampered with; an adversary can flip arbitrary bits.

In order to encrypt data using a secret key, the SecretBox class is likely to be what you are looking for.

In order to generate a deterministic stream out of a seed, the RandomBytes.deterministic_rand() function is likely to be what you need.

let sodium = Sodium()
let input = "test".bytes
let key = sodium.stream.key()
let (output, nonce) = sodium.stream.xor(input: input, secretKey: key)!
let twice = sodium.stream.xor(input: output, nonce: nonce, secretKey: key)!

XCTAssertEqual(input, twice)

Algorithms

  • Stream ciphers: XChaCha20, XSalsa20
  • MACs: Poly1305, HMAC-SHA512/256
  • Hash function: BLAKE2B
  • Key exchange: X25519
  • Signatures: Ed25519

GitHub

https://github.com/jedisct1/swift-sodium
Comments
  • 1. Missing function to seal a message with a recipient public key and a nonce

    Hi! I would like to seal a message with a given public key and a nonce. However, it seems like that I cannot provide my own nonce.

    I'm using sodium.box.seal(message: Bytes, recipientPublicKey: Box.PublicKey) right now which doesn't take a nonce as an argument.

    A similar function which does this is implemented in the tweetnacl-js-sealed-box library.

    Kind regards Tim

    Reviewed by timlangner at 2022-02-16 07:40
  • 2. Factor `Clibsodium` into its own repo and package to work around #233

    I'm not sure how seriously you should take this pull request, and I will mark it as a draft to reflect that. But I've bounced off the problem described in #233 for a while, and this is the solution that works and feels least hacky so far. So this is the workaround I'm going to go with until something better comes along.

    Reviewed by jnross at 2020-12-21 23:49
  • 3. No such module 'Clibsodium' Xcode 12

    Hi

    is anyone else seeing this issue?

    on Xcode 12 and Xcode 12.0.1.

    I get " No such module 'Clibsodium'" when I build and Archive

    "SourcePackages/checkouts/swift-sodium/Sodium/Aead.swift:2:8: No such module 'Clibsodium' import Clibsodium"

    Im using swift package manager

    Things ive tried adding, adding Exclude Archs, adding valid Archs.

    I tried release 0.8.0, that doesn't have that issue but has other issues to do with x86.

    Reviewed by marwan87 at 2020-09-30 12:57
  • 4. Building for armv7 fails

    When building swift-sodium for armv7, one gets the following link-time failure:

    Undefined symbols for architecture armv7:
      "___multi3", referenced from:
          _crypto_sign_ed25519_pk_to_curve25519 in libsodium-ios.a(libsodium_la-keypair.o)
          _poly1305_blocks in libsodium-ios.a(libsodium_la-poly1305_donna.o)
          _crypto_scalarmult_curve25519_ref10 in libsodium-ios.a(libsodium_la-x25519_ref10.o)
          _fe25519_mul in libsodium-ios.a(libsodium_la-x25519_ref10.o)
          _fe25519_sq in libsodium-ios.a(libsodium_la-x25519_ref10.o)
          _fe25519_tobytes in libsodium-ios.a(libsodium_la-ed25519_ref10.o)
          _fe25519_sq in libsodium-ios.a(libsodium_la-ed25519_ref10.o)
          ...
    ld: symbol(s) not found for architecture armv7
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    

    Is there a solution besides not building the affected functions?

    Reviewed by avi-kik at 2018-01-07 12:09
  • 5. Cleanup and improve recent tests

    This makes some changes to the tests that were added lately:

    • Hard-coded numbers are avoided
    • Key derivation test is now based on logic rather than specific values
    • Some code cleanup
    Reviewed by blochberger at 2017-07-14 08:00
  • 6. Make Sodium init properly failable.

    There are a couple of ideas captured here:

    First, if the initializer is failable, it should actually return nil when failure occurs, not crash the host application. Returning nil gives the host application the opportunity to handle the error as it chooses. It may be that many will choose to trigger a fatal error:

    guard let sodium = Sodium() else {
        abort()
    }
    

    But the choice must be available.

    Second, this commit prepares for the case in which a failed call to sodium_init() may recover in subsequent calls. From the libSodium docs:

    sodium_init() initializes the library and should be called before any other function provided by Sodium. The function can be called more than once, and can be called simultaneously from multiple threads since version 1.0.11.

    sodium_init() returns 0 on success, -1 on failure, and 1 if the library had already been initialized.

    Reviewed by jnross at 2017-01-16 19:58
  • 7. Swift Sodium 0.9.1 with Swift Package Manager on ARM64/M1, Xcode 12.3, Big Sur 11.1

    I've been teaching the use of Swift Sodium with Cocoapods, now I'm using an M1 Mac and using the Swift Package Manager and latest version of SS, 0.9.1.

    Whenever I use it to create command line apps in Big Sur 11.1, I noticed that although it creates a target (that also seems to work), I see the following warning:

    Skipping duplicate build file in Copy Files build phase: /Users/john/Library/Developer/Xcode/DerivedData/myApp/SourcePackages/checkouts/swift-sodium/Clibsodium.xcframework/macos-arm64_x86_64/libsodium.a

    Only seems to occur with SPM, any idea how to resolve?

    Reviewed by johnalanwoods at 2020-12-15 21:32
  • 8. Update all interfaces to use Swift 3's new Data type

    Swift is moving towards Data as a replacement for NSMutableData and NSData, this PR simply adds support for the Data type in the utils. The primary difference between Data and the legacy types is that memory isn't guaranteed to be contiguous, therefore withUnsafeBytes should be used in order to get a pointer into the Data as opposed to using data.bytes.

    This also makes a potentially breaking change in that zero() no longer resets the data length to 0, happy to revert this but to me 'zero-ing' memory means reseting the bits to 0, not the actual length of the data - this makes for some nicer tests as well since we can check that the underlying bits are actually zero.

    Reviewed by nathankot at 2016-12-12 01:20
  • 9. Publish Clibsodium XCFramework?

    There is a Clibsodium.xcframework file checked in on the master branch, but the cocoapod podspec still only points at the last tagged 0.8.0 release.

    It seems like several issues (namely #205) relating to unexpected Xcode 12 behaviors were resolved referencing the using the xcframework, which is not yet set up via cocoapods.

    Do you have plans to begin publishing the Clibsodium.xcframework file with cocoapods so it can be used as a dependency of the Sodium pod?

    Reviewed by mrosales at 2020-09-19 02:10
  • 10. Add Swift Package Manager and Linux support

    This PR adds SPM and Linux support, along with a bugfix (the macOS applicationDidFinishLaunching signature didn't work with newer versions of Swift).

    Tested on Ubuntu 16.04 with Swift 4.0.3 from swift.org and libsodium 1.0.16 built with

    ./configure --prefix /usr
    make
    make check
    sudo make install
    

    Fixes #69

    Reviewed by tiwoc at 2018-02-22 11:27
  • 11. How to use an existing key pair?

    Hi,

    what is the best way to use an existing key pair which is saved on the local device?

    Ist this method the optimal solution? KeyPair(publicKey: pk, secretKey: sk) pk and sk are the data of the keys.

    Thank´s in advance!

    Reviewed by ghost at 2017-05-15 15:46
  • 12. Unable to run on iOs Simulator with XCode 13

    When trying to run a project with swift-sodium on XCode 13, targeting the iOs Simulator, you will get an error message containing

    building for iOS Simulator, but linking in object file built for iOS, for architecture arm64
    

    According to https://stackoverflow.com/a/63955114, this is an issue with M1 support and can be fixed by adding the following lines to to the Podspec:

    s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
    s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
    

    Note: I have no clue about XCode and Pods, this seems to be the problem and helped me fix the issue locally.

    Reviewed by Skycoder42 at 2022-01-24 06:13
  • 13. Full libsodium build

    I re-ran dist-build/apple-xcframework.sh from libsodium with LIBSODIUM_FULL_BUILD=1, and manually corrected the file Sodium/libsodium/version.h to match. For the sake of simplicity about what actually changed, I also re-ordered the AvailableLibraries array in Clibsodium.xcframework/Info.plist from what was output by this script so as to match the current file ordering (and therefore this file is now unchanged).

    This was run using Xcode 12.5.1 on revision 7d71804ee05f71b65c94282f706c5aa82b279e8a of libsodium (as currently documented in the readme).

    This exposes some currently missing functionality from Clibsodium https://github.com/jedisct1/swift-sodium/blob/1d51e8eb8a99638166aea863e7a71d568b5a06e6/Sodium/libsodium/sodium_lib.h#L56-L67

    Even though this doesn't change the swift library, I think it makes sense for this package to make all of libsodium available in-case any of the low level functionality is needed?

    I've opened this PR for convenience, but I won't be offended if you prefer to build the modified binaries yourself :)

    Closes #248

    Reviewed by aidantwoods at 2021-09-29 23:29
  • 14. Clibsodium without `SODIUM_LIBRARY_MINIMAL`?

    Would there be any issue, in principle, with adjusting the precompiled libsodium to be a non-minimal build? At the moment I believe that SODIUM_LIBRARY_MINIMAL 1 is set, and so some parts of Clibsodium are not available.

    i.e. all of these are not currently available when importing Clibsodium

    https://github.com/jedisct1/swift-sodium/blob/1d51e8eb8a99638166aea863e7a71d568b5a06e6/Sodium/libsodium/sodium_lib.h#L56-L67

    Reviewed by aidantwoods at 2021-09-29 21:18
  • 15. New Release Tag

    I need the commit 8f94369 in my code, but unfortunately in different libraries, so that SPM doesn't work using another reference than tags. So it'd be great, if you could add a new release tag for master's head. Thank you! 🙏

    Reviewed by code28 at 2021-03-12 08:49
  • 16. Is it possible to use the Pod without `use_frameworks!`?

    I have a Cocoapod project that for some reason does not use use_frameworks! directive (legacy, react-native had issues with the frameworks).

    Compilation fails with linking errors for Sodium 0.9.1.

    Undefined symbols for architecture arm64:
    "_sodium_unpad", referenced from:
        Sodium.Utils.unpad(bytes: inout [Swift.UInt8], blockSize: Swift.Int) -> ()? in libSodium.a(Utils.o)
        Sodium.Utils.unpad(bytes: inout [Swift.UInt8], blockSize: Swift.Int) -> ()? in libsodium.a(Utils.o)
    "_sodium_base64_encoded_len", referenced from:
        Sodium.Utils.bin2base64(_: [Swift.UInt8], variant: Sodium.Utils.Base64Variant) -> Swift.String? in libSodium.a(Utils.o)
        Sodium.Utils.bin2base64(_: [Swift.UInt8], variant: Sodium.Utils.Base64Variant) -> Swift.String? in 
    

    I was wondering whether it is possible to use this Sodium pod without using use_frameworks! or using the framework is a fundamental requirement for the Sodium pod.

    It is easy to reproduce with pod spec lint on this repository:

    The following Lint passes:

    pod spec lint --no-clean --verbose --use-modular-headers --private  
    

    The following does not. The error is the same as when I am using Sodium in my project.

    pod spec lint --no-clean --verbose --use-modular-headers --private --use-libraries 
    

    I've created a simple demo project depending on Sodium 0.9.1: https://github.com/ph4r05/SodiumPoc

    When use_frameworks! is present in https://github.com/ph4r05/SodiumPoc/blob/main/Example/Podfile it builds, otherwise not.

    • It works also with use_frameworks! :linkage => :static
    • use_modular_headers! alone does not work
    Reviewed by ph4r05 at 2021-01-06 12:05
A simple way of doing both symmetric and asymmetric crypto without the headache

Simple Swift Crypto I needed a simple way of doing both symmetric and asymmetric

Mar 2, 2022
Swift cross-platform crypto library using CommonCrypto/libcrypto

BlueCryptor Swift cross-platform crypto library derived from IDZSwiftCommonCrypto. IMPORTANT NOTE: This release is NOT entirely source code compatible

May 18, 2022
A wrapper for Apple's Common Crypto library written in Swift.

IDZSwiftCommonCrypto A Swift wrapper for Apple's CommonCrypto library. IDZSwiftCommonCrypto works with both CocoaPods and Cathage. For more details on

Aug 4, 2022
Swift cross-platform crypto library using CommonCrypto/libcrypto

BlueCryptor Swift cross-platform crypto library derived from IDZSwiftCommonCrypto. IMPORTANT NOTE: This release is NOT entirely source code compatible

May 18, 2022
CryptoExchange - A fully functional structure for Crypto Exchange app without using many third party assests
CryptoExchange - A fully functional structure for Crypto Exchange app without using many third party assests

cryptoExchange A fully functional structure for Crypto Exchange app without usin

Jan 6, 2022
An easy-to-use, open-source two-factor authentication app designed specifically for iOS.
An easy-to-use, open-source two-factor authentication app designed specifically for iOS.

Tofu An easy-to-use, open-source two-factor authentication app designed specifically for iOS. Tofu generates one-time passwords to help you protect yo

Jul 31, 2022
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Aug 10, 2022
A tiny and easy to use Swift class to encrypt strings using HMAC algorithms.

#Sweet HMAC SweetHMAC is a tiny and easy to use Swift class to encrypt strings using HMAC algorithms. A special thanks to jernejstrasner for shared HM

Jul 27, 2022
A wrapper to make it really easy to deal with iOS, macOS, watchOS and Linux Keychain and store your user's credentials securely.

A wrapper (written only in Swift) to make it really easy to deal with iOS, macOS, watchOS and Linux Keychain and store your user's credentials securely.

Mar 29, 2022
A simple wrapper for the iOS Keychain to allow you to use it in a similar fashion to User Defaults. Written in Swift.

SwiftKeychainWrapper A simple wrapper for the iOS / tvOS Keychain to allow you to use it in a similar fashion to User Defaults. Written in Swift. Prov

Aug 5, 2022
CoreML-Face-Parsing - how to use face-parsing CoreML model in iOS
CoreML-Face-Parsing - how to use face-parsing CoreML model in iOS

CoreML-Face-Parsing The simple sample how to use face-parsing CoreML model in iO

Aug 4, 2022
Use Apple FaceID or TouchID authentication in your app using BiometricAuthentication.
Use Apple FaceID or TouchID authentication in your app using BiometricAuthentication.

BiometricAuthentication Use Apple FaceID or TouchID authentication in your app using BiometricAuthentication. It's very simple and easy to use that ha

Aug 6, 2022
Swift-cuckoo-collections - Cross-platform Swift dictionaries & sets that use a cuckoo hashing algorithm

CuckooCollections A Swift package for open-addressed sets and dictionaries that

Aug 2, 2022
TouchID used easy on one line in your ViewController.

TouchIDExtension TouchID used easy on one line in your ViewController. ##Installation At this moment, You can install only a way, manually. For instal

Feb 26, 2020
RSA public/private key encryption, private key signing and public key verification in Swift using the Swift Package Manager. Works on iOS, macOS, and Linux (work in progress).

BlueRSA Swift cross-platform RSA wrapper library for RSA encryption and signing. Works on supported Apple platforms (using Security framework). Linux

Jul 8, 2022
RSA public/private key encryption, private key signing and public key verification in Swift using the Swift Package Manager. Works on iOS, macOS, and Linux (work in progress).

BlueRSA Swift cross-platform RSA wrapper library for RSA encryption and signing. Works on supported Apple platforms (using Security framework). Linux

Jul 8, 2022
Native and encrypted password manager for iOS and macOS.
Native and encrypted password manager for iOS and macOS.

Open Sesame Native and encrypted password manager for iOS and macOS. What is it? OpenSesame is a free and powerful password manager that lets you mana

Aug 6, 2022
Simple Swift wrapper for Keychain that works on iOS, watchOS, tvOS and macOS.
Simple Swift wrapper for Keychain that works on iOS, watchOS, tvOS and macOS.

KeychainAccess KeychainAccess is a simple Swift wrapper for Keychain that works on iOS and OS X. Makes using Keychain APIs extremely easy and much mor

Aug 3, 2022
Valet lets you securely store data in the iOS, tvOS, or macOS Keychain without knowing a thing about how the Keychain works.

Valet Valet lets you securely store data in the iOS, tvOS, watchOS, or macOS Keychain without knowing a thing about how the Keychain works. It’s easy.

Aug 3, 2022