Dimitri James Tsiflitzis
CryptoKit is an iOS 13+ library that performs cryptographic operations securely and efficiently. Its features include:
There are two popular, trusted and open-source solutions:
These are lower-level systems that deal with raw pointers and explicit memory management.
CryptoKit provides a high-level swift API.
We are going to go through some of the most common cases covered by CryptoKit. These are:
A hash function is any function that can be used to map data of arbitrary size to fixed-size values. This means that a hash function takes an input and transforms it into an output (a hash or digest) that represents this input. This hash value is virtually unique.
import CryptoKit
import Foundation
let path = Bundle.main.path(forResource: "video",
ofType: "mp4")!
let data = FileManager.default.contents(atPath: path)!
let digest = SHA256.hash(data: data)
print(digest)
// or a better representation
let stringHash = digest.map { String(format: "%02hhx", $0) }.joined()
print(stringHash)
var hasher = SHA256()
let path = Bundle.main.path(forResource: "video", ofType: "mp4")!
let stream = InputStream(fileAtPath: path)!stream.open()
let bufferSize = 512
let buffer = UnsafeMutablePointer<UInt8>
.allocate(capacity: bufferSize)
while stream.hasBytesAvailable {
let read = stream.read(buffer, maxLength: bufferSize)
let bufferPointer = UnsafeRawBufferPointer(start: buffer,
count: read)
hasher.update(bufferPointer: bufferPointer)
}
let digest = hasher.finalize()
print(digest)
In the data encryption security method, information is encoded in a way that can only be accessed with the correct encryption key that is held by an authorized party. If the encryption key is incorrect or missing the data cannot be accessed and appears random and unreadable.
let key = SymmetricKey(size: .bits256)
let path = Bundle.main.path(forResource: "video",
ofType: "mp4")!
let data = FileManager.default.contents(atPath: path)!
// To encrypt
let encryptedData = try! ChaChaPoly.seal(data, using: key)
// To decrypt
let sealedBox = try! ChaChaPoly.SealedBox(combined: encryptedData)
let decryptedData = try! ChaChaPoly.open(sealedBox, using: key)
ChaChaPoly is an implementation of the ChaCha20-Poly1305 cipher in case you were wondering.
A digital signature in cryptography is a mathematical scheme for verifying the authenticity of digital information such as messages or documents.
A signature that has been confirmed to be valid by a recipient, gives them a strong indication that the information was indeed created by the person claiming to have created it and hasn’t been tampered with.
let privateKey = Curve25519.Signing.PrivateKey()
let publicKey = privateKey.publicKey // publicize freely
let publicKeyData = publicKey.rawRepresentation
let signingPublicKey = try! Curve25519
.Signing
.PublicKey(rawRepresentation: publicKeyData)
// sign some data with your private key
let data = "All your base are belong to us".data(using: .utf8)!
let signature = try! privateKey.signature(for: data)
if signingPublicKey.isValidSignature(signature, for: data) {
print("The signature is valid.")
}
In data authentication, the aim is to verify the identity of a user. A common case where we would be interested in doing that is when a user requests to send data to a server we control but we would like them to verify their identity before we allow them to do so.
let path = Bundle.main.path(forResource: "video", ofType: "mp4")!
let data = FileManager.default.contents(atPath: path)!
let key = SymmetricKey(size: .bits256) // key shared by both parties
let authentication = HMAC<SHA256>
.authenticationCode(for: data,
using: key)
let authenticationData = Data(authentication)
// ~~~~~~ travel accross the network ~~~~~~~
if (HMAC<SHA256>.isValidAuthenticationCode(authenticationData,
authenticating: data,
using: key)) {
print("Validated ✅")
}
In cryptography, a key-agreement protocol is a process during which two parties, each with their own separate private key, establish a shared secret between them.
This allows them to encrypt or sign data they wish to exchange. Also, this protocol, when executed, prevents unauthorized parties from eavesdropping.
let salt = "Salt".data(using: .utf8)!
let firstPrivateKey = P256.KeyAgreement.PrivateKey()
let firstPublicKey = firstPrivateKey.publicKey
let secondPrivateKey = P256.KeyAgreement.PrivateKey()
let secondPublicKey = secondPrivateKey.publicKey
let firstSharedSecret = try! firstPrivateKey
.sharedSecretFromKeyAgreement(with: secondPublicKey)
let firstSymmetricKey = firstSharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: salt,
sharedInfo: Data(),
outputByteCount: 32)
let secondSharedSecret = try! secondPrivateKey
.sharedSecretFromKeyAgreement(with: firstPublicKey)
let secondSymmetricKey = secondSharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: salt,
sharedInfo: Data(),
outputByteCount: 32)
if firstSymmetricKey == secondSymmetricKey {
print("First and second have the same key to do as they please")
}
So far, we have explored five different cases using CrypoKit, but there are so many more.