Skip to content

Commit

Permalink
Refactored Polish
Browse files Browse the repository at this point in the history
  • Loading branch information
consuelita committed Dec 18, 2018
1 parent 2e89a48 commit 620fd88
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 156 deletions.
35 changes: 35 additions & 0 deletions Sources/ReplicantSwift/Models/ReplicantClientModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Foundation
import Security
import CommonCrypto

public struct ReplicantClientModel
{
public let polish: PolishClientModel
public var config: ReplicantConfig
public var toneBurst: ToneBurst?

public init?(withConfig config: ReplicantConfig)
{
guard let polish = PolishClientModel(serverPublicKeyData: config.serverPublicKey)
else
{
return nil
}

if let addSequences = config.addSequences, let removeSequences = config.removeSequences
{
self.toneBurst = ToneBurst(addSequences: addSequences, removeSequences: removeSequences)
}

self.config = config
self.polish = polish
}
}

extension Data
{
public var bytes: Array<UInt8>
{
return Array(self)
}
}
32 changes: 32 additions & 0 deletions Sources/ReplicantSwift/Models/ReplicantServerModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// ReplicantServerModel.swift
// ReplicantSwift
//
// Created by Adelita Schule on 12/18/18.
//

import Foundation

public struct ReplicantServerModel
{
public var polish: PolishServerModel
public var config: ReplicantServerConfig
public var toneBurst: ToneBurst?

public init?(withConfig config: ReplicantServerConfig)
{
guard let polish = PolishServerModel()
else
{
return nil
}

if let addSequences = config.addSequences, let removeSequences = config.removeSequences
{
self.toneBurst = ToneBurst(addSequences: addSequences, removeSequences: removeSequences)
}

self.config = config
self.polish = polish
}
}
43 changes: 43 additions & 0 deletions Sources/ReplicantSwift/Polish/PolishClientModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// PolishClientModel.swift
// ReplicantSwift
//
// Created by Adelita Schule on 12/18/18.
//

import Foundation

public class PolishClientModel
{
let controller = PolishController()

public var serverPublicKey: SecKey
public var publicKey: SecKey
public var privateKey: SecKey

public init?(serverPublicKeyData: Data)
{
controller.deleteKeys()

guard let sPublicKey = controller.decodeKey(fromData: serverPublicKeyData)
else
{
return nil
}

guard let newKeyPair = controller.generateKeyPair()
else
{
return nil
}

self.serverPublicKey = sPublicKey
self.privateKey = newKeyPair.privateKey
self.publicKey = newKeyPair.publicKey
}

deinit
{
controller.deleteKeys()
}
}
Original file line number Diff line number Diff line change
@@ -1,75 +1,93 @@
//
// Polish.swift
// PolishController.swift
// ReplicantSwift
//
// Created by Adelita Schule on 11/9/18.
// Created by Adelita Schule on 12/18/18.
//

import Foundation
import Security
import CommonCrypto

public let keySize = 64
public let aesOverheadSize = 81

