CTR.swift 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. //
  2. // CTR.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 08/03/16.
  6. // Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. // Counter (CTR)
  9. //
  10. struct CTRModeEncryptGenerator: BlockModeGenerator {
  11. typealias Element = Array<UInt8>
  12. let options: BlockModeOptions = [.InitializationVectorRequired, .PaddingRequired]
  13. private let iv: Element
  14. private let inputGenerator: AnyGenerator<Element>
  15. private let cipherOperation: CipherOperationOnBlock
  16. private var counter: UInt = 0
  17. init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Array<UInt8>>) {
  18. self.iv = iv
  19. self.cipherOperation = cipherOperation
  20. self.inputGenerator = inputGenerator
  21. }
  22. mutating func next() -> Element? {
  23. guard let plaintext = inputGenerator.next() else {
  24. return nil
  25. }
  26. let nonce = buildNonce(iv, counter: UInt64(counter))
  27. counter = counter + 1
  28. if let encrypted = cipherOperation(block: nonce) {
  29. return xor(plaintext, encrypted)
  30. }
  31. return nil
  32. }
  33. }
  34. struct CTRModeDecryptGenerator: BlockModeGenerator {
  35. typealias Element = Array<UInt8>
  36. let options: BlockModeOptions = [.InitializationVectorRequired, .PaddingRequired]
  37. private let iv: Element
  38. private let inputGenerator: AnyGenerator<Element>
  39. private let cipherOperation: CipherOperationOnBlock
  40. private var counter: UInt = 0
  41. init(iv: Array<UInt8>, cipherOperation: CipherOperationOnBlock, inputGenerator: AnyGenerator<Element>) {
  42. self.iv = iv
  43. self.cipherOperation = cipherOperation
  44. self.inputGenerator = inputGenerator
  45. }
  46. mutating func next() -> Element? {
  47. guard let ciphertext = inputGenerator.next() else {
  48. return nil
  49. }
  50. let nonce = buildNonce(iv, counter: UInt64(counter))
  51. counter = counter + 1
  52. if let decrypted = cipherOperation(block: nonce) {
  53. return xor(decrypted, ciphertext)
  54. }
  55. return nil
  56. }
  57. }
  58. private func buildNonce(iv: [UInt8], counter: UInt64) -> [UInt8] {
  59. let noncePartLen = AES.blockSize / 2
  60. let noncePrefix = Array(iv[0..<noncePartLen])
  61. let nonceSuffix = Array(iv[noncePartLen..<iv.count])
  62. let c = UInt64.withBytes(nonceSuffix) + counter
  63. return noncePrefix + arrayOfBytes(c)
  64. }