PBKDF1.swift 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. //
  2. // PBKDF1.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 07/06/16.
  6. // Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. public extension PKCS5 {
  9. /// A key derivation function.
  10. ///
  11. /// PBKDF1 is recommended only for compatibility with existing
  12. /// applications since the keys it produces may not be large enough for
  13. /// some applications.
  14. public struct PBKDF1 {
  15. public enum Error: Swift.Error {
  16. case invalidInput
  17. case derivedKeyTooLong
  18. }
  19. public enum Variant {
  20. case md5, sha1
  21. var size: Int {
  22. switch (self) {
  23. case .md5:
  24. return MD5.digestLength
  25. case .sha1:
  26. return SHA1.digestLength
  27. }
  28. }
  29. fileprivate func calculateHash(_ bytes: Array<UInt8>) -> Array<UInt8>? {
  30. switch (self) {
  31. case .sha1:
  32. return Digest.sha1(bytes)
  33. case .md5:
  34. return Digest.md5(bytes)
  35. }
  36. }
  37. }
  38. private let iterations: Int // c
  39. private let variant: Variant
  40. private let keyLength: Int
  41. private let t1: Array<UInt8>
  42. /// - parameters:
  43. /// - salt: salt, an eight-bytes
  44. /// - variant: hash variant
  45. /// - iterations: iteration count, a positive integer
  46. /// - keyLength: intended length of derived key
  47. public init(password: Array<UInt8>, salt: Array<UInt8>, variant: Variant = .sha1, iterations: Int = 4096 /* c */ , keyLength: Int? = nil /* dkLen */ ) throws {
  48. precondition(iterations > 0)
  49. precondition(salt.count == 8)
  50. let keyLength = keyLength ?? variant.size
  51. if (keyLength > variant.size) {
  52. throw Error.derivedKeyTooLong
  53. }
  54. guard let t1 = variant.calculateHash(password + salt) else {
  55. throw Error.invalidInput
  56. }
  57. self.iterations = iterations
  58. self.variant = variant
  59. self.keyLength = keyLength
  60. self.t1 = t1
  61. }
  62. /// Apply the underlying hash function Hash for c iterations
  63. public func calculate() -> Array<UInt8> {
  64. var t = t1
  65. for _ in 2 ... self.iterations {
  66. t = self.variant.calculateHash(t)!
  67. }
  68. return Array(t[0 ..< self.keyLength])
  69. }
  70. }
  71. }