Skip to content

Instantly share code, notes, and snippets.

@YannisDC
Created April 4, 2019 15:57
Show Gist options
  • Save YannisDC/2cc945f78b92f91d07e13d74684211bf to your computer and use it in GitHub Desktop.
Save YannisDC/2cc945f78b92f91d07e13d74684211bf to your computer and use it in GitHub Desktop.
import Cocoa
struct Person: Codable {
let name: String
let age: Int
let friends: [Person]?
}
let person = Person(name: "Brad", age: 53, friends: nil)
protocol Identifiable {
var uuid: String { get set }
}
protocol Encryptable {
var encrypted: Bool { get }
func encrypt()
func decrypt()
}
public class EncryptableProperty<T: Codable>: Encryptable {
var value: T
var encryptedValue: String
var encrypted: Bool
init(value: T, encrypted: Bool) {
self.value = value
self.encrypted = encrypted
self.encryptedValue = ""
}
func encrypt() {
if value is LosslessStringConvertible, let value = value as? LosslessStringConvertible {
self.encryptedValue = value.description
} else {
do {
let object = try JSONEncoder().encode(value)
// Do actual encryption and get the signature back
if let string = String(data: object, encoding: .utf8) {
encryptedValue = string
} else {
print("not a valid UTF-8 sequence")
}
} catch{
print("Encoding failed")
}
}
}
func decrypt() {
if value is LosslessStringConvertible {
print("It's going to come here instead of in the extension decrypt") // Be LosslessStringConvertible conforms to Codable
} else {
do {
let data : [UInt8] = [UInt8](self.encryptedValue.utf8)
// Do actual decryption and get the data back
let object = try JSONDecoder().decode(T.self, from: Data(data))
self.value = object
} catch{
print("Decoding failed")
}
}
}
}
extension EncryptableProperty where T: LosslessStringConvertible {
func decrypt() {
guard let convertedValue = T(self.encryptedValue) else {
return
}
self.value = convertedValue
}
}
protocol EncryptableObject {
func encryptObject()
func decryptObject()
}
struct Test: EncryptableObject, Identifiable {
public let testInt: EncryptableProperty<Array<String>>
var uuid: String
init(uuid: String = UUID().uuidString) {
self.testInt = EncryptableProperty<Array<String>>(value: ["one", "two"], encrypted: true)
self.uuid = uuid
}
func encryptObject() {
print("\nEncryption happens")
Mirror(reflecting: self)
.children
.forEach { (property) in
if let encryptableValue = property.value as? Encryptable {
encryptableValue.encrypt()
}
}
}
func decryptObject() {
print("\nDecryption happens")
Mirror(reflecting: self)
.children
.forEach { (property) in
if let encryptableValue = property.value as? Encryptable {
encryptableValue.decrypt()
}
}
}
}
let test = Test()
print("Value= \(test.testInt.value) EncryptedValue= \(test.testInt.encryptedValue)")
test.encryptObject()
print("Value= \(test.testInt.value) EncryptedValue= \(test.testInt.encryptedValue)")
print("\nDecrypted value gets updated")
test.testInt.encryptedValue = #"["sir", "yannis"]"#
print("Value= \(test.testInt.value) EncryptedValue= \(test.testInt.encryptedValue)")
test.decryptObject()
print("Value= \(test.testInt.value) EncryptedValue= \(test.testInt.encryptedValue)")
struct Test2: EncryptableObject, Identifiable {
public let testString: EncryptableProperty<String>
public let testInt: EncryptableProperty<Int>
var uuid: String
init(uuid: String = UUID().uuidString) {
self.testString = EncryptableProperty<String>(value: "Blockstack", encrypted: true)
self.testInt = EncryptableProperty<Int>(value: 5, encrypted: true)
self.uuid = uuid
}
func encryptObject() {
print("\nEncryption happens")
Mirror(reflecting: self)
.children
.forEach { (property) in
if let encryptableValue = property.value as? Encryptable {
encryptableValue.encrypt()
}
}
}
func decryptObject() {
print("\nDecryption happens")
Mirror(reflecting: self)
.children
.forEach { (property) in
if let encryptableValue = property.value as? Encryptable {
encryptableValue.decrypt()
}
}
}
}
let test2 = Test2()
print("Value= \(test2.testInt.value) EncryptedValue= \(test2.testInt.encryptedValue)")
test2.encryptObject()
print("Value= \(test2.testInt.value) EncryptedValue= \(test2.testInt.encryptedValue)")
print("\nDecrypted value gets updated")
test2.testInt.encryptedValue = "6"
print("Value= \(test2.testInt.value) EncryptedValue= \(test2.testInt.encryptedValue)")
test2.decryptObject()
print("Value= \(test2.testInt.value) EncryptedValue= \(test2.testInt.encryptedValue)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment