CryptoSettingViewModel.swift 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. //
  2. // CryptoSettingViewModel.swift
  3. // Bark
  4. //
  5. // Created by huangfeng on 2022/11/10.
  6. // Copyright © 2022 Fin. All rights reserved.
  7. //
  8. import CryptoSwift
  9. import Foundation
  10. import RxCocoa
  11. import RxSwift
  12. class CryptoSettingViewModel: ViewModel, ViewModelType {
  13. struct Input {
  14. let algorithmChanged: Driver<String>
  15. let copyScript: Driver<CryptoSettingFields>
  16. let done: Driver<CryptoSettingFields>
  17. }
  18. struct Output {
  19. let initial: Driver<(algorithmList: [Algorithm], modeList: [String], paddingList: [String], initialFields: CryptoSettingFields?)>
  20. let modeListChanged: Driver<[String]>
  21. let paddingListChanged: Driver<[String]>
  22. let keyLengthChanged: Driver<Int>
  23. let showSnackbar: Driver<String>
  24. let done: Driver<Void>
  25. let copy: Driver<String>
  26. }
  27. struct Dependencies {
  28. let settingFieldRelay: BehaviorRelay<CryptoSettingFields?>
  29. let deviceKey: Driver<String>
  30. let serverAddress: Driver<String>
  31. }
  32. private let dependencies: Dependencies
  33. init(dependencies: Dependencies =
  34. Dependencies(
  35. settingFieldRelay: CryptoSettingRelay.shared.fields,
  36. // Key 好像没有对应的事件流,先“just”,懒得写了
  37. deviceKey: Driver.just(ServerManager.shared.currentServer.key),
  38. serverAddress: Driver.just(ServerManager.shared.currentServer.address)
  39. )
  40. ) {
  41. self.dependencies = dependencies
  42. }
  43. func transform(input: Input) -> Output {
  44. let showSnackbar = PublishRelay<String>()
  45. let modeList = input
  46. .algorithmChanged
  47. .compactMap { Algorithm(rawValue: $0) }
  48. .map { $0.modes }
  49. let keyLength =
  50. Driver.merge([
  51. Driver.just(dependencies.settingFieldRelay.value)
  52. .compactMap { $0 }
  53. .compactMap { Algorithm(rawValue: $0.algorithm)?.keyLength },
  54. input
  55. .algorithmChanged
  56. .compactMap { Algorithm(rawValue: $0)?.keyLength },
  57. ])
  58. // 保存配置
  59. let done = input.done
  60. .filter { fields in
  61. do {
  62. _ = try AESCryptoModel(cryptoFields: fields)
  63. return true
  64. }
  65. catch {
  66. showSnackbar.accept(error.rawString())
  67. return false
  68. }
  69. }
  70. done.drive(onNext: { [weak self] fields in
  71. // 保存设置
  72. self?.dependencies.settingFieldRelay.accept(fields)
  73. }).disposed(by: rx.disposeBag)
  74. let copyScript = input.copyScript
  75. .filter { [weak self] fields in
  76. do {
  77. _ = try AESCryptoModel(cryptoFields: fields)
  78. // 保存配置
  79. self?.dependencies.settingFieldRelay.accept(fields)
  80. return true
  81. }
  82. catch {
  83. showSnackbar.accept(error.rawString())
  84. return false
  85. }
  86. }
  87. let copy = Driver.combineLatest(copyScript, dependencies.deviceKey, dependencies.serverAddress)
  88. .map { fields, deviceKey,serverAddress in
  89. let key = fields.key ?? ""
  90. let iv = fields.iv ?? ""
  91. return
  92. """
  93. #!/usr/bin/env bash
  94. # Documentation: \(NSLocalizedString("encryptionUrl"))
  95. set -e
  96. # bark key
  97. deviceKey='\(deviceKey)'
  98. # push payload
  99. json='{"body": "test", "sound": "birdsong"}'
  100. # \(String(format: NSLocalizedString("keyComment"), Int(fields.algorithm.suffix(3))! / 8))
  101. key='\(key)'
  102. # \(NSLocalizedString("ivComment"))
  103. iv='\(iv)'
  104. # \(NSLocalizedString("opensslEncodingComment"))
  105. key=$(printf $key | xxd -ps -c 200)
  106. iv=$(printf $iv | xxd -ps -c 200)
  107. # \(NSLocalizedString("base64Notice"))
  108. ciphertext=$(echo -n $json | openssl enc -aes-\(fields.algorithm.suffix(3))-\(fields.mode.lowercased()) -K $key \(iv.count > 0 ? "-iv $iv " : "")| base64)
  109. # \(NSLocalizedString("consoleComment")) "\((try? AESCryptoModel(cryptoFields: fields).encrypt(text: "{\"body\": \"test\", \"sound\": \"birdsong\"}")) ?? "")"
  110. echo $ciphertext
  111. # \(NSLocalizedString("ciphertextComment"))
  112. curl --data-urlencode "ciphertext=$ciphertext"\( iv.count == 0 ? "" : " --data-urlencode \"iv=\(iv)\"") \(serverAddress)/$deviceKey
  113. """
  114. }
  115. return Output(
  116. initial: Driver.just((
  117. algorithmList: [Algorithm.aes128, Algorithm.aes192, Algorithm.aes256],
  118. modeList: ["CBC", "ECB", /* "GCM" */], // GCM 还没准备好示例代码,暂时禁用
  119. paddingList: ["pkcs7"],
  120. initialFields: dependencies.settingFieldRelay.value
  121. )),
  122. modeListChanged: modeList,
  123. paddingListChanged: Driver.just(["pkcs7"]),
  124. keyLengthChanged: keyLength,
  125. showSnackbar: showSnackbar.asDriver(onErrorDriveWith: .empty()),
  126. done: done.map { _ in () },
  127. copy: copy
  128. )
  129. }
  130. }