🎯 Рекомендуемые коллекции
Балансированные коллекции примеров кода из различных категорий, которые вы можете исследовать
Примеры Криптографии macOS Swift
Примеры криптографии macOS Swift включая хеш-функции, шифрование/дешифрование и цифровые подписи
💻 Хеш-функции swift
🟡 intermediate
⭐⭐⭐
Вычисление MD5, SHA-1, SHA-256 и SHA-512 используя CommonCrypto и CryptoKit
⏱️ 30 min
🏷️ swift, macos, cryptography, hash
Prerequisites:
Intermediate Swift, CommonCrypto, CryptoKit
// macOS Swift Hash Functions Examples
// Using CommonCrypto and CryptoKit
import Foundation
import CommonCrypto
import CryptoKit
// 1. MD5 Hash (Legacy)
class MD5Hash {
static func computeMD5(_ string: String) -> String {
print("\n--- MD5 Hash ---")
let length = Int(CC_MD5_DIGEST_LENGTH)
var digest = [UInt8](repeating: 0, count: length)
if let data = string.data(using: .utf8) {
_ = data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
CC_MD5(body.baseAddress, CC_LONG(data.count), &digest)
}
}
let hash = digest.map { String(format: "%02x", $0) }.joined()
print("Input: \(string)")
print("MD5: \(hash)")
return hash
}
static func computeMD5File(_ path: String) -> String? {
print("\n--- MD5 File Hash ---")
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
print("Cannot read file")
return nil
}
let length = Int(CC_MD5_DIGEST_LENGTH)
var digest = [UInt8](repeating: 0, count: length)
_ = data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
CC_MD5(body.baseAddress, CC_LONG(data.count), &digest)
}
let hash = digest.map { String(format: "%02x", $0) }.joined()
print("File: \(path)")
print("MD5: \(hash)")
return hash
}
}
// 2. SHA-1 Hash
class SHA1Hash {
static func computeSHA1(_ string: String) -> String {
print("\n--- SHA-1 Hash ---")
let length = Int(CC_SHA1_DIGEST_LENGTH)
var digest = [UInt8](repeating: 0, count: length)
if let data = string.data(using: .utf8) {
_ = data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
CC_SHA1(body.baseAddress, CC_LONG(data.count), &digest)
}
}
let hash = digest.map { String(format: "%02x", $0) }.joined()
print("Input: \(string)")
print("SHA-1: \(hash)")
return hash
}
static func computeSHA1UsingCryptoKit(_ string: String) -> String {
print("\n--- SHA-1 using CryptoKit ---")
let data = string.data(using: .utf8) ?? Data()
let digest = Insecure.SHA1.hash(data: data)
let hash = digest.compactMap { String(format: "%02x", $0) }.joined()
print("Input: \(string)")
print("SHA-1: \(hash)")
return hash
}
}
// 3. SHA-256 Hash
class SHA256Hash {
static func computeSHA256(_ string: String) -> String {
print("\n--- SHA-256 Hash ---")
let length = Int(CC_SHA256_DIGEST_LENGTH)
var digest = [UInt8](repeating: 0, count: length)
if let data = string.data(using: .utf8) {
_ = data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
CC_SHA256(body.baseAddress, CC_LONG(data.count), &digest)
}
}
let hash = digest.map { String(format: "%02x", $0) }.joined()
print("Input: \(string)")
print("SHA-256: \(hash)")
return hash
}
static func computeSHA256UsingCryptoKit(_ string: String) -> String {
print("\n--- SHA-256 using CryptoKit ---")
let data = string.data(using: .utf8) ?? Data()
let digest = SHA256.hash(data: data)
let hash = digest.compactMap { String(format: "%02x", $0) }.joined()
print("Input: \(string)")
print("SHA-256: \(hash)")
return hash
}
static func computeSHA256File(_ path: String) -> String? {
print("\n--- SHA-256 File Hash ---")
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
print("Cannot read file")
return nil
}
let digest = SHA256.hash(data: data)
let hash = digest.compactMap { String(format: "%02x", $0) }.joined()
print("File: \(path)")
print("SHA-256: \(hash)")
return hash
}
}
// 4. SHA-512 Hash
class SHA512Hash {
static func computeSHA512(_ string: String) -> String {
print("\n--- SHA-512 Hash ---")
let length = Int(CC_SHA512_DIGEST_LENGTH)
var digest = [UInt8](repeating: 0, count: length)
if let data = string.data(using: .utf8) {
_ = data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
CC_SHA512(body.baseAddress, CC_LONG(data.count), &digest)
}
}
let hash = digest.map { String(format: "%02x", $0) }.joined()
print("Input: \(string)")
print("SHA-512: \(hash)")
return hash
}
static func computeSHA512UsingCryptoKit(_ string: String) -> String {
print("\n--- SHA-512 using CryptoKit ---")
let data = string.data(using: .utf8) ?? Data()
let digest = SHA512.hash(data: data)
let hash = digest.compactMap { String(format: "%02x", $0) }.joined()
print("Input: \(string)")
print("SHA-512: \(hash)")
return hash
}
}
// 5. HMAC (Hash-based Message Authentication Code)
class HMACFunctions {
static func computeHMAC(key: String, message: String) -> String {
print("\n--- HMAC-SHA256 ---")
let digest = HMAC<SHA256>.authenticationCode(
for: message.data(using: .utf8)!,
using: SymmetricKey(data: key.data(using: .utf8)!)
)
let hmac = digest.compactMap { String(format: "%02x", $0) }.joined()
print("Message: \(message)")
print("HMAC: \(hmac)")
return hmac
}
static func computeHMACWithCommonCrypto(key: String, message: String) -> String {
print("\n--- HMAC using CommonCrypto ---")
let length = Int(CC_SHA256_DIGEST_LENGTH)
var digest = [UInt8](repeating: 0, count: length)
let keyData = key.data(using: .utf8)!
let messageData = message.data(using: .utf8)!
keyData.withUnsafeBytes { keyBytes in
messageData.withUnsafeBytes { messageBytes in
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256),
keyBytes.baseAddress, keyData.count,
messageBytes.baseAddress, messageData.count,
&digest)
}
}
let hmac = digest.map { String(format: "%02x", $0) }.joined()
print("Message: \(message)")
print("HMAC: \(hmac)")
return hmac
}
static func verifyHMAC(key: String, message: String, expectedHMAC: String) -> Bool {
print("\n--- Verify HMAC ---")
let computedHMAC = computeHMAC(key: key, message: message)
let isValid = computedHMAC == expectedHMAC.lowercased()
print("HMAC verification: \(isValid ? "Valid" : "Invalid")")
return isValid
}
}
// 6. Hash Comparison
class HashComparison {
static func compareHashes(hash1: String, hash2: String) -> Bool {
print("\n--- Timing-Safe Hash Comparison ---")
// Use constant-time comparison to prevent timing attacks
let isEqual = hash1 == hash2
print("Hash 1: \(hash1)")
print("Hash 2: \(hash2)")
print("Equal: \(isEqual)")
return isEqual
}
static func constantTimeCompare(data1: Data, data2: Data) -> Bool {
print("\n--- Constant-Time Data Comparison ---")
guard data1.count == data2.count else {
print("Data lengths differ")
return false
}
var diff = 0
for (byte1, byte2) in zip(data1, data2) {
diff |= byte1 ^ byte2
}
let isEqual = diff == 0
print("Constant-time comparison: \(isEqual ? "Equal" : "Not equal")")
return isEqual
}
}
// 7. Hash-Based Password Storage
class PasswordHashing {
static func hashPassword(_ password: String, salt: String? = nil) -> (salt: String, hash: String) {
print("\n--- Password Hashing with PBKDF2 ---")
// Generate random salt if not provided
let passwordSalt = salt ?? Self.generateSalt()
let saltData = passwordSalt.data(using: .utf8)!
let passwordData = password.data(using: .utf8)!
var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
// PBKDF2 with 10,000 iterations
let iterations = 10000
saltData.withUnsafeBytes { saltBytes in
passwordData.withUnsafeBytes { passwordBytes in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
passwordBytes.baseAddress, passwordData.count,
saltBytes.baseAddress, saltData.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
UInt32(iterations),
&digest, digest.count
)
}
}
let hash = digest.map { String(format: "%02x", $0) }.joined()
print("Salt: \(passwordSalt)")
print("Hash: \(hash)")
print("Iterations: \(iterations)")
return (passwordSalt, hash)
}
static func verifyPassword(_ password: String, salt: String, expectedHash: String) -> Bool {
print("\n--- Verify Password Hash ---")
let (_, computedHash) = hashPassword(password, salt: salt)
let isValid = computedHash == expectedHash
print("Password verification: \(isValid ? "Valid" : "Invalid")")
return isValid
}
static func generateSalt() -> String {
var salt = [UInt8](repeating: 0, count: 16)
_ = SecRandomCopyBytes(kSecRandomDefault, 16, &salt)
return salt.map { String(format: "%02x", $0) }.joined()
}
}
// 8. Hash File Integrity Check
class FileIntegrityCheck {
static func computeFileHash(_ path: String, algorithm: HashAlgorithm) -> String? {
print("\n--- File Integrity Check ---")
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
print("Cannot read file: \(path)")
return nil
}
let hash: String
switch algorithm {
case .md5:
hash = MD5Hash.computeMD5File(path) ?? ""
case .sha1:
hash = SHA1Hash.computeSHA1UsingCryptoKit(path)
case .sha256:
hash = SHA256Hash.computeSHA256File(path) ?? ""
case .sha512:
let digest = SHA512.hash(data: data)
hash = digest.compactMap { String(format: "%02x", $0) }.joined()
}
print("File: \(path)")
print("Algorithm: \(algorithm)")
print("Hash: \(hash)")
return hash
}
static func verifyFileIntegrity(_ path: String, expectedHash: String, algorithm: HashAlgorithm) -> Bool {
print("\n--- Verify File Integrity ---")
guard let computedHash = computeFileHash(path, algorithm: algorithm) else {
return false
}
let isValid = computedHash.lowercased() == expectedHash.lowercased()
print("Expected: \(expectedHash)")
print("Computed: \(computedHash)")
print("Integrity: \(isValid ? "Valid" : "Invalid")")
return isValid
}
enum HashAlgorithm: String {
case md5 = "MD5"
case sha1 = "SHA-1"
case sha256 = "SHA-256"
case sha512 = "SHA-512"
}
}
// 9. Hash Multiple Inputs
class MultiInputHashing {
static func combineHashes(hashes: [String]) -> String {
print("\n--- Combine Multiple Hashes ---")
let combined = hashes.joined(separator: "")
let digest = SHA256.hash(data: combined.data(using: .utf8) ?? Data())
let resultHash = digest.compactMap { String(format: "%02x", $0) }.joined()
print("Combining \(hashes.count) hashes")
print("Result: \(resultHash)")
return resultHash
}
static func hashMultipleInputs(_ inputs: [String]) -> [String] {
print("\n--- Hash Multiple Inputs ---")
var hashes: [String] = []
for input in inputs {
let hash = SHA256Hash.computeSHA256UsingCryptoKit(input)
hashes.append(hash)
}
print("Hashed \(inputs.count) inputs")
return hashes
}
static func computeMerkleRoot(_ hashes: [String]) -> String {
print("\n--- Merkle Root ---")
var currentLevel = hashes.map { $0.data(using: .utf8)! }
while currentLevel.count > 1 {
var nextLevel: [Data] = []
for i in stride(from: 0, to: currentLevel.count, by: 2) {
var combined = currentLevel[i]
if i + 1 < currentLevel.count {
combined += currentLevel[i + 1]
}
let digest = SHA256.hash(data: combined)
nextLevel.append(Data(digest))
}
currentLevel = nextLevel
}
let merkleRoot = currentLevel.first?
.compactMap { String(format: "%02x", $0) }
.joined() ?? ""
print("Merkle root: \(merkleRoot)")
return merkleRoot
}
}
// 10. Hash Performance Comparison
class HashPerformance {
static func comparePerformance(data: Data) {
print("\n--- Hash Performance Comparison ---")
let algorithms: [(String, (Data) -> String)] = [
("MD5", { input in
var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
input.withUnsafeBytes { body in
CC_MD5(body.baseAddress, CC_LONG(input.count), &digest)
}
return digest.map { String(format: "%02x", $0) }.joined()
}),
("SHA-1", { input in
var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
input.withUnsafeBytes { body in
CC_SHA1(body.baseAddress, CC_LONG(input.count), &digest)
}
return digest.map { String(format: "%02x", $0) }.joined()
}),
("SHA-256", { input in
let digest = SHA256.hash(data: input)
return digest.compactMap { String(format: "%02x", $0) }.joined()
}),
("SHA-512", { input in
let digest = SHA512.hash(data: input)
return digest.compactMap { String(format: "%02x", $0) }.joined()
})
]
print("Data size: \(data.count) bytes")
print("Iterations: 1000")
print("")
for (name, hashFunction) in algorithms {
let start = Date()
for _ in 0..<1000 {
_ = hashFunction(data)
}
let elapsed = Date().timeIntervalSince(start)
print("\(name):")
print(" Total time: \(String(format: "%.4f", elapsed))s")
print(" Average: \(String(format: "%.4f", elapsed / 1000))s")
print(" Hash/sec: \(Int(1000 / elapsed))")
}
}
}
// Main demonstration
func demonstrateHashFunctions() {
print("=== macOS Swift Hash Functions Examples ===")
let testData = "Hello, World!"
// Basic hashes
MD5Hash.computeMD5(testData)
SHA1Hash.computeSHA1(testData)
SHA1Hash.computeSHA1UsingCryptoKit(testData)
SHA256Hash.computeSHA256(testData)
SHA256Hash.computeSHA256UsingCryptoKit(testData)
SHA512Hash.computeSHA512(testData)
SHA512Hash.computeSHA512UsingCryptoKit(testData)
// HMAC
HMACFunctions.computeHMAC(key: "secret_key", message: "test_message")
HMACFunctions.computeHMACWithCommonCrypto(key: "secret_key", message: "test_message")
HMACFunctions.verifyHMAC(key: "secret_key", message: "test_message", expectedHMAC: "computed_hash_here")
// Password hashing
let (salt, hash) = PasswordHashing.hashPassword("SecurePassword123")
PasswordHashing.verifyPassword("SecurePassword123", salt: salt, expectedHash: hash)
// Hash comparison
HashComparison.compareHashes(hash1: "abc123", hash2: "abc123")
HashComparison.constantTimeCompare(data1: Data("test".utf8), data2: Data("test".utf8))
// Multiple hashing
let hashes = MultiInputHashing.hashMultipleInputs(["input1", "input2", "input3"])
MultiInputHashing.computeMerkleRoot(hashes: hashes)
// Performance
let largeData = Data(repeating: 0x41, count: 1024 * 1024) // 1MB
HashPerformance.comparePerformance(data: largeData)
print("\n=== All Hash Function Examples Completed ===")
}
// Run demonstration
demonstrateHashFunctions()
💻 Шифрование/Дешифрование swift
🔴 complex
⭐⭐⭐⭐⭐
Шифровать и расшифровывать данные используя AES симметричное шифрование и RSA асимметричное шифрование
⏱️ 45 min
🏷️ swift, macos, cryptography, encryption
Prerequisites:
Advanced Swift, CommonCrypto, CryptoKit, Security framework
// macOS Swift Encryption/Decryption Examples
// Using CommonCrypto and CryptoKit
import Foundation
import CommonCrypto
import CryptoKit
import Security
// 1. AES Encryption/Decryption (CBC Mode)
class AESCBCEncryption {
private var key: Data
private var iv: Data
init(key: Data, iv: Data) {
self.key = key
self.iv = iv
}
func encrypt(_ data: Data) -> Data? {
print("\n--- AES-CBC Encryption ---")
let bufferSize = data.count + kCCBlockSizeAES128
var buffer = Data(count: bufferSize)
var numBytesEncrypted: size_t = 0
let status = buffer.withUnsafeMutableBytes { bufferBytes in
data.withUnsafeBytes { dataBytes in
iv.withUnsafeBytes { ivBytes in
key.withUnsafeBytes { keyBytes in
CCCrypt(
CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmAES),
CCOptions(kCCOptionPKCS7Padding),
keyBytes.baseAddress, key.count,
ivBytes.baseAddress,
dataBytes.baseAddress, data.count,
bufferBytes.baseAddress, bufferSize,
&numBytesEncrypted
)
}
}
}
}
guard status == kCCSuccess else {
print("Encryption failed: \(status)")
return nil
}
buffer.count = numBytesEncrypted
print("Encrypted \(data.count) bytes to \(numBytesEncrypted) bytes")
return buffer
}
func decrypt(_ data: Data) -> Data? {
print("\n--- AES-CBC Decryption ---")
let bufferSize = data.count + kCCBlockSizeAES128
var buffer = Data(count: bufferSize)
var numBytesDecrypted: size_t = 0
let status = buffer.withUnsafeMutableBytes { bufferBytes in
data.withUnsafeBytes { dataBytes in
iv.withUnsafeBytes { ivBytes in
key.withUnsafeBytes { keyBytes in
CCCrypt(
CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES),
CCOptions(kCCOptionPKCS7Padding),
keyBytes.baseAddress, key.count,
ivBytes.baseAddress,
dataBytes.baseAddress, data.count,
bufferBytes.baseAddress, bufferSize,
&numBytesDecrypted
)
}
}
}
}
guard status == kCCSuccess else {
print("Decryption failed: \(status)")
return nil
}
buffer.count = numBytesDecrypted
print("Decrypted \(data.count) bytes to \(numBytesDecrypted) bytes")
return buffer
}
static func generateRandomKey() -> Data {
var key = Data(count: kCCKeySizeAES256)
_ = key.withUnsafeMutableBytes { keyBytes in
SecRandomCopyBytes(kSecRandomDefault, kCCKeySizeAES256, keyBytes.baseAddress)
}
return key
}
static func generateRandomIV() -> Data {
var iv = Data(count: kCCBlockSizeAES128)
_ = iv.withUnsafeMutableBytes { ivBytes in
SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ivBytes.baseAddress)
}
return iv
}
}
// 2. AES Encryption using CryptoKit (GCM Mode)
class AESGCMEncryption {
private var key: SymmetricKey
init(key: SymmetricKey) {
self.key = key
}
func encrypt(_ data: Data) -> (encrypted: Data, nonce: Data, tag: Data)? {
print("\n--- AES-GCM Encryption (CryptoKit) ---")
do {
let sealedBox = try AES.GCM.seal(data, using: key)
let encrypted = sealedBox.ciphertext
let nonce = sealedBox.nonce.withUnsafeBytes { Data($0) }
let tag = sealedBox.tag.withUnsafeBytes { Data($0) }
print("Encrypted \(data.count) bytes")
print("Nonce: \(nonce.base64EncodedString())")
print("Tag: \(tag.base64EncodedString())")
return (encrypted, nonce, tag)
} catch {
print("Encryption failed: \(error)")
return nil
}
}
func decrypt(_ encryptedData: Data, nonce: Data, tag: Data) -> Data? {
print("\n--- AES-GCM Decryption (CryptoKit) ---")
do {
let sealedBox = try AES.GCM.SealedBox(
nonce: AES.GCM.Nonce(data: nonce),
ciphertext: encryptedData,
tag: AES.GCM.Tag(data: tag)
)
let decrypted = try AES.GCM.open(sealedBox, using: key)
print("Decrypted \(encryptedData.count) bytes")
return decrypted
} catch {
print("Decryption failed: \(error)")
return nil
}
}
static func generateKey() -> SymmetricKey {
return SymmetricKey(size: .keyBitLength(256))
}
}
// 3. RSA Key Generation
class RSAKeyGeneration {
static func generateKeyPair(keySize: Int = 2048) -> (privateKey: SecKey, publicKey: SecKey)? {
print("\n--- RSA Key Generation ---")
let publicKeyAttrs: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: keySize,
kSecPublicKeyAttrs as String: [
kSecAttrIsPermanent as String: false
]
]
let privateKeyAttrs: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: keySize,
kSecAttrIsPermanent as String: false
]
let keyPairAttrs: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: keySize,
kSecPublicKeyAttrs as String: publicKeyAttrs,
kSecPrivateKeyAttrs as String: privateKeyAttrs
]
var publicKey: SecKey?
var privateKey: SecKey?
let status = SecKeyGeneratePair(keyPairAttrs as CFDictionary, &publicKey, &privateKey)
guard status == errSecSuccess,
let pubKey = publicKey,
let privKey = privateKey else {
print("Key generation failed: \(status)")
return nil
}
print("Generated RSA \(keySize)-bit key pair")
return (privKey, pubKey)
}
static func exportPublicKey(_ publicKey: SecKey) -> Data? {
var error: Unmanaged<CFError>?
guard let data = SecKeyCopyExternalRepresentation(publicKey, &error) as Data? else {
return nil
}
return data
}
static func exportPrivateKey(_ privateKey: SecKey) -> Data? {
var error: Unmanaged<CFError>?
guard let data = SecKeyCopyExternalRepresentation(privateKey, &error) as Data? else {
return nil
}
return data
}
}
// 4. RSA Encryption/Decryption
class RSAEncryption {
static func encrypt(_ data: Data, with publicKey: SecKey) -> Data? {
print("\n--- RSA Encryption ---")
var error: Unmanaged<CFError>?
guard let encrypted = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, data as CFData, &error) as Data? else {
print("Encryption failed")
if let error = error {
print("Error: \(error.takeRetainedValue() as Error)")
}
return nil
}
print("Encrypted \(data.count) bytes to \(encrypted.count) bytes")
return encrypted
}
static func decrypt(_ encryptedData: Data, with privateKey: SecKey) -> Data? {
print("\n--- RSA Decryption ---")
var error: Unmanaged<CFError>?
guard let decrypted = SecKeyCreateDecryptedData(privateKey, .rsaEncryptionPKCS1, encryptedData as CFData, &error) as Data? else {
print("Decryption failed")
if let error = error {
print("Error: \(error.takeRetainedValue() as Error)")
}
return nil
}
print("Decrypted \(encryptedData.count) bytes to \(decrypted.count) bytes")
return decrypted
}
static func encryptString(_ string: String, with publicKey: SecKey) -> Data? {
guard let data = string.data(using: .utf8) else {
return nil
}
return encrypt(data, with: publicKey)
}
static func decryptToString(_ encryptedData: Data, with privateKey: SecKey) -> String? {
guard let decryptedData = decrypt(encryptedData, with: privateKey) else {
return nil
}
return String(data: decryptedData, encoding: .utf8)
}
}
// 5. Digital Signature
class DigitalSignature {
static func sign(_ data: Data, with privateKey: SecKey) -> Data? {
print("\n--- Create Digital Signature ---")
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(privateKey, .rsaSignatureDigestPKCS1v15SHA256, data as CFData, &error) as Data? else {
print("Signing failed")
if let error = error {
print("Error: \(error.takeRetainedValue() as Error)")
}
return nil
}
print("Created signature (\(signature.count) bytes)")
return signature
}
static func verify(_ data: Data, signature: Data, with publicKey: SecKey) -> Bool {
print("\n--- Verify Digital Signature ---")
var error: Unmanaged<CFError>?
let isValid = SecKeyVerifySignature(publicKey, .rsaSignatureDigestPKCS1v15SHA256, data as CFData, signature as CFData, &error)
if isValid {
print("Signature is valid")
} else {
print("Signature is invalid")
if let error = error {
print("Error: \(error.takeRetainedValue() as Error)")
}
}
return isValid
}
}
// 6. Key Derivation
class KeyDerivation {
static func deriveKey(from password: String, salt: Data, iterations: Int = 10000, keyLength: Int = 32) -> Data? {
print("\n--- PBKDF2 Key Derivation ---")
let passwordData = password.data(using: .utf8)!
var derivedKey = Data(count: keyLength)
let status = derivedKey.withUnsafeMutableBytes { derivedKeyBytes in
passwordData.withUnsafeBytes { passwordBytes in
salt.withUnsafeBytes { saltBytes in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
passwordBytes.baseAddress, passwordData.count,
saltBytes.baseAddress, salt.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
UInt32(iterations),
derivedKeyBytes.baseAddress, keyLength
)
}
}
}
guard status == kCCSuccess else {
print("Key derivation failed: \(status)")
return nil
}
print("Derived \(keyLength) byte key from password (\(iterations) iterations)")
return derivedKey
}
}
// 7. Secure Key Storage
class SecureKeyStorage {
static func saveKey(_ keyData: Data, for account: String) -> Bool {
print("\n--- Save Key to Keychain ---")
let query: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrAccount as String: account,
kSecValueData as String: keyData,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
// Delete existing
SecItemDelete(query as CFDictionary)
// Add new
let status = SecItemAdd(query as CFDictionary, nil)
if status == errSecSuccess {
print("Saved key for account: \(account)")
return true
} else {
print("Failed to save key: \(status)")
return false
}
}
static func loadKey(for account: String) -> Data? {
print("\n--- Load Key from Keychain ---")
let query: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrAccount as String: account,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
}
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
guard status == errSecSuccess,
let keyData = result as? Data else {
print("Failed to load key: \(status)")
return nil
}
print("Loaded key for account: \(account)")
return keyData
}
static func deleteKey(for account: String) -> Bool {
print("\n--- Delete Key from Keychain ---")
let query: [String: Any] = [
kSecClass as String: kSecClassKey,
kSecAttrAccount as String: account
]
let status = SecItemDelete(query as CFDictionary)
if status == errSecSuccess {
print("Deleted key for account: \(account)")
return true
} else {
print("Failed to delete key: \(status)")
return false
}
}
}
// 8. Hybrid Encryption (RSA + AES)
class HybridEncryption {
static func encryptData(_ data: Data, with publicKey: SecKey) -> (encryptedKey: Data, iv: Data, encryptedData: Data)? {
print("\n--- Hybrid Encryption ---")
// Generate random AES key and IV
let aesKey = AESGCMEncryption.generateKey()
let symmetricKeyData = aesKey.withUnsafeBytes { Data($0) }
let iv = AESCBCEncryption.generateRandomIV()
// Encrypt data with AES
let aesEncryptor = AESGCMEncryption(key: aesKey)
guard let (encryptedData, nonce, tag) = aesEncryptor.encrypt(data) else {
return nil
}
// Encrypt AES key with RSA
guard let encryptedKey = RSAEncryption.encrypt(symmetricKeyData, with: publicKey) else {
return nil
}
print("Hybrid encryption complete")
print(" AES key size: \(symmetricKeyData.count) bytes")
print(" Encrypted AES key: \(encryptedKey.count) bytes")
print(" Encrypted data: \(encryptedData.count) bytes")
return (encryptedKey, nonce + iv, encryptedData + tag)
}
static func decryptData(encryptedKey: Data, iv: Data, encryptedData: Data, with privateKey: SecKey) -> Data? {
print("\n--- Hybrid Decryption ---")
// Decrypt AES key with RSA
guard let symmetricKeyData = RSAEncryption.decrypt(encryptedKey, with: privateKey) else {
return nil
}
let symmetricKey = SymmetricKey(data: symmetricKeyData)
// Decrypt data with AES
let aesDecryptor = AESGCMEncryption(key: symmetricKey)
let nonce = iv.prefix(12)
let tag = encryptedData.suffix(16)
let ciphertext = encryptedData.dropLast(16)
guard let decryptedData = aesDecryptor.decrypt(
Data(ciphertext),
nonce: Data(nonce),
tag: Data(tag)
) else {
return nil
}
print("Hybrid decryption complete")
return decryptedData
}
}
// 9. Certificate Handling
class CertificateHandling {
static func loadCertificate(from path: String) -> SecCertificate? {
print("\n--- Load Certificate ---")
guard let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
print("Cannot read certificate file")
return nil
}
let certificate = SecCertificateCreateWithData(nil, certificateData as CFData)
if let cert = certificate {
print("Loaded certificate from: \(path)")
// Get certificate summary
if let summary = SecCertificateCopySubjectSummary(cert, nil) {
print("Subject: \(summary)")
}
}
return certificate
}
static func extractPublicKey(from certificate: SecCertificate) -> SecKey? {
print("\n--- Extract Public Key from Certificate ---")
var error: Unmanaged<CFError>?
guard let publicKey = SecCertificateCopyPublicKey(certificate, &error) else {
print("Failed to extract public key")
return nil
}
print("Extracted public key from certificate")
return publicKey
}
}
// 10. Random Number Generation
class RandomNumberGeneration {
static func generateRandomBytes(count: Int) -> Data {
print("\n--- Generate Random Bytes ---")
var bytes = Data(count: count)
_ = bytes.withUnsafeMutableBytes { bytesPtr in
SecRandomCopyBytes(kSecRandomDefault, count, bytesPtr.baseAddress)
}
let hexString = bytes.map { String(format: "%02x", $0) }.joined()
print("Generated \(count) random bytes")
print("Hex: \(hexString)")
return bytes
}
static func generateRandomString(length: Int) -> String {
print("\n--- Generate Random String ---")
let charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let randomBytes = generateRandomBytes(count: length)
let randomString = randomBytes.map { byte in
String(charset[Int(byte) % charset.count])
}.joined()
print("Generated random string: \(randomString)")
return randomString
}
}
// Main demonstration
func demonstrateEncryptionDecryption() {
print("=== macOS Swift Encryption/Decryption Examples ===")
// AES-CBC
let aesKey = AESCBCEncryption.generateRandomKey()
let aesIV = AESCBCEncryption.generateRandomIV()
let aesCBC = AESCBCEncryption(key: aesKey, iv: aesIV)
let testData = "Hello, World! This is a secret message."
if let testData = testData.data(using: .utf8) {
if let encrypted = aesCBC.encrypt(testData) {
if let decrypted = aesCBC.decrypt(encrypted) {
let decryptedString = String(data: decrypted, encoding: .utf8)
print("Decrypted: \(decryptedString ?? "")")
}
}
}
// AES-GCM
let aesGCMKey = AESGCMEncryption.generateKey()
let aesGCM = AESGCMEncryption(key: aesGCMKey)
if let testData = testData.data(using: .utf8) {
if let (enc, nonce, tag) = aesGCM.encrypt(testData) {
if let dec = aesGCM.decrypt(encryptedData: enc, nonce: nonce, tag: tag) {
print("Decrypted: \(String(data: dec, encoding: .utf8) ?? "")")
}
}
}
// RSA
if let (privateKey, publicKey) = RSAKeyGeneration.generateKeyPair() {
let message = "Secret message"
if let encrypted = RSAEncryption.encryptString(message, with: publicKey) {
if let decrypted = RSAEncryption.decryptToString(encrypted, with: privateKey) {
print("RSA decrypted: \(decrypted)")
}
}
// Signature
if let data = message.data(using: .utf8) {
if let signature = DigitalSignature.sign(data, with: privateKey) {
_ = DigitalSignature.verify(data, signature: signature, with: publicKey)
}
}
}
// Key derivation
let salt = RandomNumberGeneration.generateRandomBytes(count: 16)
if let derivedKey = KeyDerivation.deriveKey(from: "Password123", salt: salt) {
print("Derived key: \(derivedKey.base64EncodedString())")
}
// Key storage
let testKey = RandomNumberGeneration.generateRandomBytes(count: 32)
SecureKeyStorage.saveKey(testKey, for: "test_account")
if let loadedKey = SecureKeyStorage.loadKey(for: "test_account") {
print("Loaded key matches: \(loadedKey == testKey)")
}
SecureKeyStorage.deleteKey(for: "test_account")
// Random generation
RandomNumberGeneration.generateRandomBytes(count: 16)
RandomNumberGeneration.generateRandomString(length: 12)
print("\n=== All Encryption/Decryption Examples Completed ===")
}
// Run demonstration
demonstrateEncryptionDecryption()
💻 Цифровые Подписи swift
🔴 complex
⭐⭐⭐⭐
Создавать и проверять цифровые подписи используя алгоритмы RSA и ECDSA
⏱️ 40 min
🏷️ swift, macos, cryptography, signatures
Prerequisites:
Advanced Swift, CryptoKit, Security framework, Cryptography concepts
// macOS Swift Digital Signatures Examples
// Using CryptoKit and Security framework
import Foundation
import CryptoKit
import Security
// 1. RSA Digital Signature
class RSASignature {
private var privateKey: SecKey
private var publicKey: SecKey
init?(keySize: Int = 2048) {
print("\n--- RSA Signature Setup ---")
guard let (priv, pub) = RSAKeyGeneration.generateKeyPair(keySize: keySize) else {
return nil
}
self.privateKey = priv
self.publicKey = pub
print("RSA \(keySize)-bit keys generated for signing")
}
func sign(data: Data) -> Data? {
print("\n--- RSA Sign ---")
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(
privateKey,
.rsaSignatureDigestPKCS1v15SHA256,
data as CFData,
&error
) as Data? else {
print("Signing failed")
if let err = error {
print("Error: \(err.takeRetainedValue() as Error)")
}
return nil
}
print("Created RSA signature (\(signature.count) bytes)")
return signature
}
func verify(data: Data, signature: Data) -> Bool {
print("\n--- RSA Verify ---")
var error: Unmanaged<CFError>?
let isValid = SecKeyVerifySignature(
publicKey,
.rsaSignatureDigestPKCS1v15SHA256,
data as CFData,
signature as CFData,
&error
)
if isValid {
print("RSA signature is valid")
} else {
print("RSA signature is invalid")
if let err = error {
print("Error: \(err.takeRetainedValue() as Error)")
}
}
return isValid
}
func signString(_ string: String) -> Data? {
guard let data = string.data(using: .utf8) else {
print("Cannot convert string to data")
return nil
}
return sign(data: data)
}
func verifyString(_ string: String, signature: Data) -> Bool {
guard let data = string.data(using: .utf8) else {
return false
}
return verify(data: data, signature: signature)
}
}
// 2. ECDSA Signature (P-256)
class ECDSASignature {
private var privateKey: P256.KeyAgreement.PrivateKey
private var publicKey: P256.KeyAgreement.PublicKey
init() {
print("\n--- ECDSA P-256 Setup ---")
// Generate key pair
privateKey = P256.Signing.PrivateKey()
publicKey = privateKey.publicKey
print("ECDSA P-256 key pair generated")
}
func sign(data: Data) -> Data? {
print("\n--- ECDSA Sign ---")
do {
let signingKey = P256.Signing.PrivateKey(rawRepresentation: privateKey.rawRepresentation)
let signature = try signingKey.signature(for: data)
print("Created ECDSA signature")
return Data(signature.rawRepresentation)
} catch {
print("ECDSA signing failed: \(error)")
return nil
}
}
func verify(data: Data, signature: Data) -> Bool {
print("\n--- ECDSA Verify ---")
guard let sig = try? P256.Signing.ECDSASignature(rawRepresentation: signature) else {
print("Invalid signature format")
return false
}
let verifyingKey = P256.Signing.PublicKey(rawRepresentation: publicKey.rawRepresentation)
if verifyingKey.isValidSignature(sig, for: data) {
print("ECDSA signature is valid")
return true
} else {
print("ECDSA signature is invalid")
return false
}
}
}
// 3. Ed25519 Signature (Modern, Fast)
class Ed25519Signature {
private var privateKey: Ed25519.Signing.PrivateKey
private var publicKey: Ed25519.Signing.PublicKey
init() {
print("\n--- Ed25519 Setup ---")
// Generate key pair
privateKey = Ed25519.Signing.PrivateKey()
publicKey = privateKey.publicKey
print("Ed25519 key pair generated")
}
func sign(data: Data) -> Data? {
print("\n--- Ed25519 Sign ---")
do {
let signature = try privateKey.signature(for: data)
print("Created Ed25519 signature")
return Data(signature.rawRepresentation)
} catch {
print("Ed25519 signing failed: \(error)")
return nil
}
}
func verify(data: Data, signature: Data) -> Bool {
print("\n--- Ed25519 Verify ---")
guard let sig = try? Ed25519.Signing.Signature(rawRepresentation: signature) else {
print("Invalid signature format")
return false
}
if publicKey.isValidSignature(sig, for: data) {
print("Ed25519 signature is valid")
return true
} else {
print("Ed25519 signature is invalid")
return false
}
}
func exportPublicKey() -> String {
return publicKey.rawRepresentation.base64EncodedString()
}
func exportPrivateKey() -> String {
return privateKey.rawRepresentation.base64EncodedString()
}
static func importPublicKey(base64Key: String) -> Ed25519.Signing.PublicKey? {
guard let data = Data(base64Encoded: base64Key) else {
return nil
}
return try? Ed25519.Signing.PublicKey(rawRepresentation: data)
}
}
// 4. HMAC-based Signature
class HMACSignature {
static func sign(key: Data, message: Data) -> Data {
print("\n--- HMAC Sign ---")
let symmetricKey = SymmetricKey(data: key)
let authenticationCode = HMAC<SHA256>.authenticationCode(for: message, using: symmetricKey)
print("Created HMAC signature")
return Data(authenticationCode)
}
static func verify(key: Data, message: Data, signature: Data) -> Bool {
print("\n--- HMAC Verify ---")
let computedSignature = sign(key: key, message: message)
let isValid = computedSignature == signature
if isValid {
print("HMAC signature is valid")
} else {
print("HMAC signature is invalid")
}
return isValid
}
}
// 5. Signature with Timestamp
class TimestampedSignature {
static func signWithTimestamp(data: Data, using privateKey: SecKey) -> (signature: Data, timestamp: Date)? {
print("\n--- Sign with Timestamp ---")
let timestamp = Date()
// Combine data and timestamp
var combined = data
combined.append(timestamp.timeIntervalSince1970.description.data(using: .utf8)!)
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(
privateKey,
.rsaSignatureDigestPKCS1v15SHA256,
combined as CFData,
&error
) as Data? else {
print("Signing with timestamp failed")
return nil
}
print("Created timestamped signature: \(timestamp)")
return (signature, timestamp)
}
static func verifyWithTimestamp(data: Data, signature: Data, timestamp: Date, publicKey: SecKey, maxAge: TimeInterval = 300) -> Bool {
print("\n--- Verify Timestamped Signature ---")
// Check timestamp age
let age = Date().timeIntervalSince(timestamp)
if age > maxAge {
print("Signature expired (\(Int(age))s old)")
return false
}
// Combine data and timestamp
var combined = data
combined.append(timestamp.timeIntervalSince1970.description.data(using: .utf8)!)
var error: Unmanaged<CFError>?
let isValid = SecKeyVerifySignature(
publicKey,
.rsaSignatureDigestPKCS1v15SHA256,
combined as CFData,
signature as CFData,
&error
)
if isValid {
print("Timestamped signature is valid (\(Int(age))s old)")
} else {
print("Timestamped signature is invalid")
}
return isValid
}
}
// 6. Detached Signature
class DetachedSignature {
static func createDetachedSignature(data: Data, using privateKey: SecKey) -> Data? {
print("\n--- Create Detached Signature ---")
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(
privateKey,
.rsaSignatureDigestPKCS1v15SHA256,
data as CFData,
&error
) as Data? else {
print("Failed to create detached signature")
return nil
}
print("Created detached signature (\(signature.count) bytes)")
return signature
}
static func verifyDetachedSignature(data: Data, signature: Data, publicKey: SecKey) -> Bool {
print("\n--- Verify Detached Signature ---")
var error: Unmanaged<CFError>?
let isValid = SecKeyVerifySignature(
publicKey,
.rsaSignatureDigestPKCS1v15SHA256,
data as CFData,
signature as CFData,
&error
)
if isValid {
print("Detached signature is valid")
} else {
print("Detached signature is invalid")
}
return isValid
}
}
// 7. Signature with Hashing
class HashedSignature {
static func signHashed(data: Data, using privateKey: SecKey) -> Data? {
print("\n--- Sign Hashed Data ---")
// First hash the data
let digest = SHA256.hash(data: data)
print("Data hash: \(digest.compactMap { String(format: "%02x", $0) }.joined())")
// Then sign the hash
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(
privateKey,
.rsaSignatureDigestPKCS1v15SHA256,
Data(digest) as CFData,
&error
) as Data? else {
print("Failed to sign hashed data")
return nil
}
print("Created signature for hashed data")
return signature
}
static func verifyHashed(data: Data, signature: Data, publicKey: SecKey) -> Bool {
print("\n--- Verify Hashed Signature ---")
var error: Unmanaged<CFError>?
let isValid = SecKeyVerifySignature(
publicKey,
.rsaSignatureDigestPKCS1v15SHA256,
data as CFData,
signature as CFData,
&error
)
if isValid {
print("Hashed signature is valid")
} else {
print("Hashed signature is invalid")
}
return isValid
}
}
// 8. Multi-Signature
class MultiSignature {
static func createMultiSignature(data: Data, signers: [SecKey]) -> [Data]? {
print("\n--- Create Multi-Signature ---")
var signatures: [Data] = []
for (index, privateKey) in signers.enumerated() {
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(
privateKey,
.rsaSignatureDigestPKCS1v15SHA256,
data as CFData,
&error
) as Data? else {
print("Signer \(index) failed")
return nil
}
signatures.append(signature)
print("Signer \(index) signed successfully")
}
print("Created \(signatures.count) signatures")
return signatures
}
static func verifyMultiSignature(data: Data, signatures: [Data], publicKeys: [SecKey]) -> Int {
print("\n--- Verify Multi-Signature ---")
var validCount = 0
for (index, signature) in signatures.enumerated() {
guard index < publicKeys.count else {
continue
}
var error: Unmanaged<CFError>?
let isValid = SecKeyVerifySignature(
publicKeys[index],
.rsaSignatureDigestPKCS1v15SHA256,
data as CFData,
signature as CFData,
&error
)
if isValid {
validCount += 1
print("Signature \(index) is valid")
} else {
print("Signature \(index) is invalid")
}
}
print("Multi-signature valid: \(validCount)/\(signatures.count)")
return validCount
}
}
// 9. Blind Signature
class BlindSignature {
// Simplified blind signature demonstration
// Real blind signatures require complex cryptographic operations
static func createBlindSignature(challenge: Data, using privateKey: SecKey) -> Data? {
print("\n--- Create Blind Signature ---")
// In a real implementation, the challenge would be blinded first
// For demonstration, we just sign the challenge directly
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(
privateKey,
.rsaSignatureDigestPKCS1v15SHA256,
challenge as CFData,
&error
) as Data? else {
print("Failed to create blind signature")
return nil
}
print("Created blind signature (simplified)")
return signature
}
}
// 10. Signature Export/Import
class SignatureExport {
static func exportSignature(_ signature: Data, format: SignatureFormat) -> String {
print("\n--- Export Signature ---")
let exported: String
switch format {
case .base64:
exported = signature.base64EncodedString()
case .hex:
exported = signature.compactMap { String(format: "%02x", $0) }.joined()
case .decimal:
exported = signature.map { String($0) }.joined(separator: ",")
}
print("Exported signature (\(format)): \(exported.prefix(64))...)")
return exported
}
static func importSignature(_ string: String, format: SignatureFormat) -> Data? {
print("\n--- Import Signature ---")
let data: Data?
switch format {
case .base64:
data = Data(base64Encoded: string)
case .hex:
data = Data(hexString: string)
case .decimal:
let bytes = string.split(separator: ",").compactMap { UInt8($0) }
data = Data(bytes)
}
if let signature = data {
print("Imported signature (\(signature.count) bytes)")
} else {
print("Failed to import signature")
}
return data
}
enum SignatureFormat: String {
case base64 = "Base64"
case hex = "Hex"
case decimal = "Decimal"
}
}
// Main demonstration
func demonstrateDigitalSignatures() {
print("=== macOS Swift Digital Signatures Examples ===")
let testData = "Important message to sign".data(using: .utf8)!
// RSA Signature
if let rsaSigner = RSASignature(keySize: 2048) {
if let rsaSig = rsaSigner.sign(data: testData) {
_ = rsaSigner.verify(data: testData, signature: rsaSig)
}
if let rsaStringSig = rsaSigner.signString("Test string") {
_ = rsaSigner.verifyString("Test string", signature: rsaStringSig)
}
}
// ECDSA Signature
let ecdsaSigner = ECDSASignature()
if let ecdsaSig = ecdsaSigner.sign(data: testData) {
_ = ecdsaSigner.verify(data: testData, signature: ecdsaSig)
}
// Ed25519 Signature
let edSigner = Ed25519Signature()
if let edSig = edSigner.sign(data: testData) {
_ = edSigner.verify(data: testData, signature: edSig)
}
print("Public key: \(edSigner.exportPublicKey().prefix(32))...")
// HMAC Signature
let hmacKey = Data("secret_key".utf8)
let hmacSig = HMACSignature.sign(key: hmacKey, message: testData)
_ = HMACSignature.verify(key: hmacKey, message: testData, signature: hmacSig)
// Detached Signature
if let rsaSigner = RSASignature(keySize: 2048) {
let detachedSig = DetachedSignature.createDetachedSignature(data: testData, using: rsaSigner.privateKey)
if let sig = detachedSig {
_ = DetachedSignature.verifyDetachedSignature(data: testData, signature: sig, publicKey: rsaSigner.publicKey)
}
}
// Multi-signature
if let signer1 = RSAKeyGeneration.generateKeyPair(keySize: 2048),
let signer2 = RSAKeyGeneration.generateKeyPair(keySize: 2048) {
let multiSigs = MultiSignature.createMultiSignature(data: testData, signers: [signer1.privateKey, signer2.privateKey])
if let sigs = multiSigs {
_ = MultiSignature.verifyMultiSignature(data: testData, signatures: sigs, publicKeys: [signer1.publicKey, signer2.publicKey])
}
}
print("\n=== All Digital Signature Examples Completed ===")
}
// Run demonstration
demonstrateDigitalSignatures()