public class Polish: NSObject
public struct PolishController
{
static let clientTag = "org.operatorfoundation.replicant.client".data(using: .utf8)!
let algorithm: SecKeyAlgorithm = .eciesEncryptionCofactorVariableIVX963SHA256AESGCM
let polishTag = "org.operatorfoundation.replicant.polish".data(using: .utf8)!

public var recipientPublicKey: SecKey?
public var publicKey: SecKey
public var privateKey: SecKey

public init?(recipientPublicKeyData: Data?)
/// Decode data to get public key. This only decodes key data that is NOT padded.
public func decodeKey(fromData publicKeyData: Data) -> SecKey?
{
Polish.deleteKeys()
var error: Unmanaged<CFError>?

if let rPublicKeyData = recipientPublicKeyData
{
recipientPublicKey = Polish.decodeKey(fromData: rPublicKeyData)
}
let options: [String: Any] = [kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
kSecAttrKeySizeInBits as String: 256]

guard let newKeyPair = Polish.generateKeyPair()
else
guard let decodedPublicKey = SecKeyCreateWithData(publicKeyData as CFData, options as CFDictionary, &error)
else
{
print("\nUnable to decode server public key: \(error!.takeRetainedValue() as Error)\n")
return nil
}

self.privateKey = newKeyPair.privateKey
self.publicKey = newKeyPair.publicKey
return decodedPublicKey
}

deinit
public func generatePrivateKey() -> SecKey?
{
Polish.deleteKeys()
// Generate private key
var error: Unmanaged<CFError>?
let attributes = self.generateKeyAttributesDictionary()

guard let privateKey = SecKeyCreateRandomKey(attributes, &error)
else
{
print("\nUnable to generate the client private key: \(error!.takeRetainedValue() as Error)\n")
return nil
}

return privateKey
}

static func deleteKeys()
func generatePublicKey(usingPrivateKey privateKey: SecKey) -> SecKey?
{
//Remove client keys from secure enclave
let query = Polish.generateKeyAttributesDictionary()
let deleteStatus = SecItemDelete(query)
print("\nAttempted to delete key from secure enclave. Status: \(deleteStatus)\n")
guard let publicKey = SecKeyCopyPublicKey(privateKey)
else
{
print("\nUnable to generate a public key from the provided private key.\n")
return nil
}

return publicKey
}

public static func generatePrivateKey() -> SecKey?
func generateKeyPair() -> (privateKey: SecKey, publicKey: SecKey)?
{
// Generate private key
var error: Unmanaged<CFError>?
let attributes = Polish.generateKeyAttributesDictionary()
guard let privateKey = generatePrivateKey()
else
{
return nil
}

guard let alicePrivate = SecKeyCreateRandomKey(attributes, &error)
guard let publicKey = generatePublicKey(usingPrivateKey: privateKey)
else
{
print("\nUnable to generate the client private key: \(error!.takeRetainedValue() as Error)\n")
return nil
}

return alicePrivate
return (privateKey, publicKey)
}

func deleteKeys()
{
//Remove client keys from secure enclave
let query = generateKeyAttributesDictionary()
let deleteStatus = SecItemDelete(query)
print("\nAttempted to delete key from secure enclave. Status: \(deleteStatus)\n")
}

static func generateKeyAttributesDictionary() -> CFDictionary
func generateKeyAttributesDictionary() -> CFDictionary
{
let access = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleAlwaysThisDeviceOnly,
Expand All @@ -78,7 +96,7 @@ public class Polish: NSObject

let privateKeyAttributes: [String: Any] = [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: Polish.clientTag,
kSecAttrApplicationTag as String: polishTag,
//kSecAttrAccessControl as String: access
]

Expand All @@ -92,35 +110,6 @@ public class Polish: NSObject
return attributes as CFDictionary
}

static func generatePublicKey(usingPrivateKey privateKey: SecKey) -> SecKey?
{
guard let alicePublic = SecKeyCopyPublicKey(privateKey)
else
{
print("\nUnable to generate a public key from the provided private key.\n")
return nil
}

return alicePublic
}

static func generateKeyPair() -> (privateKey: SecKey, publicKey: SecKey)?
{
guard let privateKey = generatePrivateKey()
else
{
return nil
}

guard let publicKey = generatePublicKey(usingPrivateKey: privateKey)
else
{
return nil
}

return (privateKey, publicKey)
}

/// This is the format needed to send the key to the server.
public func generateAndEncryptPaddedKeyData(fromKey key: SecKey, withChunkSize chunkSize: Int, usingServerKey serverKey: SecKey) -> Data?
{
Expand All @@ -145,32 +134,15 @@ public class Polish: NSObject

// Encrypt the key
guard let encryptedKeyData = encrypt(payload: newKeyData, usingPublicKey: serverKey)
else
else
{
return nil
}

return encryptedKeyData
}

/// Decode data to get public key. This only decodes key data that is NOT padded.
public static func decodeKey(fromData publicKeyData: Data) -> SecKey?
{
var error: Unmanaged<CFError>?

let options: [String: Any] = [kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
kSecAttrKeySizeInBits as String: 256]

guard let decodedBobPublicKey = SecKeyCreateWithData(publicKeyData as CFData, options as CFDictionary, &error)
else
{
print("\nUnable to decode server public key: \(error!.takeRetainedValue() as Error)\n")
return nil
}

return decodedBobPublicKey
}
//MARK: Encryption

/// Encrypt payload
public func encrypt(payload: Data, usingPublicKey publicKey: SecKey) -> Data?
Expand Down Expand Up @@ -218,4 +190,3 @@ public class Polish: NSObject
}
}
}

36 changes: 36 additions & 0 deletions Sources/ReplicantSwift/Polish/PolishServerModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// PolishServerModel.swift
// ReplicantSwift
//
// Created by Adelita Schule on 12/18/18.
//

import Foundation

public class PolishServerModel
{
let controller = PolishController()

public var publicKey: SecKey
public var privateKey: SecKey


public init?()
{
controller.deleteKeys()

guard let newKeyPair = controller.generateKeyPair()
else
{
return nil
}

self.privateKey = newKeyPair.privateKey
self.publicKey = newKeyPair.publicKey
}

deinit
{
controller.deleteKeys()
}
}
Loading

0 comments on commit 620fd88

Please sign in to comment.