Last active
November 1, 2018 11:10
-
-
Save alskipp/016c8ba96352e5c74bf2 to your computer and use it in GitHub Desktop.
Swift encrypt/decrypt string using XOR
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension Character { | |
func utf8() -> UInt8 { | |
let utf8 = String(self).utf8 | |
return utf8[utf8.startIndex] | |
} | |
} | |
func encrypt(c:Character, key:Character) -> String { | |
let byte = [c.utf8() ^ key.utf8()] | |
return String(bytes: byte, encoding: NSUTF8StringEncoding)! // forced unwrapping alert! | |
} | |
func encrypt(message:String, #key:String) -> String { | |
return reduce(Zip2(message, key), "") { $0 + encrypt($1) } | |
} | |
let message = "Hello world!" | |
let secretKey = "(:.,?P!9@PAz" // really should be randomly generated! | |
let encryptedMessage = encrypt(message, key: secretKey) // > "`_B@PpVV2<%[" | |
let decryptedMessage = encrypt(encryptedMessage, key: secretKey) // > "Hello world!" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* (Requires Swift 1.2) | |
In the version above you'll notice that there's use of forced Optional unwrapping. | |
This is potentially hazardous. Here's a version that deals with Optional values safely. | |
Having to 'reduce' Optional Strings adds significant complexity. | |
Below, I've shown 2 ways of dealing with this (Monadic bind & 'if let' syntax). | |
*/ | |
import Foundation | |
// Monadic bind for Optionals | |
infix operator >>= {associativity left} | |
func >>= <A,B> (m: A?, f: A -> B?) -> B? { | |
if let x = m {return f(x)} | |
return .None | |
} | |
extension Character { | |
func utf8() -> UInt8 { | |
let utf8 = String(self).utf8 | |
return utf8[utf8.startIndex] | |
} | |
} | |
func encrypt(key:Character, c:Character) -> String? { | |
let byte = [key.utf8() ^ c.utf8()] | |
return String(bytes: byte, encoding: NSUTF8StringEncoding) | |
} | |
// Curried func for convenient use with map | |
func encryptKey(key:String)(message:String) -> String? { | |
return reduce(zip(key, message), Optional("")) { str, c in str >>= { s in encrypt(c).map {s + $0} }} | |
} | |
let message = "Hello world!" | |
let secretKey = "(:.,?P!9@PAz" // really should be randomly generated! | |
let encryptedMessage = encryptKey(secretKey)(message: message) // > .Some("`_B@PpVV2<%[") | |
// As the encryptKey func is curried it can be passed directly to map | |
let decryptedMessage = encryptedMessage.map(encryptKey(secretKey)) // > .Some("Hello world!") | |
/* here's how the encrypt function would look like using 'if let' syntax | |
func encryptKey_if_let(key:String)(message:String) -> String? { | |
return reduce(zip(key, message), Optional("")) { if let str = $0, c = encrypt($1) { | |
return str + c | |
} else { | |
return .None} | |
} | |
} | |
*/ |
I'm wondering if there's a library around this solution or was this dropped back then?
Thanks :)
Shai
could someone explain encryptKey? I'm guessing that its reducing zipped tuples of the key and message characters. However it looks like its calling the encrypt function with a tuple, instead of 2 characters. Can/How could this work in Swift 3?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My message is just a string object when returned from the server. How come I cannot call .map on a string? Sorry, I'm still relatively new to Swift. The only difference I see between your code and mine is that your string is an optional String.