PBKDF2.swift 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. //
  2. // PBKDF2.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 05/04/16.
  6. // Copyright © 2016 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. public extension PKCS5 {
  9. // PBKDF2 - Password-Based Key Derivation Function 2. Key stretching technique.
  10. // DK = PBKDF2(PRF, Password, Salt, c, dkLen)
  11. public struct PBKDF2 {
  12. public enum Error: ErrorType {
  13. case InvalidInput
  14. }
  15. private let salt: [UInt8]
  16. private let iterations: Int // c
  17. private let numBlocks: UInt // l
  18. private let prf: HMAC
  19. public init(password: [UInt8], salt: [UInt8], iterations: Int = 4096 /* c */, keyLength: Int? = nil /* dkLen */ , hashVariant: HMAC.Variant = .sha256) throws {
  20. guard let prf = HMAC(key: password, variant: hashVariant) where (iterations > 0) && (password.count > 0) && (salt.count > 0) else {
  21. throw Error.InvalidInput
  22. }
  23. let keyLengthFinal: Int
  24. if let kl = keyLength {
  25. keyLengthFinal = kl
  26. } else {
  27. keyLengthFinal = hashVariant.size
  28. }
  29. let hLen = Double(prf.variant.size)
  30. if keyLength > Int(((pow(2,32) as Double) - 1) * hLen) {
  31. throw Error.InvalidInput
  32. }
  33. self.salt = salt
  34. self.iterations = iterations
  35. self.prf = prf
  36. self.numBlocks = UInt(ceil(Double(keyLengthFinal) / hLen)) // l = ceil(keyLength / hLen)
  37. }
  38. public func calculate() -> [UInt8] {
  39. var ret = [UInt8]()
  40. for i in 1...self.numBlocks {
  41. // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
  42. if let value = calculateBlock(salt: self.salt, blockNum: i) {
  43. ret.appendContentsOf(value)
  44. }
  45. }
  46. return ret
  47. }
  48. }
  49. }
  50. private extension PKCS5.PBKDF2 {
  51. private func INT(i: UInt) -> [UInt8] {
  52. var inti = [UInt8](count: 4, repeatedValue: 0)
  53. inti[0] = UInt8((i >> 24) & 0xFF)
  54. inti[1] = UInt8((i >> 16) & 0xFF)
  55. inti[2] = UInt8((i >> 8) & 0xFF)
  56. inti[3] = UInt8(i & 0xFF)
  57. return inti
  58. }
  59. // F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
  60. // U_1 = PRF (P, S || INT (i))
  61. private func calculateBlock(salt salt: [UInt8], blockNum: UInt) -> [UInt8]? {
  62. guard let u1 = prf.authenticate(salt + INT(blockNum)) else {
  63. return nil
  64. }
  65. var u = u1
  66. var ret = u
  67. if self.iterations > 1 {
  68. // U_2 = PRF (P, U_1) ,
  69. // U_c = PRF (P, U_{c-1}) .
  70. for _ in 2...self.iterations {
  71. u = prf.authenticate(u)!
  72. for x in 0..<ret.count {
  73. ret[x] = ret[x] ^ u[x]
  74. }
  75. }
  76. }
  77. return ret
  78. }
  79. }