Skip to content

Instantly share code, notes, and snippets.

@shakemno
Forked from alskipp/encrypt_xor1.swift
Created November 1, 2018 11:10
Show Gist options
  • Save shakemno/ffd33d1307a688348f5f33e33af1001e to your computer and use it in GitHub Desktop.
Save shakemno/ffd33d1307a688348f5f33e33af1001e to your computer and use it in GitHub Desktop.
Swift encrypt/decrypt string using XOR
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!"
/* (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}
}
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment