RNCryptorTests.swift 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. //
  2. // RNCryptorTests.swift
  3. //
  4. // Copyright © 2015 Rob Napier. All rights reserved.
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a
  7. // copy of this software and associated documentation files (the "Software"),
  8. // to deal in the Software without restriction, including without limitation
  9. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. // and/or sell copies of the Software, and to permit persons to whom the
  11. // Software is furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22. // DEALINGS IN THE SOFTWARE.
  23. //
  24. import XCTest
  25. @testable import RNCryptor
  26. func randomLength() -> Int {
  27. return Int(arc4random_uniform(1024) + 1)
  28. }
  29. func randomData() -> Data {
  30. return RNCryptor.randomData(ofLength: randomLength())
  31. }
  32. class RNCryptorTests: XCTestCase {
  33. func testRandomData() {
  34. let len = 1024
  35. let data = RNCryptor.randomData(ofLength: len)
  36. XCTAssertEqual(data.count, len)
  37. let secondData = RNCryptor.randomData(ofLength: len)
  38. XCTAssertNotEqual(data, secondData, "Random data this long should never be equal")
  39. }
  40. func testKDF() {
  41. let password = "a"
  42. let salt = "0102030405060708".dataFromHexEncoding!
  43. let key = V3.makeKey(forPassword: password, withSalt: salt)
  44. let expect = "fc632b0c a6b23eff 9a9dc3e0 e585167f 5a328916 ed19f835 58be3ba9 828797cd".dataFromHexEncoding!
  45. XCTAssertEqual(key, expect)
  46. }
  47. func testEngine() {
  48. let data = randomData()
  49. let encryptKey = RNCryptor.randomData(ofLength: V3.keySize)
  50. let iv = RNCryptor.randomData(ofLength: V3.ivSize)
  51. var encrypted = Data()
  52. let encryptor = Engine(operation: .encrypt, key: encryptKey, iv: iv)
  53. encrypted.append(encryptor.update(withData: data))
  54. encrypted.append(encryptor.finalData())
  55. let decryptor = Engine(operation: .decrypt, key: encryptKey, iv: iv)
  56. var decrypted = decryptor.update(withData: encrypted)
  57. decrypted.append(decryptor.finalData())
  58. XCTAssertEqual(decrypted, data)
  59. }
  60. func testKeyEncryptor() {
  61. let encryptKey = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f".dataFromHexEncoding!
  62. let hmacKey = "0102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f00".dataFromHexEncoding!
  63. let iv = "02030405060708090a0b0c0d0e0f0001".dataFromHexEncoding!
  64. let plaintext = "01".dataFromHexEncoding!
  65. let ciphertext = "03000203 04050607 08090a0b 0c0d0e0f 0001981b 22e7a644 8118d695 bd654f72 e9d6ed75 ec14ae2a a067eed2 a98a56e0 993dfe22 ab5887b3 f6e3cdd4 0767f519 5eb5".dataFromHexEncoding!
  66. let encryptor = RNCryptor.EncryptorV3(encryptionKey: encryptKey, hmacKey: hmacKey, iv: iv)
  67. let encrypted = encryptor.encrypt(data: plaintext)
  68. XCTAssertEqual(encrypted, ciphertext)
  69. }
  70. func testKeyDecryptor() {
  71. let encryptKey = "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f".dataFromHexEncoding!
  72. let hmacKey = "0102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f00".dataFromHexEncoding!
  73. let plaintext = "01".dataFromHexEncoding!
  74. let ciphertext = "03000203 04050607 08090a0b 0c0d0e0f 0001981b 22e7a644 8118d695 bd654f72 e9d6ed75 ec14ae2a a067eed2 a98a56e0 993dfe22 ab5887b3 f6e3cdd4 0767f519 5eb5".dataFromHexEncoding!
  75. let decryptor = RNCryptor.DecryptorV3(encryptionKey: encryptKey, hmacKey: hmacKey)
  76. do {
  77. let decrypted = try decryptor.decrypt(data: ciphertext)
  78. XCTAssertEqual(decrypted, plaintext)
  79. } catch {
  80. XCTFail("Caught: \(error)")
  81. }
  82. }
  83. func testPasswordEncryptor() {
  84. let password = "thepassword"
  85. let encryptionSalt = "0001020304050607".dataFromHexEncoding!
  86. let hmacSalt = "0102030405060708".dataFromHexEncoding!
  87. let iv = "02030405060708090a0b0c0d0e0f0001".dataFromHexEncoding!
  88. let plaintext = "01".dataFromHexEncoding!
  89. let ciphertext = "03010001 02030405 06070102 03040506 07080203 04050607 08090a0b 0c0d0e0f 0001a1f8 730e0bf4 80eb7b70 f690abf2 1e029514 164ad3c4 74a51b30 c7eaa1ca 545b7de3 de5b010a cbad0a9a 13857df6 96a8".dataFromHexEncoding!
  90. let encryptor = RNCryptor.EncryptorV3(password: password, encryptionSalt: encryptionSalt, hmacSalt: hmacSalt, iv: iv)
  91. let encrypted = encryptor.encrypt(data: plaintext)
  92. XCTAssertEqual(encrypted, ciphertext)
  93. }
  94. func testPasswordDecryptor() {
  95. let password = "thepassword"
  96. let plaintext = "01".dataFromHexEncoding!
  97. let ciphertext = "03010001 02030405 06070102 03040506 07080203 04050607 08090a0b 0c0d0e0f 0001a1f8 730e0bf4 80eb7b70 f690abf2 1e029514 164ad3c4 74a51b30 c7eaa1ca 545b7de3 de5b010a cbad0a9a 13857df6 96a8".dataFromHexEncoding!
  98. let decryptor = RNCryptor.Decryptor(password: password)
  99. do {
  100. let decrypted = try decryptor.decrypt(data: ciphertext)
  101. XCTAssertEqual(decrypted, plaintext)
  102. } catch {
  103. XCTFail("Caught: \(error)")
  104. }
  105. }
  106. func testOneShotKey() {
  107. let encryptionKey = RNCryptor.randomData(ofLength: V3.keySize)
  108. let hmacKey = RNCryptor.randomData(ofLength: V3.keySize)
  109. let data = randomData()
  110. let ciphertext = RNCryptor.EncryptorV3(encryptionKey: encryptionKey, hmacKey: hmacKey).encrypt(data: data)
  111. let plaintext: Data
  112. do {
  113. plaintext = try RNCryptor.DecryptorV3(encryptionKey: encryptionKey, hmacKey: hmacKey).decrypt(data: ciphertext)
  114. } catch {
  115. plaintext = Data([0xaa])
  116. XCTFail("Caught: \(error)")
  117. }
  118. XCTAssertEqual(plaintext, data)
  119. }
  120. func testOneShotPassword() {
  121. let password = "thepassword"
  122. let data = randomData()
  123. let ciphertext = RNCryptor.Encryptor(password: password).encrypt(data: data)
  124. let plaintext: Data
  125. do {
  126. plaintext = try RNCryptor.Decryptor(password: password).decrypt(data: ciphertext)
  127. } catch {
  128. plaintext = Data([0])
  129. XCTFail("Caught: \(error)")
  130. }
  131. XCTAssertEqual(plaintext, data)
  132. }
  133. func testMultipleUpdate() {
  134. let password = "thepassword"
  135. let datas = (0..<10).map{ _ in randomData() }
  136. let fullData = Data(datas.joined())
  137. let encryptor = RNCryptor.Encryptor(password: password)
  138. var ciphertext = Data()
  139. for data in datas {
  140. ciphertext.append(encryptor.update(withData: data))
  141. }
  142. ciphertext.append(encryptor.finalData())
  143. do {
  144. let decrypted = try RNCryptor.Decryptor(password: password).decrypt(data: ciphertext)
  145. XCTAssertEqual(fullData, decrypted)
  146. } catch {
  147. XCTFail("Caught: \(error)")
  148. }
  149. }
  150. func testBadFormat() {
  151. let data = NSMutableData(length: randomLength())!
  152. do {
  153. try _ = RNCryptor.Decryptor(password: "password").decrypt(data: data as Data)
  154. XCTFail("Should have thrown")
  155. } catch let error as RNCryptor.Error {
  156. XCTAssertEqual(error, RNCryptor.Error.unknownHeader)
  157. } catch {
  158. XCTFail("Threw wrong thing \(error)")
  159. }
  160. }
  161. func testBadFormatV3() {
  162. let data = NSMutableData(length: randomLength())!
  163. do {
  164. try _ = RNCryptor.DecryptorV3(password: "password").decrypt(data: data as Data)
  165. XCTFail("Should not thrown")
  166. } catch let error as RNCryptor.Error {
  167. XCTAssertEqual(error, RNCryptor.Error.unknownHeader)
  168. } catch {
  169. XCTFail("Threw wrong thing \(error)")
  170. }
  171. }
  172. func testBadPassword() {
  173. let password = "thepassword"
  174. let data = randomData()
  175. let ciphertext = RNCryptor.Encryptor(password: password).encrypt(data: data)
  176. do {
  177. let _ = try RNCryptor.Decryptor(password: "wrongpassword").decrypt(data: ciphertext)
  178. XCTFail("Should have failed to decrypt")
  179. } catch let err as RNCryptor.Error {
  180. XCTAssertEqual(err, RNCryptor.Error.hmacMismatch)
  181. } catch {
  182. XCTFail("Wrong error: \(error)")
  183. }
  184. }
  185. func testOneShot() {
  186. let password = "thepassword"
  187. let data = randomData()
  188. let ciphertext = RNCryptor.encrypt(data: data, withPassword: password)
  189. do {
  190. let decrypted = try RNCryptor.decrypt(data: ciphertext, withPassword: password)
  191. XCTAssertEqual(decrypted, data)
  192. } catch {
  193. XCTFail("Caught: \(error)")
  194. }
  195. }
  196. }