Skip to content

Commit a015234

Browse files
move CTR-specific test cases to specialized test class
1 parent a66dc2b commit a015234

File tree

4 files changed

+118
-76
lines changed

4 files changed

+118
-76
lines changed

CryptomatorCryptoLib.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
9E9BB81624558DFF00F9FF51 /* MasterkeyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E9BB81524558DFF00F9FF51 /* MasterkeyTests.swift */; };
3535
9EB822C1248AF82200879838 /* AesCtr.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EB822C0248AF82200879838 /* AesCtr.swift */; };
3636
9EB822C3248AF9C500879838 /* AesCtrTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EB822C2248AF9C500879838 /* AesCtrTests.swift */; };
37+
9EBEC947283782E6002210DE /* CtrCryptorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EBEC946283782E6002210DE /* CtrCryptorTests.swift */; };
3738
/* End PBXBuildFile section */
3839

3940
/* Begin PBXContainerItemProxy section */
@@ -97,6 +98,7 @@
9798
9E9BB81524558DFF00F9FF51 /* MasterkeyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterkeyTests.swift; sourceTree = "<group>"; };
9899
9EB822C0248AF82200879838 /* AesCtr.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AesCtr.swift; sourceTree = "<group>"; };
99100
9EB822C2248AF9C500879838 /* AesCtrTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AesCtrTests.swift; sourceTree = "<group>"; };
101+
9EBEC946283782E6002210DE /* CtrCryptorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CtrCryptorTests.swift; sourceTree = "<group>"; };
100102
/* End PBXFileReference section */
101103

