125 lines
2.9 KiB
Swift
125 lines
2.9 KiB
Swift
public func convertToUnicodeScalars(
|
|
str: String,
|
|
minChar: UInt32,
|
|
maxChar: UInt32
|
|
) -> [UInt32] {
|
|
var scalars = [UInt32]()
|
|
|
|
for scalar in str.unicodeScalars {
|
|
let val = scalar.value
|
|
|
|
guard val >= minChar && val <= maxChar else {
|
|
continue
|
|
}
|
|
|
|
scalars.append(val)
|
|
}
|
|
|
|
return scalars
|
|
}
|
|
|
|
public struct Vigenere {
|
|
private let keyScalars: [UInt32]
|
|
private let smallestScalar: UInt32
|
|
private let largestScalar: UInt32
|
|
private let sizeAlphabet: UInt32
|
|
|
|
public init?(key: String, smallestCharacter: Character = "A", largestCharacter: Character = "Z") {
|
|
let smallScalars = smallestCharacter.unicodeScalars
|
|
let largeScalars = largestCharacter.unicodeScalars
|
|
|
|
guard smallScalars.count == 1, largeScalars.count == 1 else {
|
|
return nil
|
|
}
|
|
|
|
self.smallestScalar = smallScalars.first!.value
|
|
self.largestScalar = largeScalars.first!.value
|
|
self.sizeAlphabet = (largestScalar - smallestScalar) + 1
|
|
|
|
let scalars = convertToUnicodeScalars(str: key, minChar: smallestScalar, maxChar: largestScalar)
|
|
|
|
guard !scalars.isEmpty else {
|
|
return nil
|
|
}
|
|
|
|
self.keyScalars = scalars
|
|
|
|
}
|
|
|
|
public func decrypt(_ str: String) -> String? {
|
|
let txtBytes = convertToUnicodeScalars(str: str, minChar: smallestScalar, maxChar: largestScalar)
|
|
|
|
guard !txtBytes.isEmpty else {
|
|
return nil
|
|
}
|
|
|
|
var res = ""
|
|
|
|
for (i, c) in txtBytes.enumerated() where c >= smallestScalar && c <= largestScalar {
|
|
guard let char =
|
|
UnicodeScalar((c &+ sizeAlphabet &- keyScalars[i % keyScalars.count]) % sizeAlphabet &+ smallestScalar)
|
|
else {
|
|
return nil
|
|
}
|
|
|
|
res += String(char)
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
public func encrypt(_ str: String) -> String? {
|
|
let txtBytes = convertToUnicodeScalars(str: str, minChar: smallestScalar, maxChar: largestScalar)
|
|
|
|
guard !txtBytes.isEmpty else {
|
|
return nil
|
|
}
|
|
|
|
var res = ""
|
|
|
|
for (i, c) in txtBytes.enumerated() where c >= smallestScalar && c <= largestScalar {
|
|
guard let char =
|
|
UnicodeScalar((c &+ keyScalars[i % keyScalars.count] &- 2 &* smallestScalar) % sizeAlphabet &+ smallestScalar)
|
|
else {
|
|
return nil
|
|
}
|
|
|
|
res += String(char)
|
|
}
|
|
|
|
return res
|
|
}
|
|
}
|
|
|
|
let text = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!";
|
|
let key = "VIGENERECIPHER";
|
|
let cipher = Vigenere(key: key)!
|
|
|
|
print("Key: \(key)")
|
|
print("Plain Text: \(text)")
|
|
|
|
let encoded = cipher.encrypt(text.uppercased())!
|
|
|
|
print("Cipher Text: \(encoded)")
|
|
|
|
let decoded = cipher.decrypt(encoded)!
|
|
|
|
print("Decoded: \(decoded)")
|
|
|
|
print("\nLarger set:")
|
|
|
|
let key2 = "Vigenère cipher"
|
|
let text2 = "This is a ünicode string 😃"
|
|
|
|
let cipher2 = Vigenere(key: key2, smallestCharacter: " ", largestCharacter: "🛹")!
|
|
|
|
print("Key: \(key2)")
|
|
print("Plain Text: \(text2)")
|
|
|
|
let encoded2 = cipher2.encrypt(text2)!
|
|
|
|
print("Cipher Text: \(encoded2)")
|
|
|
|
let decoded2 = cipher2.decrypt(encoded2)!
|
|
|
|
print("Decoded: \(decoded2)")
|