• Stars
    star
    507
  • Rank 83,759 (Top 2 %)
  • Language
    C
  • License
    ISC License
  • Created over 9 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Safe and easy to use crypto for iOS and macOS

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 15.2 on the revision b3333f07fae1daf1b46ec1ee51ddff0733e73832 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)!

Use RandomBytes.Generator as a generator to produce cryptographically secure pseudorandom numbers.

var rng = RandomBytes.Generator()
let randomUInt32 = UInt32.random(in: 0...10, using: &rng)
let randomUInt64 = UInt64.random(in: 0...10, using: &rng)
let randomInt = Int.random(in: 0...10, using: &rng)
let randomDouble = Double.random(in: 0...1, using: &rng)

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
  • AEADs: XChaCha20Poly1305, AEGIS-128L, AEGIS-256, AES256-GCM
  • MACs: Poly1305, HMAC-SHA512/256
  • Hash function: BLAKE2B
  • Key exchange: X25519
  • Signatures: Ed25519

More Repositories

1

libsodium

A modern, portable, easy to use crypto library.
C
11,796
star
2

dsvpn

A Dead Simple VPN.
C
5,068
star
3

piknik

Copy/paste anything over the network.
Go
2,342
star
4

minisign

A dead simple tool to sign files and verify digital signatures.
C
1,856
star
5

libsodium.js

libsodium compiled to Webassembly and pure JavaScript, with convenient wrappers.
HTML
899
star
6

pure-ftpd

Pure FTP server
C
589
star
7

libhydrogen

A lightweight, secure, easy-to-use crypto library suitable for constrained environments.
C
564
star
8

libsodium-php

The PHP extension for libsodium.
C
546
star
9

edgedns

A high performance DNS cache designed for Content Delivery Networks
Rust
490
star
10

libpuzzle

A library to quickly find visually similar images
C
262
star
11

iptoasn-webservice

Web service to map IP addresses to AS information, using iptoasn.com
Rust
254
star
12

dnsblast

A simple and stupid load testing tool for DNS resolvers
C
233
star
13

as-wasi

An AssemblyScript API layer for WASI system calls.
TypeScript
232
star
14

wasm-crypto

A WebAssembly (via AssemblyScript) set of cryptographic primitives for building authentication and key exchange protocols.
TypeScript
214
star
15

rust-jwt-simple

A secure, standard-conformant, easy to use JWT implementation for Rust.
Rust
204
star
16

rust-bloom-filter

A fast Bloom filter implementation in Rust
Rust
187
star
17

encpipe

The dum^H^H^Hsimplest encryption tool in the world.
C
182
star
18

Pincaster

A fast persistent nosql database with a HTTP/JSON interface, not only for geographical data.
C
171
star
19

blacknurse

BlackNurse attack PoC
C
170
star
20

libsodium-doc

Gitbook documentation for libsodium
Shell
164
star
21

UCarp

UCARP allows a couple of hosts to share common virtual IP addresses in order to provide automatic failover. It is a portable userland implementation of the secure and patent-free Common Address Redundancy Protocol (CARP, OpenBSD's alternative to the patents-bloated VRRP).
M4
164
star
22

bitbar-dnscrypt-proxy-switcher

BitBar plugin to control dnscrypt-proxy usage
Shell
148
star
23

charm

A really tiny crypto library.
C
148
star
24

witx-codegen

WITX code and documentation generator for AssemblyScript, Zig, Rust and more.
Rust
127
star
25

siphash-js

A Javascript implementation of SipHash-2-4
JavaScript
122
star
26

rust-ed25519-compact

Small, wasm-friendly, zero-dependencies Ed25519 and X25519 implementation for Rust.
Rust
118
star
27

rsign2

A command-line tool to sign files and verify signatures in pure Rust.
Rust
112
star
28

go-minisign

Minisign verification library for Golang.
Go
103
star
29

rust-nats

A simple NATS client library for Rust
Rust
102
star
30

was-not-wasm

A hostile memory allocator to make WebAssembly applications more predictable.
Rust
81
star
31

webassembly-benchmarks

Libsodium WebAssembly benchmarks results.
79
star
32

zigly

The easiest way to write services for Fastly's Compute@Edge in Zig.
Zig
78
star
33

rust-minisign

A pure Rust implementation of the Minisign signature tool.
Rust
78
star
34

zig-charm

A Zig version of the Charm crypto library.
Zig
73
star
35

rust-sthash

Very fast cryptographic hashing for large messages.
Rust
65
star
36

vtun

A mirror of VTUN, with some changes
C
63
star
37

iptrap

A simple, but damn fast sinkhole
Rust
62
star
38

openssl-wasm

OpenSSL 3 compiled for WebAssembly/WASI (up-to-date, maintained)
C
58
star
39

rust-ffmpeg-wasi

ffmpeg libraries precompiled for WebAsembly/WASI, as a Rust crate.
Rust
57
star
40

libsodium-signcryption

Signcryption using libsodium.
C
57
star
41

wasmsign

A tool to add and verify digital signatures to/from WASM binaries
Rust
56
star
42

boringssl-wasm

BoringSSL for WebAssembly/WASI
Zig
56
star
43

blobcrypt

Authenticated encryption for streams and arbitrary large files using libsodium
C
54
star
44

rust-coarsetime

Time and duration crate optimized for speed
Rust
52
star
45

rust-siphash

SipHash (2-4, 1-3 + 128 bit variant) implementations for Rust
Rust
48
star
46

6Jack

A framework for analyzing/testing/fuzzing network applications.
C
46
star
47

rust-hyperloglog

A HyperLogLog implementation in Rust.
Rust
46
star
48

zig-minisign

Minisign reimplemented in Zig.
Zig
45
star
49

libchloride

Networking layer for libsodium, based on CurveCP
C
44
star
50

rust-qptrie

A qp-trie implementation in Rust
Rust
42
star
51

minicsv

A tiny, fast, simple, single-file, BSD-licensed CSV parsing library in C.
C
39
star
52

libaegis

Portable C implementations of the AEGIS family of high-performance authenticated encryption algorithms.
C
38
star
53

spake2-ee

A SPAKE2+ Elligator Edition implementation for libsodium 1.0.16+
C
36
star
54

massresolver

Mass DNS resolution tool
C
36
star
55

rust-privdrop

A simple Rust crate to drop privileges
Rust
34
star
56

PureDB

PureDB is a portable and tiny set of libraries for creating and reading constant databases.
C
33
star
57

cpace

A CPace PAKE implementation using libsodium.
C
32
star
58

libclang_rt.builtins-wasm32.a

The missing libclang_rt.builtins-wasm32.a file to compile to WebAssembly.
32
star
59

c-ipcrypt

ipcrypt implementation in C
C
31
star
60

aegis-X

The AEGIS-128X and AEGIS-256X high performance ciphers.
Zig
30
star
61

rust-dnsclient

A simple and secure DNS client crate for Rust.
Rust
29
star
62

fastly-terrarium-examples

Example code you can run in Fastly Terrarium: https://www.fastlylabs.com/
C
28
star
63

rust-xoodyak

Xoodyak, a lightweight and versatile cryptographic scheme implemented in Rust.
Rust
28
star
64

rust-geoip

GeoIP bindings for Rust
Rust
28
star
65

rust-minisign-verify

A small Rust crate to verify Minisign signatures.
Rust
27
star
66

libsodium-xchacha20-siv

Deterministic/nonce-reuse resistant authenticated encryption scheme using XChaCha20, implemented on libsodium.
C
27
star
67

whatsmyresolver

A tiny DNS server that returns the client (resolver) IP
Go
26
star
68

libsodium-sys-stable

Sodiumoxide's libsodium-sys crate, but that installs stable versions of libsodium.
Rust
26
star
69

spritz

A C implementation of Spritz, a spongy RC4-like stream cipher and hash function.
C
25
star
70

metrohash-c

C version of the MetroHash function
C
25
star
71

rust-hmac-sha256

A small, self-contained SHA256 and HMAC-SHA256 implementation.
Rust
25
star
72

rust-clockpro-cache

CLOCK-Pro cache replacement algorithm for Rust
Rust
24
star
73

rust-blind-rsa-signatures

RSA blind signatures in Rust
Rust
24
star
74

PHP-OAuth2-Provider

Skyrock OAuth2 server
PHP
23
star
75

openssl-family-bench

A quick benchmark of {Open,Libre,Boring}SSL
C
23
star
76

dnssector

A DNS library for Rust.
Rust
23
star
77

system-tuning-for-crypto

System tuning recommendations for running cryptographic applications
23
star
78

hashseq

A simple proof of work, mainly designed to mitigate DDoS attacks.
C
23
star
79

rust-cpace

A Rust implementation of CPace, a balanced PAKE.
Rust
23
star
80

rust-aegis

AEGIS cipher for Rust.
Rust
22
star
81

randen-rng

A port of the Google Randen fast backtracking-resistant random generator to the C language.
C
21
star
82

Blogbench

A filesystem benchmark tool that simulates a realistic load
C
21
star
83

vue-dnsstamp

DNS Stamp calculator component for VueJS
Vue
21
star
84

yaifo

YAIFO [remote OpenBSD installer] for OpenBSD-current
Shell
21
star
85

supercop

Always up-to-date mirror of the SUPERCOP cryptographic benchmark.
C
21
star
86

ratelimit

Plug-and-play IP rate limiter in C
C
21
star
87

draft-aegis-aead

The AEGIS cipher family - Draft.
20
star
88

go-hpke-compact

A small and easy to use HPKE implementation in Go.
Go
20
star
89

ipgrep

Extract, defang, resolve names and IPs from text
Python
20
star
90

Simple-Comet-Server

HTTP long-polling server and javascript client library.
Python
19
star
91

simpira384

An AES-based 384 bit permutation.
C
18
star
92

PHP-WebDAV-extension

The PHP WebDAV extension allows easy access to remote resources with PHP through the DAV protocol.
Shell
18
star
93

zig-rocca-s

An implementation of the ROCCA-S encryption scheme.
Zig
17
star
94

c-blind-rsa-signatures

Blind RSA signatures for OpenSSL/BoringSSL.
C
17
star
95

nonce-extension

Make AES-GCM safe to use with random nonces, for any practical number of messages.
Rust
16
star
96

rust-sealed_box

Sealed boxes implementation for Rust/WebAssembly.
Rust
16
star
97

zig-eddsa-key-blinding

A Zig implementation of EdDSA signatures with blind keys.
Zig
16
star
98

js-base64-ct

Safe Base64 encoding/decoding in pure JavaScript.
TypeScript
16
star
99

dlog

A super simple logger for Go. Supports stderr, logfiles, syslog and windows event log.
Go
16
star
100

aes-stream

A fast AES-PRF based secure random-number generator
C
15
star