Delete history, allow retry
This commit is contained in:
14
Sesame/Extensions/Array+Extensions.swift
Normal file
14
Sesame/Extensions/Array+Extensions.swift
Normal file
@ -0,0 +1,14 @@
|
||||
import Foundation
|
||||
|
||||
extension Array {
|
||||
|
||||
func count(where closure: (Element) -> Bool) -> Int {
|
||||
var result = 0
|
||||
forEach { element in
|
||||
if closure(element) {
|
||||
result += 1
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
71
Sesame/Extensions/SymmetricKey+Extensions.swift
Normal file
71
Sesame/Extensions/SymmetricKey+Extensions.swift
Normal file
@ -0,0 +1,71 @@
|
||||
import Foundation
|
||||
import CryptoKit
|
||||
|
||||
extension SymmetricKey {
|
||||
|
||||
var data: Data {
|
||||
withUnsafeBytes { Data(Array($0)) }
|
||||
}
|
||||
|
||||
var base64: String {
|
||||
data.base64EncodedString()
|
||||
}
|
||||
|
||||
var displayString: String {
|
||||
data.hexEncoded.uppercased().split(by: 4).joined(separator: " ")
|
||||
}
|
||||
|
||||
var codeString: String {
|
||||
" {" +
|
||||
withUnsafeBytes {
|
||||
return Data(Array($0))
|
||||
}.map(String.init).joined(separator: ", ") +
|
||||
"},"
|
||||
}
|
||||
}
|
||||
|
||||
extension SHA256.Digest {
|
||||
|
||||
var hexEncoded: String {
|
||||
Data(map { $0 }).hexEncoded
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
|
||||
func split(by length: Int) -> [String] {
|
||||
var startIndex = self.startIndex
|
||||
var results = [Substring]()
|
||||
|
||||
while startIndex < self.endIndex {
|
||||
let endIndex = self.index(startIndex, offsetBy: length, limitedBy: self.endIndex) ?? self.endIndex
|
||||
results.append(self[startIndex..<endIndex])
|
||||
startIndex = endIndex
|
||||
}
|
||||
|
||||
return results.map { String($0) }
|
||||
}
|
||||
}
|
||||
|
||||
let protocolSalt = "CryptoKit Playgrounds Putting It Together".data(using: .utf8)!
|
||||
|
||||
/// Generates an ephemeral key agreement key and performs key agreement to get the shared secret and derive the symmetric encryption key.
|
||||
func encrypt(_ data: Data, to theirEncryptionKey: Curve25519.KeyAgreement.PublicKey, signedBy ourSigningKey: Curve25519.Signing.PrivateKey) throws ->
|
||||
(ephemeralPublicKeyData: Data, ciphertext: Data, signature: Data) {
|
||||
let ephemeralKey = Curve25519.KeyAgreement.PrivateKey()
|
||||
let ephemeralPublicKey = ephemeralKey.publicKey.rawRepresentation
|
||||
|
||||
let sharedSecret = try ephemeralKey.sharedSecretFromKeyAgreement(with: theirEncryptionKey)
|
||||
|
||||
let symmetricKey = sharedSecret.hkdfDerivedSymmetricKey(using: SHA256.self,
|
||||
salt: protocolSalt,
|
||||
sharedInfo: ephemeralPublicKey +
|
||||
theirEncryptionKey.rawRepresentation +
|
||||
ourSigningKey.publicKey.rawRepresentation,
|
||||
outputByteCount: 32)
|
||||
|
||||
let ciphertext = try ChaChaPoly.seal(data, using: symmetricKey).combined
|
||||
let signature = try ourSigningKey.signature(for: ciphertext + ephemeralPublicKey + theirEncryptionKey.rawRepresentation)
|
||||
|
||||
return (ephemeralPublicKey, ciphertext, signature)
|
||||
}
|
Reference in New Issue
Block a user