XChaCha20Tests.swift 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. //
  2. // CryptoSwift
  3. //
  4. // Copyright (C) Marcin Krzyżanowski <marcin@krzyzanowskim.com>
  5. // This software is provided 'as-is', without any express or implied warranty.
  6. //
  7. // In no event will the authors be held liable for any damages arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
  10. //
  11. // - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
  12. // - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  13. // - This notice may not be removed or altered from any source or binary distribution.
  14. //
  15. import XCTest
  16. @testable import CryptoSwift
  17. final class XChaCha20Tests: XCTestCase {
  18. /// See: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#section-2.2.1
  19. func testHChaCha20BlockFunction() {
  20. let key: Array<UInt8> = .init(
  21. hex: "00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f".replacingOccurrences(of: ":", with: ""))
  22. let counter: Array<UInt8> = .init(
  23. hex: "00:00:00:09:00:00:00:4a:00:00:00:00:31:41:59:27".replacingOccurrences(of: ":", with: ""))
  24. XCTAssertEqual(
  25. XChaCha20.hChaCha20(key: key, nonce: counter).toHexString(),
  26. """
  27. 82413b42 27b27bfe d30e4250 8a877d73
  28. a0f9e4d5 8a74a853 c12ec413 26d3ecdc
  29. """.replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "\n", with: "")
  30. )
  31. }
  32. // See: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#appendix-A.3.2.1
  33. let plaintext: Array<UInt8> = .init(
  34. hex: """
  35. 5468652064686f6c65202870726f6e6f756e6365642022646f6c652229206973
  36. 20616c736f206b6e6f776e2061732074686520417369617469632077696c6420
  37. 646f672c2072656420646f672c20616e642077686973746c696e6720646f672e
  38. 2049742069732061626f7574207468652073697a65206f662061204765726d61
  39. 6e20736865706865726420627574206c6f6f6b73206d6f7265206c696b652061
  40. 206c6f6e672d6c656767656420666f782e205468697320686967686c7920656c
  41. 757369766520616e6420736b696c6c6564206a756d70657220697320636c6173
  42. 736966696564207769746820776f6c7665732c20636f796f7465732c206a6163
  43. 6b616c732c20616e6420666f78657320696e20746865207461786f6e6f6d6963
  44. 2066616d696c792043616e696461652e
  45. """.replacingOccurrences(of: "\n", with: ""))
  46. let key: Array<UInt8> = .init(hex: "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f")
  47. let iv: Array<UInt8> = .init(hex: "404142434445464748494a4b4c4d4e4f5051525354555658")
  48. let expectedResult0 = """
  49. 4559abba4e48c16102e8bb2c05e6947f50a786de162f9b0b7e592a9b53d0d4e9
  50. 8d8d6410d540a1a6375b26d80dace4fab52384c731acbf16a5923c0c48d3575d
  51. 4d0d2c673b666faa731061277701093a6bf7a158a8864292a41c48e3a9b4c0da
  52. ece0f8d98d0d7e05b37a307bbb66333164ec9e1b24ea0d6c3ffddcec4f68e744
  53. 3056193a03c810e11344ca06d8ed8a2bfb1e8d48cfa6bc0eb4e2464b74814240
  54. 7c9f431aee769960e15ba8b96890466ef2457599852385c661f752ce20f9da0c
  55. 09ab6b19df74e76a95967446f8d0fd415e7bee2a12a114c20eb5292ae7a349ae
  56. 577820d5520a1f3fb62a17ce6a7e68fa7c79111d8860920bc048ef43fe84486c
  57. cb87c25f0ae045f0cce1e7989a9aa220a28bdd4827e751a24a6d5c62d790a663
  58. 93b93111c1a55dd7421a10184974c7c5
  59. """.replacingOccurrences(of: "\n", with: "")
  60. func testXChaCha20() {
  61. do {
  62. let actualResult0 = try XChaCha20(key: key, iv: iv, blockCounter: 0).encrypt(self.plaintext).toHexString()
  63. XCTAssertEqual(actualResult0, self.expectedResult0)
  64. // See: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#appendix-A.3.2.2
  65. let actualResult1 = try XChaCha20(key: key, iv: iv, blockCounter: 1).encrypt(self.plaintext).toHexString()
  66. XCTAssertEqual(
  67. actualResult1,
  68. """
  69. 7d0a2e6b7f7c65a236542630294e063b7ab9b555a5d5149aa21e4ae1e4fbce87
  70. ecc8e08a8b5e350abe622b2ffa617b202cfad72032a3037e76ffdcdc4376ee05
  71. 3a190d7e46ca1de04144850381b9cb29f051915386b8a710b8ac4d027b8b050f
  72. 7cba5854e028d564e453b8a968824173fc16488b8970cac828f11ae53cabd201
  73. 12f87107df24ee6183d2274fe4c8b1485534ef2c5fbc1ec24bfc3663efaa08bc
  74. 047d29d25043532db8391a8a3d776bf4372a6955827ccb0cdd4af403a7ce4c63
  75. d595c75a43e045f0cce1f29c8b93bd65afc5974922f214a40b7c402cdb91ae73
  76. c0b63615cdad0480680f16515a7ace9d39236464328a37743ffc28f4ddb324f4
  77. d0f5bbdc270c65b1749a6efff1fbaa09536175ccd29fb9e6057b307320d31683
  78. 8a9c71f70b5b5907a66f7ea49aadc409
  79. """.replacingOccurrences(of: "\n", with: "")
  80. )
  81. } catch {
  82. XCTFail(error.localizedDescription)
  83. }
  84. }
  85. func testXChaCha20PartialEncryption() {
  86. do {
  87. let cipher = try XChaCha20(key: key, iv: iv)
  88. var ciphertext = Array<UInt8>()
  89. var encryptor = try cipher.makeEncryptor()
  90. try self.plaintext.batched(by: 8).forEach { chunk in
  91. ciphertext += try encryptor.update(withBytes: chunk)
  92. }
  93. ciphertext += try encryptor.finish()
  94. XCTAssertEqual(ciphertext.toHexString(), self.expectedResult0)
  95. } catch {
  96. XCTFail(error.localizedDescription)
  97. }
  98. }
  99. func testXChaCha20PartialDecryption() {
  100. do {
  101. let cipher = try XChaCha20(key: key, iv: iv)
  102. var plaintext = Array<UInt8>()
  103. var decryptor = try cipher.makeDecryptor()
  104. let ciphertext = Array<UInt8>(hex: expectedResult0)
  105. try ciphertext.batched(by: 8).forEach { chunk in
  106. plaintext += try decryptor.update(withBytes: chunk)
  107. }
  108. plaintext += try decryptor.finish()
  109. XCTAssertEqual(plaintext, self.plaintext)
  110. } catch {
  111. XCTFail(error.localizedDescription)
  112. }
  113. }
  114. static func allTests() -> [(String, (XChaCha20Tests) -> () -> Void)] {
  115. let tests = [
  116. ("Test Vector for the HChaCha20 Block Function", testHChaCha20BlockFunction),
  117. ("Test Vectors for XChaCha20", testXChaCha20),
  118. ("XChaCha20 partial encryption", testXChaCha20PartialEncryption),
  119. ("XChaCha20 partial decryption", testXChaCha20PartialDecryption),
  120. ]
  121. return tests
  122. }
  123. }