|
@@ -11,10 +11,14 @@ import Foundation
|
|
// I have no better name for that
|
|
// I have no better name for that
|
|
typealias CipherOperationOnBlock = (block: [UInt8]) -> [UInt8]?
|
|
typealias CipherOperationOnBlock = (block: [UInt8]) -> [UInt8]?
|
|
|
|
|
|
|
|
+enum BlockError: ErrorType {
|
|
|
|
+ case MissingInitializationVector
|
|
|
|
+}
|
|
|
|
+
|
|
private protocol BlockMode {
|
|
private protocol BlockMode {
|
|
var needIV:Bool { get }
|
|
var needIV:Bool { get }
|
|
- func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]?
|
|
|
|
- func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]?
|
|
|
|
|
|
+ func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8]
|
|
|
|
+ func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8]
|
|
}
|
|
}
|
|
|
|
|
|
public enum CipherBlockMode {
|
|
public enum CipherBlockMode {
|
|
@@ -46,7 +50,7 @@ public enum CipherBlockMode {
|
|
|
|
|
|
- returns: encrypted bytes
|
|
- returns: encrypted bytes
|
|
*/
|
|
*/
|
|
- func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
|
|
+ func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
|
|
|
|
|
|
// if IV is not available, fallback to plain
|
|
// if IV is not available, fallback to plain
|
|
var finalBlockMode:CipherBlockMode = self
|
|
var finalBlockMode:CipherBlockMode = self
|
|
@@ -54,17 +58,17 @@ public enum CipherBlockMode {
|
|
finalBlockMode = .ECB
|
|
finalBlockMode = .ECB
|
|
}
|
|
}
|
|
|
|
|
|
- return finalBlockMode.mode.encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
|
|
|
|
|
|
+ return try finalBlockMode.mode.encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
|
|
}
|
|
}
|
|
|
|
|
|
- func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
|
|
+ func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
|
|
// if IV is not available, fallback to plain
|
|
// if IV is not available, fallback to plain
|
|
var finalBlockMode:CipherBlockMode = self
|
|
var finalBlockMode:CipherBlockMode = self
|
|
if (iv == nil) {
|
|
if (iv == nil) {
|
|
finalBlockMode = .ECB
|
|
finalBlockMode = .ECB
|
|
}
|
|
}
|
|
|
|
|
|
- return finalBlockMode.mode.decryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
|
|
|
|
|
|
+ return try finalBlockMode.mode.decryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -74,35 +78,33 @@ Cipher-block chaining (CBC)
|
|
private struct CBCMode: BlockMode {
|
|
private struct CBCMode: BlockMode {
|
|
let needIV = true
|
|
let needIV = true
|
|
|
|
|
|
- func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
|
|
+ func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
|
|
precondition(blocks.count > 0)
|
|
precondition(blocks.count > 0)
|
|
- assert(iv != nil, "CFB require IV")
|
|
|
|
- if (iv == nil) {
|
|
|
|
- return nil
|
|
|
|
|
|
+ guard let iv = iv else {
|
|
|
|
+ throw BlockError.MissingInitializationVector
|
|
}
|
|
}
|
|
|
|
|
|
var out:[UInt8] = [UInt8]()
|
|
var out:[UInt8] = [UInt8]()
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
- var prevCiphertext = iv! // for the first time prevCiphertext = iv
|
|
|
|
|
|
+ var prevCiphertext = iv // for the first time prevCiphertext = iv
|
|
for plaintext in blocks {
|
|
for plaintext in blocks {
|
|
if let encrypted = cipherOperation(block: xor(prevCiphertext, b: plaintext)) {
|
|
if let encrypted = cipherOperation(block: xor(prevCiphertext, b: plaintext)) {
|
|
out.extend(encrypted)
|
|
out.extend(encrypted)
|
|
prevCiphertext = encrypted
|
|
prevCiphertext = encrypted
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return out;
|
|
|
|
|
|
+ return out
|
|
}
|
|
}
|
|
|
|
|
|
- func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
|
|
+ func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
|
|
precondition(blocks.count > 0)
|
|
precondition(blocks.count > 0)
|
|
- assert(iv != nil, "CFB require IV")
|
|
|
|
- if (iv == nil) {
|
|
|
|
- return nil
|
|
|
|
|
|
+ guard let iv = iv else {
|
|
|
|
+ throw BlockError.MissingInitializationVector
|
|
}
|
|
}
|
|
|
|
|
|
var out:[UInt8] = [UInt8]()
|
|
var out:[UInt8] = [UInt8]()
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
- var prevCiphertext = iv! // for the first time prevCiphertext = iv
|
|
|
|
|
|
+ var prevCiphertext = iv // for the first time prevCiphertext = iv
|
|
for ciphertext in blocks {
|
|
for ciphertext in blocks {
|
|
if let decrypted = cipherOperation(block: ciphertext) { // decrypt
|
|
if let decrypted = cipherOperation(block: ciphertext) { // decrypt
|
|
out.extend(xor(prevCiphertext, b: decrypted)) //FIXME: b:
|
|
out.extend(xor(prevCiphertext, b: decrypted)) //FIXME: b:
|
|
@@ -120,27 +122,26 @@ Cipher feedback (CFB)
|
|
private struct CFBMode: BlockMode {
|
|
private struct CFBMode: BlockMode {
|
|
let needIV = true
|
|
let needIV = true
|
|
|
|
|
|
- func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
- assert(iv != nil, "CFB require IV")
|
|
|
|
- if (iv == nil) {
|
|
|
|
- return nil
|
|
|
|
|
|
+ func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
|
|
|
|
+ guard let iv = iv else {
|
|
|
|
+ throw BlockError.MissingInitializationVector
|
|
}
|
|
}
|
|
|
|
|
|
var out:[UInt8] = [UInt8]()
|
|
var out:[UInt8] = [UInt8]()
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
|
|
|
|
- var lastCiphertext = iv!
|
|
|
|
|
|
+ var lastCiphertext = iv
|
|
for plaintext in blocks {
|
|
for plaintext in blocks {
|
|
if let encrypted = cipherOperation(block: lastCiphertext) {
|
|
if let encrypted = cipherOperation(block: lastCiphertext) {
|
|
lastCiphertext = xor(plaintext,b: encrypted)
|
|
lastCiphertext = xor(plaintext,b: encrypted)
|
|
out.extend(lastCiphertext)
|
|
out.extend(lastCiphertext)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return out;
|
|
|
|
|
|
+ return out
|
|
}
|
|
}
|
|
|
|
|
|
- func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
- return encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
|
|
|
|
|
|
+ func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
|
|
|
|
+ return try encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -150,7 +151,8 @@ Electronic codebook (ECB)
|
|
*/
|
|
*/
|
|
private struct ECBMode: BlockMode {
|
|
private struct ECBMode: BlockMode {
|
|
let needIV = false
|
|
let needIV = false
|
|
- func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
|
|
+
|
|
|
|
+ func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8] {
|
|
var out:[UInt8] = [UInt8]()
|
|
var out:[UInt8] = [UInt8]()
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
for plaintext in blocks {
|
|
for plaintext in blocks {
|
|
@@ -161,7 +163,7 @@ private struct ECBMode: BlockMode {
|
|
return out
|
|
return out
|
|
}
|
|
}
|
|
|
|
|
|
- func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
|
|
+ func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8] {
|
|
return encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
|
|
return encryptBlocks(blocks, iv: iv, cipherOperation: cipherOperation)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -182,13 +184,18 @@ private struct CTRMode: BlockMode {
|
|
return nonce
|
|
return nonce
|
|
}
|
|
}
|
|
|
|
|
|
- func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
|
|
+ func encryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
|
|
//var counter:UInt = 17940646550795321087
|
|
//var counter:UInt = 17940646550795321087
|
|
|
|
+
|
|
|
|
+ guard let iv = iv else {
|
|
|
|
+ throw BlockError.MissingInitializationVector
|
|
|
|
+ }
|
|
|
|
+
|
|
var counter:UInt = 0
|
|
var counter:UInt = 0
|
|
var out:[UInt8] = [UInt8]()
|
|
var out:[UInt8] = [UInt8]()
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
for plaintext in blocks {
|
|
for plaintext in blocks {
|
|
- let nonce = buildNonce(iv!, counter: counter++)
|
|
|
|
|
|
+ let nonce = buildNonce(iv, counter: counter++)
|
|
if let encrypted = cipherOperation(block: nonce) {
|
|
if let encrypted = cipherOperation(block: nonce) {
|
|
out.extend(xor(plaintext, b: encrypted))
|
|
out.extend(xor(plaintext, b: encrypted))
|
|
}
|
|
}
|
|
@@ -196,7 +203,11 @@ private struct CTRMode: BlockMode {
|
|
return out
|
|
return out
|
|
}
|
|
}
|
|
|
|
|
|
- func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) -> [UInt8]? {
|
|
|
|
|
|
+ func decryptBlocks(blocks:[[UInt8]], iv:[UInt8]?, cipherOperation:CipherOperationOnBlock) throws -> [UInt8] {
|
|
|
|
+ guard iv != nil else {
|
|
|
|
+ throw BlockError.MissingInitializationVector
|
|
|
|
+ }
|
|
|
|
+
|
|
var counter:UInt = 0
|
|
var counter:UInt = 0
|
|
var out:[UInt8] = [UInt8]()
|
|
var out:[UInt8] = [UInt8]()
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|
|
out.reserveCapacity(blocks.count * blocks[0].count)
|