|
@@ -8,26 +8,30 @@
|
|
|
|
|
|
import Foundation
|
|
import Foundation
|
|
|
|
|
|
-public class AES {
|
|
|
|
|
|
+private enum AESVariant:Int {
|
|
|
|
+ case unknown, aes128, aes192, aes256
|
|
|
|
|
|
- enum Variant:Int {
|
|
|
|
- case unknown, aes128, aes192, aes256
|
|
|
|
-
|
|
|
|
- var Nk:Int { // Nk words
|
|
|
|
- return [4,6,8][self.rawValue - 1]
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var Nb:Int { // Nb words
|
|
|
|
- return 4
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- var Nr:Int { // Nr
|
|
|
|
- return Nk + 6
|
|
|
|
- }
|
|
|
|
|
|
+ var Nk:Int { // Nk words
|
|
|
|
+ return [4,6,8][self.rawValue - 1]
|
|
}
|
|
}
|
|
|
|
|
|
- let variant:Variant
|
|
|
|
- let key:NSData
|
|
|
|
|
|
+ var Nb:Int { // Nb words
|
|
|
|
+ return 4
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var Nr:Int { // Nr
|
|
|
|
+ return Nk + 6
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+public class AES {
|
|
|
|
+
|
|
|
|
+ public let blockSizeBytes = 128 / 8
|
|
|
|
+ public let blockMode:CipherBlockMode
|
|
|
|
+
|
|
|
|
+ private let variant:AESVariant
|
|
|
|
+ private let key:NSData
|
|
|
|
+ private let iv:NSData?
|
|
|
|
|
|
private let sBox:[Byte] = [
|
|
private let sBox:[Byte] = [
|
|
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, // 0
|
|
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, // 0
|
|
@@ -90,8 +94,14 @@ public class AES {
|
|
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
|
|
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
|
|
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]
|
|
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]
|
|
|
|
|
|
- public init?(key:NSData) {
|
|
|
|
|
|
+ public convenience init?(key:NSData) {
|
|
|
|
+ self.init(key:key, iv:nil)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public init?(key:NSData, iv:NSData?) {
|
|
self.key = key
|
|
self.key = key
|
|
|
|
+ self.iv = iv
|
|
|
|
+ self.blockMode = .CBC
|
|
switch (key.length * 8) {
|
|
switch (key.length * 8) {
|
|
case 128:
|
|
case 128:
|
|
self.variant = .aes128
|
|
self.variant = .aes128
|
|
@@ -107,26 +117,18 @@ public class AES {
|
|
return nil;
|
|
return nil;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- public func blockSizeBytes() -> Int {
|
|
|
|
- return 128 / 8
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ // if "iv" is given then CBC mode is used by default
|
|
public func encrypt(message:NSData) -> NSData? {
|
|
public func encrypt(message:NSData) -> NSData? {
|
|
- if (message.length % blockSizeBytes() != 0) {
|
|
|
|
|
|
+ if (message.length % blockSizeBytes != 0) {
|
|
// 128 bit block exceeded
|
|
// 128 bit block exceeded
|
|
println("AES 128-bit block exceeded!")
|
|
println("AES 128-bit block exceeded!")
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
- var out:[Byte] = [Byte]()
|
|
|
|
- for block in message.bytes().chunks(blockSizeBytes()) {
|
|
|
|
- for byte in encryptBlock(block) {
|
|
|
|
- out.append(byte)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return NSData.withBytes(out)
|
|
|
|
|
|
+ let blocks = message.bytes().chunks(blockSizeBytes)
|
|
|
|
+ let out = blockMode.processBlocks(blocks, iv: self.iv?.bytes(), cipher: encryptBlock)
|
|
|
|
+ return out == nil ? nil : NSData.withBytes(out!)
|
|
}
|
|
}
|
|
|
|
|
|
private func encryptBlock(block:[Byte]) -> [Byte] {
|
|
private func encryptBlock(block:[Byte]) -> [Byte] {
|