В настоящее время я реализую частичную расшифровку с использованием режима AES-128 CBC. Я использовал 3 разные библиотеки и 2 разных собственных подхода к расшифровке. Пока что все они терпят неудачу в этом одном блоке, который я не могу исправить.
Пожалуйста, взгляните на код -
protocol AESDecrypting {
var name: String { get }
func decryptData(_ data: Data, withKey key: Data, startingBlock: Int,
numberOfBlocks: Int) -> Data?
func decryptData(_ data: Data, withKey key: Data) -> Data?
}
protocol AESEncrypting {
var name: String { get }
func encryptData(_ data: Data, withKey key: Data) -> Data?
}
struct CryptoSwiftDecryption: AESDecrypting, AESEncrypting {
let name = "CryptoSwiftDecryption"
func decryptData(_ data: Data, withKey key: Data, startingBlock: Int,
numberOfBlocks: Int) -> Data? {
guard numberOfBlocks > 0 && startingBlock >= 0 else {
return nil
}
let startingPoint = (startingBlock * kCCBlockSizeAES128)
guard startingPoint < data.count else {
return nil
}
let endingPoint = min(
startingPoint + (numberOfBlocks * kCCBlockSizeAES128) + kCCBlockSizeAES128,
data.count)
let dataToUse = data.subdata(in: startingPoint..<endingPoint)
return decryptData(dataToUse, withKey: key)
}
func decryptData(_ data: Data, withKey key: Data) -> Data? {
let keyBites: [UInt8] = key.bytes
let iv = data.subdata(in: 0..<16).bytes
let contentPortion = data.subdata(in: 16..<data.count)
do {
let aes = try AES(key: keyBites, blockMode: CBC(iv: iv), padding: .pkcs7)
let decryptedBytes = try aes.decrypt(contentPortion.bytes)
return Data(decryptedBytes)
} catch {
print(error)
return nil
}
}
func encryptData(_ data: Data, withKey key: Data) -> Data? {
do {
let keyBites: [UInt8] = key.bytes
let iv: [UInt8] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
let aes = try AES(key: keyBites, blockMode: CBC(iv: iv), padding: .pkcs7)
let encryptedBytes = try aes.encrypt(data.bytes)
return Data(iv) + Data(encryptedBytes)
} catch {
print(error)
return nil
}
}
}
А теперь тесты. Пока работает для всего, кроме блока номер 22, при сравнении результатов после расшифровки поблочно.
import XCTest
import CommonCrypto
class PartialAESDecryptionTests: XCTestCase {
private let crypto = CryptoSwiftDecryption()
lazy private var fullyDecryptedString: String = {
return """
<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n<head>\n\t<title>CHAPTER I -- Metamorphosis </title>\n\t<meta http-equiv=\"Content-Type\" content=\"application/xhtml+xml; charset=utf-8\" />\n\t<meta name=\"EPB-UUID\" content=\"\" />\n\n\t<link rel=\"stylesheet\" href=\"jackson.css\" type=\"text/css\" />\n</head>\n<body>\n<div class=\"chapter introduction type-1\" id=\"chapter-i\"><div class=\"chapter-title-wrap\"><h3
"""
}()
lazy private var fullyDecryptedData: Data = {
return fullyDecryptedString.data(using: .utf8)!
}()
lazy private var inputData: Data = {
return crypto.encryptData(fullyDecryptedData, withKey: keyData)!
}()
lazy private var keyData: Data = {
return "keyData890123456".data(using: .utf8)!
}()
override func setUp() {
super.setUp()
continueAfterFailure = true
}
func testDecryptingEntireFile() {
let expected = fullyDecryptedString
let actual = decrypt(inputData, keyData, crypto)
XCTAssertEqual(expected, actual)
}
func testDecryptingOneBlockFromBeginning() {
let startingBlock = 0
let numberOfBlocks = 1
let expected = usableBlockFromGivenDecryptedFile(startingBlock, numberOfBlocks)
let result = decrypt(
inputData, keyData, startingBlock: startingBlock, numberOfBlocks: numberOfBlocks, crypto)
XCTAssertEqual(result, expected)
}
func testDecryptingThreeBlocksFromBeginning() {
let startingBlock = 0
let numberOfBlocks = 3
let expected = usableBlockFromGivenDecryptedFile(startingBlock, numberOfBlocks)
let result = decrypt(
inputData, keyData, startingBlock: startingBlock, numberOfBlocks: numberOfBlocks, crypto)
XCTAssertEqual(result, expected)
}
func testDecryptingSecondThirdForthBlock() {
let startingBlock = 1
let numberOfBlocks = 3
let expected = usableBlockFromGivenDecryptedFile(startingBlock, numberOfBlocks)
let result = decrypt(
inputData, keyData, startingBlock: startingBlock, numberOfBlocks: numberOfBlocks, crypto)
XCTAssertEqual(result, expected)
}
func testDecryptingOneBlockInMiddle() {
let startingBlock = 10
let numberOfBlocks = 1
let expected = usableBlockFromGivenDecryptedFile(startingBlock, numberOfBlocks)
let result = decrypt(
inputData, keyData, startingBlock: startingBlock, numberOfBlocks: numberOfBlocks, crypto)
XCTAssertEqual(result, expected)
}
func testDecryptingThreeBlocksInMiddle() {
let startingBlock = 10
let numberOfBlocks = 3
let expected = usableBlockFromGivenDecryptedFile(startingBlock, numberOfBlocks)
let result = decrypt(
inputData, keyData, startingBlock: startingBlock, numberOfBlocks: numberOfBlocks, crypto)
XCTAssertEqual(result, expected)
}
func testComparingBlockByBlock() {
let totalBlocks = Int(inputData.count/kCCBlockSizeAES128) + 1
let numberOfBlocks = 1
for startingBlock in 0..<totalBlocks {
let expected = usableBlockFromGivenDecryptedFile(startingBlock, numberOfBlocks)
let result = decrypt(
inputData, keyData, startingBlock: startingBlock, numberOfBlocks: numberOfBlocks, crypto)
XCTAssertEqual(expected, result, "\(startingBlock)")
}
}
// // MARK: - Helper Methods
private func decrypt(_ data: Data, _ key: Data, _ decryptor: AESDecrypting) -> String? {
guard
let decrypted = decryptor.decryptData(data, withKey: key) else {
print("\(decryptor.name) failed to decrypt")
return nil
}
guard let result = String(data: decrypted, encoding: .utf8) else {
print("\(decryptor.name) failed to convert to string")
return nil
}
return result
}
private func decrypt(_ data: Data, _ key: Data, startingBlock: Int, numberOfBlocks: Int, _ decryptor: AESDecrypting) -> String? {
guard
let decrypted = decryptor
.decryptData(data, withKey: keyData,
startingBlock: startingBlock,
numberOfBlocks: numberOfBlocks)
else {
print("\(decryptor.name) failed to decrypt")
return nil
}
guard let result = String(data: decrypted, encoding: .utf8) else {
print("\(decryptor.name) failed to convert to string")
return nil
}
return result
}
private func usableBlockFromGivenDecryptedFile(_ startingBlock: Int, _ numberOfBlocks: Int) -> String? {
let blockSize = kCCBlockSizeAES128
let startingPoint = (startingBlock * blockSize)
guard startingPoint < fullyDecryptedData.count else {
return nil
}
let endingPoint = min(startingPoint + (numberOfBlocks * blockSize), fullyDecryptedData.count)
let dataToUse = fullyDecryptedData.subdata(in: startingPoint..<endingPoint)
return String(data: dataToUse, encoding: .utf8) ?? nil
}
}
Все остальные тесты проходят успешно. Единственный тест, который не проходит, это testComparingBlockByBlock
в блоке 22. Кто-нибудь, пожалуйста, скажите мне, что я делаю неправильно, прежде чем я сойду с ума.
Я вижу это в тестах
- XCTAsertEqual не удалось: ("Необязательно(" content="" />\n\n")") не равно ("Необязательно(" conte")) - 22