102104
/* Begin PBXFrameworksBuildPhase section */
@@ -171,6 +173,7 @@
171173
9EB822C2248AF9C500879838 /* AesCtrTests.swift */,
172174
9E44EEA724599C7800A37B01 /* AesSivTests.swift */,
173175
9E35C4EA24576A3D0006E50C /* CryptorTests.swift */,
176+
9EBEC946283782E6002210DE /* CtrCryptorTests.swift */,
174177
74A5B57D25A86A69002D10F7 /* CryptoSupportMock.swift */,
175178
74A5B57525A869DD002D10F7 /* MasterkeyFileTests.swift */,
176179
9E9BB81524558DFF00F9FF51 /* MasterkeyTests.swift */,
@@ -443,6 +446,7 @@
443446
files = (
444447
74A5B57E25A86A69002D10F7 /* CryptoSupportMock.swift in Sources */,
445448
9E44EEA92459AB1500A37B01 /* AesSivTests.swift in Sources */,
449+
9EBEC947283782E6002210DE /* CtrCryptorTests.swift in Sources */,
446450
9EB822C3248AF9C500879838 /* AesCtrTests.swift in Sources */,
447451
74A5B57625A869DD002D10F7 /* MasterkeyFileTests.swift in Sources */,
448452
9E9BB81624558DFF00F9FF51 /* MasterkeyTests.swift in Sources */,

Sources/CryptomatorCryptoLib/Cryptor.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ public class Cryptor {
6666
return contentCryptor.nonceLen + fileHeaderPayloadSize + contentCryptor.tagLen
6767
}
6868

69-
private let cleartextChunkSize = 32 * 1024
70-
private var ciphertextChunkSize: Int {
69+
public let cleartextChunkSize = 32 * 1024
70+
public var ciphertextChunkSize: Int {
7171
return contentCryptor.nonceLen + cleartextChunkSize + contentCryptor.tagLen
7272
}
7373

Tests/CryptomatorCryptoLibTests/CryptorTests.swift

Lines changed: 42 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,19 @@ import XCTest
1010
@testable import CryptomatorCryptoLib
1111

1212
class CryptorTests: XCTestCase {
13+
var contentCryptor: ContentCryptor!
1314
var cryptor: Cryptor!
1415
var tmpDirURL: URL!
1516

16-
override func setUpWithError() throws {
17-
let aesKey = [UInt8](repeating: 0x55, count: 32)
18-
let macKey = [UInt8](repeating: 0x77, count: 32)
19-
let masterkey = Masterkey.createFromRaw(aesMasterKey: aesKey, macMasterKey: macKey)
20-
let cryptoSupport = CryptoSupportMock()
21-
let contentCryptor = CtrThenHmacContentCryptor(macKey: macKey, cryptoSupport: cryptoSupport)
22-
cryptor = Cryptor(masterkey: masterkey, cryptoSupport: cryptoSupport, contentCryptor: contentCryptor)
17+
override class var defaultTestSuite: XCTestSuite {
18+
// Return empty `XCTestSuite` so that no tests from this "abstract" `XCTestCase` is run.
19+
// Make sure to override this in subclasses so that the implemented test case can run.
20+
return XCTestSuite(name: "InterfaceTests Excluded")
21+
}
2322

23+
func setUpWithError(masterkey: Masterkey, cryptoSupport: CryptoSupport, contentCryptor: ContentCryptor) throws {
24+
self.contentCryptor = contentCryptor
25+
cryptor = Cryptor(masterkey: masterkey, cryptoSupport: cryptoSupport, contentCryptor: contentCryptor)
2426
tmpDirURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent(UUID().uuidString, isDirectory: true)
2527
try FileManager.default.createDirectory(at: tmpDirURL, withIntermediateDirectories: true)
2628
}
@@ -59,50 +61,6 @@ class CryptorTests: XCTestCase {
5961
}
6062
}
6163

62-
func testCreateHeader() throws {
63-
let header = try cryptor.createHeader()
64-
XCTAssertEqual([UInt8](repeating: 0xF0, count: 16), header.nonce)
65-
XCTAssertEqual([UInt8](repeating: 0xF0, count: 32), header.contentKey)
66-
}
67-
68-
func testEncryptHeader() throws {
69-
let header = try cryptor.createHeader()
70-
let encrypted = try cryptor.encryptHeader(header)
71-
let expected: [UInt8] = [
72-
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
73-
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
74-
0x0D, 0x91, 0xF2, 0x9C, 0xC6, 0x35, 0xD7, 0x5E,
75-
0x1E, 0x42, 0x23, 0x1E, 0xC7, 0x90, 0x57, 0xE3,
76-
0x8D, 0x98, 0xF3, 0x58, 0x07, 0x2C, 0x9F, 0x03,
77-
0xBC, 0xEA, 0x5A, 0x98, 0x3B, 0x68, 0x62, 0x89,
78-
0x3E, 0xBC, 0x5E, 0x5E, 0x27, 0x39, 0xCB, 0x8E,
79-
0xD4, 0x27, 0x61, 0x06, 0x8E, 0x7F, 0x3A, 0x4E,
80-
0xC7, 0x9F, 0x4D, 0x3E, 0x20, 0x57, 0xDC, 0xE4,
81-
0x65, 0xA5, 0xFF, 0x93, 0xC2, 0x7B, 0xD2, 0xB8,
82-
0x3F, 0xE3, 0xD0, 0x8C, 0xB3, 0x92, 0xED, 0x96
83-
]
84-
XCTAssertEqual(expected, encrypted)
85-
}
86-
87-
func testDecryptHeader() throws {
88-
let ciphertext: [UInt8] = [
89-
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
90-
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
91-
0x0D, 0x91, 0xF2, 0x9C, 0xC6, 0x35, 0xD7, 0x5E,
92-
0x1E, 0x42, 0x23, 0x1E, 0xC7, 0x90, 0x57, 0xE3,
93-
0x8D, 0x98, 0xF3, 0x58, 0x07, 0x2C, 0x9F, 0x03,
94-
0xBC, 0xEA, 0x5A, 0x98, 0x3B, 0x68, 0x62, 0x89,
95-
0x3E, 0xBC, 0x5E, 0x5E, 0x27, 0x39, 0xCB, 0x8E,
96-
0xD4, 0x27, 0x61, 0x06, 0x8E, 0x7F, 0x3A, 0x4E,
97-
0xC7, 0x9F, 0x4D, 0x3E, 0x20, 0x57, 0xDC, 0xE4,
98-
0x65, 0xA5, 0xFF, 0x93, 0xC2, 0x7B, 0xD2, 0xB8,
99-
0x3F, 0xE3, 0xD0, 0x8C, 0xB3, 0x92, 0xED, 0x96
100-
]
101-
let decrypted = try cryptor.decryptHeader(ciphertext)
102-
XCTAssertEqual([UInt8](repeating: 0xF0, count: 16), decrypted.nonce)
103-
XCTAssertEqual([UInt8](repeating: 0xF0, count: 32), decrypted.contentKey)
104-
}
105-
10664
func testEncryptAndDecryptContent() throws {
10765
let originalData = Data(repeating: 0x0F, count: 65 * 1024)
10866
let originalURL = tmpDirURL.appendingPathComponent(UUID().uuidString, isDirectory: false)
@@ -128,7 +86,7 @@ class CryptorTests: XCTestCase {
12886
}
12987

13088
func testEncryptAndDecryptSingleChunk() throws {
131-
let nonce = [UInt8](repeating: 0x00, count: 16)
89+
let nonce = [UInt8](repeating: 0x00, count: contentCryptor.nonceLen)
13290
let filekey = [UInt8](repeating: 0x00, count: 32)
13391
let cleartext = [UInt8]("hello world".data(using: .ascii)!)
13492

@@ -139,47 +97,57 @@ class CryptorTests: XCTestCase {
13997
}
14098

14199
func testCalculateCiphertextSize() {
100+
let overheadPerChunk = contentCryptor.nonceLen + contentCryptor.tagLen
101+
142102
XCTAssertEqual(0, cryptor.calculateCiphertextSize(0))
143103

144-
XCTAssertEqual(1 + 48, cryptor.calculateCiphertextSize(1))
145-
XCTAssertEqual(32 * 1024 - 1 + 48, cryptor.calculateCiphertextSize(32 * 1024 - 1))
146-
XCTAssertEqual(32 * 1024 + 48, cryptor.calculateCiphertextSize(32 * 1024))
104+
XCTAssertEqual(1 + overheadPerChunk, cryptor.calculateCiphertextSize(1))
105+
XCTAssertEqual(32 * 1024 - 1 + overheadPerChunk, cryptor.calculateCiphertextSize(32 * 1024 - 1))
106+
XCTAssertEqual(32 * 1024 + overheadPerChunk, cryptor.calculateCiphertextSize(32 * 1024))
147107

148-
XCTAssertEqual(32 * 1024 + 1 + 48 * 2, cryptor.calculateCiphertextSize(32 * 1024 + 1))
149-
XCTAssertEqual(32 * 1024 + 2 + 48 * 2, cryptor.calculateCiphertextSize(32 * 1024 + 2))
150-
XCTAssertEqual(64 * 1024 - 1 + 48 * 2, cryptor.calculateCiphertextSize(64 * 1024 - 1))
151-
XCTAssertEqual(64 * 1024 + 48 * 2, cryptor.calculateCiphertextSize(64 * 1024))
108+
XCTAssertEqual(32 * 1024 + 1 + overheadPerChunk * 2, cryptor.calculateCiphertextSize(32 * 1024 + 1))
109+
XCTAssertEqual(32 * 1024 + 2 + overheadPerChunk * 2, cryptor.calculateCiphertextSize(32 * 1024 + 2))
110+
XCTAssertEqual(64 * 1024 - 1 + overheadPerChunk * 2, cryptor.calculateCiphertextSize(64 * 1024 - 1))
111+
XCTAssertEqual(64 * 1024 + overheadPerChunk * 2, cryptor.calculateCiphertextSize(64 * 1024))
152112

153-
XCTAssertEqual(64 * 1024 + 1 + 48 * 3, cryptor.calculateCiphertextSize(64 * 1024 + 1))
113+
XCTAssertEqual(64 * 1024 + 1 + overheadPerChunk * 3, cryptor.calculateCiphertextSize(64 * 1024 + 1))
154114
}
155115

156116
func testCalculateCleartextSize() throws {
117+
let overheadPerChunk = contentCryptor.nonceLen + contentCryptor.tagLen
118+
157119
XCTAssertEqual(0, try cryptor.calculateCleartextSize(0))
158120

159-
XCTAssertEqual(1, try cryptor.calculateCleartextSize(1 + 48))
160-
XCTAssertEqual(32 * 1024 - 1, try cryptor.calculateCleartextSize(32 * 1024 - 1 + 48))
161-
XCTAssertEqual(32 * 1024, try cryptor.calculateCleartextSize(32 * 1024 + 48))
121+
XCTAssertEqual(1, try cryptor.calculateCleartextSize(1 + overheadPerChunk))
122+
XCTAssertEqual(32 * 1024 - 1, try cryptor.calculateCleartextSize(32 * 1024 - 1 + overheadPerChunk))
123+
XCTAssertEqual(32 * 1024, try cryptor.calculateCleartextSize(32 * 1024 + overheadPerChunk))
162124

163-
XCTAssertEqual(32 * 1024 + 1, try cryptor.calculateCleartextSize(32 * 1024 + 1 + 48 * 2))
164-
XCTAssertEqual(32 * 1024 + 2, try cryptor.calculateCleartextSize(32 * 1024 + 2 + 48 * 2))
165-
XCTAssertEqual(64 * 1024 - 1, try cryptor.calculateCleartextSize(64 * 1024 - 1 + 48 * 2))
166-
XCTAssertEqual(64 * 1024, try cryptor.calculateCleartextSize(64 * 1024 + 48 * 2))
125+
XCTAssertEqual(32 * 1024 + 1, try cryptor.calculateCleartextSize(32 * 1024 + 1 + overheadPerChunk * 2))
126+
XCTAssertEqual(32 * 1024 + 2, try cryptor.calculateCleartextSize(32 * 1024 + 2 + overheadPerChunk * 2))
127+
XCTAssertEqual(64 * 1024 - 1, try cryptor.calculateCleartextSize(64 * 1024 - 1 + overheadPerChunk * 2))
128+
XCTAssertEqual(64 * 1024, try cryptor.calculateCleartextSize(64 * 1024 + overheadPerChunk * 2))
167129

168-
XCTAssertEqual(64 * 1024 + 1, try cryptor.calculateCleartextSize(64 * 1024 + 1 + 48 * 3))
130+
XCTAssertEqual(64 * 1024 + 1, try cryptor.calculateCleartextSize(64 * 1024 + 1 + overheadPerChunk * 3))
169131
}
170132

171133
func testCalculateCleartextSizeWithInvalidCiphertextSize() throws {
172134
XCTAssertThrowsError(try cryptor.calculateCleartextSize(1), "invalid ciphertext size") { error in
173135
XCTAssertEqual(.invalidParameter("Method not defined for input value 1"), error as? CryptoError)
174136
}
175-
XCTAssertThrowsError(try cryptor.calculateCleartextSize(48), "invalid ciphertext size") { error in
176-
XCTAssertEqual(.invalidParameter("Method not defined for input value 48"), error as? CryptoError)
137+
138+
let emptyPayload = contentCryptor.nonceLen + contentCryptor.tagLen
139+
XCTAssertThrowsError(try cryptor.calculateCleartextSize(emptyPayload), "invalid ciphertext size") { error in
140+
XCTAssertEqual(.invalidParameter("Method not defined for input value \(emptyPayload)"), error as? CryptoError)
177141
}
178-
XCTAssertThrowsError(try cryptor.calculateCleartextSize(32 * 1024 + 1 + 48), "invalid ciphertext size") { error in
179-
XCTAssertEqual(.invalidParameter("Method not defined for input value 32817"), error as? CryptoError)
142+
143+
let oneChunkPlusOneByte = cryptor.ciphertextChunkSize + 1
144+
XCTAssertThrowsError(try cryptor.calculateCleartextSize(oneChunkPlusOneByte), "invalid ciphertext size") { error in
145+
XCTAssertEqual(.invalidParameter("Method not defined for input value \(oneChunkPlusOneByte)"), error as? CryptoError)
180146
}
181-
XCTAssertThrowsError(try cryptor.calculateCleartextSize(32 * 1024 + 48 * 2), "invalid ciphertext size") { error in
182-
XCTAssertEqual(.invalidParameter("Method not defined for input value 32864"), error as? CryptoError)
147+
148+
let oneChunkPlusEmptySecondChunk = cryptor.ciphertextChunkSize + contentCryptor.nonceLen + contentCryptor.tagLen
149+
XCTAssertThrowsError(try cryptor.calculateCleartextSize(oneChunkPlusEmptySecondChunk), "invalid ciphertext size") { error in
150+
XCTAssertEqual(.invalidParameter("Method not defined for input value \(oneChunkPlusEmptySecondChunk)"), error as? CryptoError)
183151
}
184152
}
185153
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//
2+
// CryptorTests.swift
3+
// CryptomatorCryptoLibTests
4+
//
5+
// Created by Sebastian Stenzel on 27.04.20.
6+
// Copyright © 2020 Skymatic GmbH. All rights reserved.
7+
//
8+
9+
import XCTest
10+
@testable import CryptomatorCryptoLib
11+
12+
class CtrCryptorTest: CryptorTests {
13+
override class var defaultTestSuite: XCTestSuite {
14+
return XCTestSuite(forTestCaseClass: CtrCryptorTest.self)
15+
}
16+
17+
override func setUpWithError() throws {
18+
let aesKey = [UInt8](repeating: 0x55, count: 32)
19+
let macKey = [UInt8](repeating: 0x77, count: 32)
20+
let masterkey = Masterkey.createFromRaw(aesMasterKey: aesKey, macMasterKey: macKey)
21+
let cryptoSupport = CryptoSupportMock()
22+
let contentCryptor = CtrThenHmacContentCryptor(macKey: macKey, cryptoSupport: cryptoSupport)
23+
24+
try super.setUpWithError(masterkey: masterkey, cryptoSupport: cryptoSupport, contentCryptor: contentCryptor)
25+
}
26+
27+
func testCreateHeader() throws {
28+
let header = try cryptor.createHeader()
29+
XCTAssertEqual([UInt8](repeating: 0xF0, count: 16), header.nonce)
30+
XCTAssertEqual([UInt8](repeating: 0xF0, count: 32), header.contentKey)
31+
}
32+
33+
func testEncryptHeader() throws {
34+
let header = try cryptor.createHeader()
35+
let encrypted = try cryptor.encryptHeader(header)
36+
let expected: [UInt8] = [
37+
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
38+
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
39+
0x0D, 0x91, 0xF2, 0x9C, 0xC6, 0x35, 0xD7, 0x5E,
40+
0x1E, 0x42, 0x23, 0x1E, 0xC7, 0x90, 0x57, 0xE3,
41+
0x8D, 0x98, 0xF3, 0x58, 0x07, 0x2C, 0x9F, 0x03,
42+
0xBC, 0xEA, 0x5A, 0x98, 0x3B, 0x68, 0x62, 0x89,
43+
0x3E, 0xBC, 0x5E, 0x5E, 0x27, 0x39, 0xCB, 0x8E,
44+
0xD4, 0x27, 0x61, 0x06, 0x8E, 0x7F, 0x3A, 0x4E,
45+
0xC7, 0x9F, 0x4D, 0x3E, 0x20, 0x57, 0xDC, 0xE4,
46+
0x65, 0xA5, 0xFF, 0x93, 0xC2, 0x7B, 0xD2, 0xB8,
47+
0x3F, 0xE3, 0xD0, 0x8C, 0xB3, 0x92, 0xED, 0x96
48+
]
49+
XCTAssertEqual(expected, encrypted)
50+
}
51+
52+
func testDecryptHeader() throws {
53+
let ciphertext: [UInt8] = [
54+
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
55+
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
56+
0x0D, 0x91, 0xF2, 0x9C, 0xC6, 0x35, 0xD7, 0x5E,
57+
0x1E, 0x42, 0x23, 0x1E, 0xC7, 0x90, 0x57, 0xE3,
58+
0x8D, 0x98, 0xF3, 0x58, 0x07, 0x2C, 0x9F, 0x03,
59+
0xBC, 0xEA, 0x5A, 0x98, 0x3B, 0x68, 0x62, 0x89,
60+
0x3E, 0xBC, 0x5E, 0x5E, 0x27, 0x39, 0xCB, 0x8E,
61+
0xD4, 0x27, 0x61, 0x06, 0x8E, 0x7F, 0x3A, 0x4E,
62+
0xC7, 0x9F, 0x4D, 0x3E, 0x20, 0x57, 0xDC, 0xE4,
63+
0x65, 0xA5, 0xFF, 0x93, 0xC2, 0x7B, 0xD2, 0xB8,
64+
0x3F, 0xE3, 0xD0, 0x8C, 0xB3, 0x92, 0xED, 0x96
65+
]
66+
let decrypted = try cryptor.decryptHeader(ciphertext)
67+
XCTAssertEqual([UInt8](repeating: 0xF0, count: 16), decrypted.nonce)
68+
XCTAssertEqual([UInt8](repeating: 0xF0, count: 32), decrypted.contentKey)
69+
}
70+
}

0 commit comments

Comments
 (0)