Skip to content

Instantly share code, notes, and snippets.

@felipebweber
Last active March 8, 2025 13:06
Show Gist options
  • Save felipebweber/fe0d7dff40f65655e8302de2eed705bc to your computer and use it in GitHub Desktop.
Save felipebweber/fe0d7dff40f65655e8302de2eed705bc to your computer and use it in GitHub Desktop.
Crypt-ptbr
import CryptoKit
import Foundation
import CommonCrypto
struct Crypt {
private static let secretKey = "s3cr3tKeY!"
static func deriveKey(timestamp: Int) throws -> SymmetricKey {
let salt = "\(timestamp)".data(using: .utf8)!
let password = secretKey.data(using: .utf8)!
var derivedKey = [UInt8](repeating: 0, count: 32)
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password.withUnsafeBytes { $0.baseAddress?.assumingMemoryBound(to: Int8.self) },
password.count,
salt.withUnsafeBytes { $0.baseAddress?.assumingMemoryBound(to: UInt8.self) },
salt.count,
CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256),
UInt32(100000),
&derivedKey,
derivedKey.count
)
return SymmetricKey(data: Data(derivedKey))
}
static func encrypt(data: String) throws -> String {
let timestamp = Int(Date().timeIntervalSince1970)
let key = try deriveKey(timestamp: timestamp)
let iv = AES.GCM.Nonce()
let sealedBox = try AES.GCM.seal(data.data(using: .utf8)!, using: key, nonce: iv)
let encryptedData = sealedBox.ciphertext
let tag = sealedBox.tag
// Calcular HMAC (encryptedData + iv + timestamp)
let hmacKey = SymmetricKey(data: key.withUnsafeBytes { Data($0) })
let hmac = HMAC<SHA256>.authenticationCode(
for: encryptedData + iv.withUnsafeBytes { Data($0) } + Data("\(timestamp)".utf8),
using: hmacKey
)
// Formatar payload: encryptedData|iv|tag|hmac
let payload = [
encryptedData.base64EncodedString(),
iv.withUnsafeBytes { Data($0) }.base64EncodedString(),
tag.base64EncodedString(),
Data(hmac).base64EncodedString()
].joined(separator: "|")
return payload
}
static func decrypt(payload: String) throws -> String {
let parts = payload.components(separatedBy: "|")
guard parts.count == 4 else { throw NSError(domain: "Invalid payload", code: 1) }
let encryptedData = Data(base64Encoded: parts[0])!
let ivData = Data(base64Encoded: parts[1])!
let tag = Data(base64Encoded: parts[2])!
let hmac = Data(base64Encoded: parts[3])!
let timestamp = Int(Date().timeIntervalSince1970)
// Verificar timestamp
if abs(Int(Date().timeIntervalSince1970) - timestamp) > 300 {
throw NSError(domain: "Timestamp expirado", code: 2)
}
let key = try deriveKey(timestamp: timestamp)
// Verificar HMAC
let hmacKey = SymmetricKey(data: key.withUnsafeBytes { Data($0) })
let calculatedHmac = HMAC<SHA256>.authenticationCode(
for: encryptedData + ivData + Data("\(timestamp)".utf8),
using: hmacKey
)
guard hmac == Data(calculatedHmac) else {
throw NSError(domain: "HMAC inválido", code: 3)
}
// Descriptografar
let sealedBox = try AES.GCM.SealedBox(
nonce: AES.GCM.Nonce(data: ivData),
ciphertext: encryptedData,
tag: tag
)
let decryptedData = try AES.GCM.open(sealedBox, using: key)
return String(data: decryptedData, encoding: .utf8)!
}
}
// Como usar
let encrypted = try! Crypt.encrypt(data: "Dados secretos")
print("Encrypted data: \(encrypted)")
let decrypted = try! Crypt.decrypt(payload: encrypted)
print("Decrypted data: \(decrypted)")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment