Skip to content

Commit

Permalink
Added Config
Browse files Browse the repository at this point in the history
  • Loading branch information
consuelita committed Nov 21, 2018
1 parent eab1b7e commit ca44491
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 372 deletions.
17 changes: 0 additions & 17 deletions Sources/ReplicantSwift/Constants.swift

This file was deleted.

64 changes: 0 additions & 64 deletions Sources/ReplicantSwift/CryptoHandshake.swift

This file was deleted.

150 changes: 58 additions & 92 deletions Sources/ReplicantSwift/Encryption.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,13 @@ import Foundation
import Security
import CommonCrypto

let keySize = 64
let keyDataSize = keySize + 1
let aesOverheadSize = 81

class Encryption: NSObject
{
let algorithm: SecKeyAlgorithm = .eciesEncryptionCofactorX963SHA256AESGCM
//var privateKey: SecKey

// public init?(withPrivateKey initKey: Data?)
// {
// if let providedKey = initKey
// {
// guard let secKey = Encryption.decodeKey(fromData: providedKey)
// else
// {
// print("\nFailed to initialize Replicant: Unable to create SecKey from key data provided.")
// return nil
// }
//
// privateKey = secKey
// }
// else
// {
// guard let newKey = Encryption.generatePrivateKey()
// else
// {
// return nil
// }
//
// privateKey = newKey
// }
//
// }

let algorithm: SecKeyAlgorithm = .eciesEncryptionCofactorVariableIVX963SHA256AESGCM

func generatePrivateKey() -> SecKey?
{
Expand Down Expand Up @@ -78,36 +54,75 @@ class Encryption: NSObject
/**
Generate a public key from the provided private key and encodes it as data.

- Returns: optional, encoded key as data
- Returns: optional, encoded key as SecKey
*/
func generatePublicKey(usingPrivateKey privateKey: SecKey) -> Data?
func generatePublicKey(usingPrivateKey privateKey: SecKey) -> SecKey?
{
var error: Unmanaged<CFError>?

guard let alicePublic = SecKeyCopyPublicKey(privateKey)
else
{
print("\nUnable to generate a public key from the provided private key.\n")
return nil
}

// Encode public key as data
guard let alicePublicData = SecKeyCopyExternalRepresentation(alicePublic, &error) as Data?
return alicePublic
}

public 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?
{
var error: Unmanaged<CFError>?
var newKeyData: Data

// Encode key as data
guard let keyData = SecKeyCopyExternalRepresentation(key, &error) as Data?
else
{
print("\nUnable to generate public key external representation: \(error!.takeRetainedValue() as Error)\n")
return nil
}

return alicePublicData
newKeyData = keyData

// Add padding if needed
if let padding = getKeyPadding(chunkSize: chunkSize)
{
newKeyData = keyData + padding
}

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

return encryptedKeyData
}

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

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

Expand Down Expand Up @@ -153,67 +168,18 @@ class Encryption: NSObject
return decryptedText
}

func cleanKeyData(keyData: Data) -> Data?
func getKeyPadding(chunkSize: Int) -> Data?
{
if keyData.count == keyDataSize
{
if keyData.first! == 4
{
// Strip the redundant 4 from the key data
let cleanKey = keyData.dropFirst()
return cleanKey
}
else
{
print("\nFailed to clean key: Data was 65 bytes but the first byte was not 4.\n")
return nil
}
}
else if keyData.count == keySize
{
print("\nReturning unchanged key data, the byte count was already 64.\n")
return keyData
}
else
let paddingSize = chunkSize - (keySize + aesOverheadSize)
if paddingSize > 0
{
print("Failed to clean key data: unexpected byte count of \(keyData.count)")
return nil
}
}

func getKeyPadding() -> Data?
{
var bytes = [UInt8](repeating: 0, count: chunkSize - keySize)
let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)

if status == errSecSuccess
{
// Always test the status.
print(bytes)
// Prints something different every time you run.
let bytes = [UInt8](repeating: 0, count: paddingSize)
return Data(array: bytes)
}
else
{
print("\nFailed to gnerate padding: \(status)\n")
return nil
}
}

func cleanAndPadKey(keyData: Data) -> Data?
{
guard let cleanKey = cleanKeyData(keyData: keyData)
else
{
return nil
}

guard let padding = getKeyPadding()
else
{
return nil
}

return cleanKey + padding
}
}

30 changes: 30 additions & 0 deletions Sources/ReplicantSwift/Models/SequenceModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// SequenceModel.swift
// ReplicantSwift
//
// Created by Adelita Schule on 11/15/18.
//

import Foundation

public struct SequenceModel
{
/// Byte Sequence.
var sequence: Data

/// Target sequence Length.
var length: UInt

init?(sequence: Data, length: UInt)
{
///FIXME: Is this still correct? Length must be no larger than 1440 bytes
if length == 0 || length > 65535
{
print("\nSequenceModel initialization failed: target length was either 0 or larger than 65535\n")
return nil
}

self.sequence = sequence
self.length = length
}
}
33 changes: 33 additions & 0 deletions Sources/ReplicantSwift/ReplicantConfig.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// ReplicantConfig.swift
// ReplicantSwift
//
// Created by Adelita Schule on 11/14/18.
//

import Foundation

public struct ReplicantConfig
{
var serverPublicKey: SecKey
var chunkSize: Int
var chunkTimeout: Int
var addSequences: [SequenceModel]?
var removeSequences: [SequenceModel]?


public init?(serverPublicKey: SecKey, chunkSize: Int, chunkTimeout: Int, addSequences: [SequenceModel]?, removeSequences: [SequenceModel]?)
{
guard chunkSize >= keySize + aesOverheadSize
else
{
print("\nUnable to initialize ReplicantConfig: chunkSize (\(chunkSize)) cannot be smaller than keySize + aesOverheadSize (\(keySize + aesOverheadSize))\n")
return nil
}
self.serverPublicKey = serverPublicKey
self.chunkSize = chunkSize
self.chunkTimeout = chunkTimeout
self.addSequences = addSequences
self.removeSequences = removeSequences
}
}
40 changes: 34 additions & 6 deletions Sources/ReplicantSwift/ReplicantSwift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,41 @@ import Foundation
import Security
import CommonCrypto

/**
* [Using Keys For Encryption](https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/using_keys_for_encryption),
* [Storing Keys in the Secure Enclave](https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_secure_enclave),
* [seckeyalgorithm](https://developer.apple.com/documentation/security/seckeyalgorithm/2091905-eciesencryptioncofactorx963sha25)
*/
public struct Replicant
{

let encryptor = Encryption()

var config: ReplicantConfig
var serverPublicKey: SecKey
var clientPublicKey: SecKey
var clientPrivateKey: SecKey

var toneBurst: ToneBurst?

public init?(withConfig config: ReplicantConfig)
{
guard let keyPair = encryptor.generateKeyPair()
else
{
return nil
}

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

self.config = config
self.serverPublicKey = config.serverPublicKey
self.clientPublicKey = keyPair.publicKey
self.clientPrivateKey = keyPair.privateKey
}
}

extension Data
{
public var bytes: Array<UInt8>
{
return Array(self)
}
}
Loading

0 comments on commit ca44491

Please sign in to comment.