DES.swift 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. //
  2. // DES.swift
  3. // CryptoSwift
  4. //
  5. // Created by Marcin Krzyzanowski on 21/01/2017.
  6. // Copyright © 2017 Marcin Krzyzanowski. All rights reserved.
  7. //
  8. // http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
  9. // Eric Young's http://ftp.nluug.nl/security/coast/libs/libdes/ALGORITHM
  10. /// Data Encryption Standard (DES).
  11. public final class DES: BlockCipher {
  12. public static let blockSize: Int = 8
  13. // PC-1
  14. fileprivate let permutedChoice1: Array<UInt8> = [7, 15, 23, 31, 39, 47, 55, 63,
  15. 6, 14, 22, 30, 38, 46, 54, 62,
  16. 5, 13, 21, 29, 37, 45, 53, 61,
  17. 4, 12, 20, 28, 1, 9, 17, 25,
  18. 33, 41, 49, 57, 2, 10, 18, 26,
  19. 34, 42, 50, 58, 3, 11, 19, 27,
  20. 35, 43, 51, 59, 36, 44, 52, 60]
  21. // PC-2
  22. fileprivate let permutedChoice2: Array<UInt8> = [42, 39, 45, 32, 55, 51, 53, 28,
  23. 41, 50, 35, 46, 33, 37, 44, 52,
  24. 30, 48, 40, 49, 29, 36, 43, 54,
  25. 15, 4, 25, 19, 9, 1, 26, 16,
  26. 5, 11, 23, 8, 12, 7, 17, 0,
  27. 22, 3, 10, 14, 6, 20, 27, 24]
  28. // Key schedule number of Left Shifts
  29. fileprivate let ksRotations: Array<UInt8> = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
  30. fileprivate var feistelBox = Array<Array<UInt32>>(repeating: Array<UInt32>(repeating: 0, count: 8), count: 64)
  31. fileprivate var subkeys = Array<UInt64>()
  32. public init(key: Array<UInt8>) throws {
  33. self.subkeys = self.generateSubkeys(key: key)
  34. }
  35. /// The 64 bits of the input block to be enciphered are first subjected to the following permutation, called the initial permutation.
  36. ///
  37. /// - Parameter block: 8 bytes
  38. /// - Returns: block
  39. fileprivate func initialPermuation(block: inout UInt64) {
  40. // block = b7 b6 b5 b4 b3 b2 b1 b0
  41. var b1 = block >> 48
  42. var b2 = block << 48
  43. block ^= b1 ^ b2 ^ b1 << 48 ^ b2 >> 48
  44. // block = b1 b0 b5 b4 b3 b2 b7 b6
  45. b1 = block >> 32 & 0xff00ff
  46. b2 = (block & 0xff00ff00)
  47. block ^= (b1 << 32) ^ b2 ^ (b1 << 8) ^ (b2 << 24) // exchange b0 b4 with b3 b7
  48. // exchange 4,5,6,7 with 32,33,34,35 etc.
  49. b1 = block & 0x0f0f00000f0f0000
  50. b2 = block & 0x0000f0f00000f0f0
  51. block ^= b1 ^ b2 ^ (b1 >> 12) ^ (b2 << 12)
  52. // exchange 0,1,4,5 with 18,19,22,23
  53. b1 = block & 0x3300330033003300
  54. b2 = block & 0x00cc00cc00cc00cc
  55. block ^= b1 ^ b2 ^ (b1 >> 6) ^ (b2 << 6)
  56. // exchange 0,2,4,6 with 9,11,13,15
  57. b1 = block & 0xaaaaaaaa55555555
  58. block ^= b1 ^ (b1 >> 33) ^ (b1 << 33)
  59. }
  60. fileprivate func finalPermutaion(block: inout UInt64) {
  61. var b1 = block & 0xaaaaaaaa55555555
  62. block ^= b1 ^ (b1 >> 33) ^ (b1 << 33)
  63. b1 = block & 0x3300330033003300
  64. var b2 = block & 0x00cc00cc00cc00cc
  65. block ^= b1 ^ b2 ^ (b1 >> 6) ^ (b2 << 6)
  66. b1 = block & 0x0f0f00000f0f0000
  67. b2 = block & 0x0000f0f00000f0f0
  68. block ^= b1 ^ b2 ^ (b1 >> 12) ^ (b2 << 12)
  69. b1 = block >> 32 & 0xff00ff
  70. b2 = block & 0xff00ff00
  71. block ^= (b1 << 32) ^ b2 ^ (b1 << 8) ^ (b2 << 24)
  72. b1 = block >> 48
  73. b2 = block << 48
  74. block ^= b1 ^ b2 ^ (b1 << 48) ^ (b2 >> 48)
  75. }
  76. /// Expands an input block of 32 bits, producing an output block of 48 bits.
  77. fileprivate func expand(src: UInt32) -> UInt64 {
  78. var src = (src << 5) | (src >> 27)
  79. var result: UInt64 = 0
  80. for _ in 0 ..< 8 {
  81. result <<= 6
  82. result |= UInt64(src) & (1 << 6 - 1)
  83. src = (src << 4) | (src >> 28)
  84. }
  85. return result
  86. }
  87. /// General purpose function to perform block permutations
  88. fileprivate func permute(block: UInt64, permutation: Array<UInt8>) -> UInt64 {
  89. var result: UInt64 = 0
  90. for (idx,value) in permutation.enumerated() {
  91. let bit = (block >> UInt64(value)) & 1
  92. result |= bit << UInt64(permutation.count - 1 - idx)
  93. }
  94. return result
  95. }
  96. // 16 28-bit blocks rotated according to the rotation ksRotations schedule
  97. fileprivate func ksRotate(_ value: UInt32) -> Array<UInt32> {
  98. var result = Array<UInt32>(repeating: 0, count: 16)
  99. var last = value
  100. for i in 0 ..< 16 {
  101. let left = (last << UInt32(4 + ksRotations[i])) >> 4
  102. let right = (last << 4) >> 32 - UInt32(ksRotations[i])
  103. result[i] = left | right
  104. last = result[i]
  105. }
  106. return result
  107. }
  108. fileprivate func feistel(l: UInt32, r: UInt32, k0: UInt64, k1: UInt64) -> (UInt32, UInt32) {
  109. var t:UInt32 = 0
  110. var l = l
  111. var r = r
  112. t = r ^ UInt32(k0 >> 32)
  113. l ^= feistelBox[7][Int(t) & 0x3f] ^ feistelBox[5][Int(t >> 8) & 0x3f] ^ feistelBox[3][Int(t >> 16) & 0x3f] ^ feistelBox[1][Int(t >> 24) & 0x3f]
  114. t = ((r << 28) | (r >> 4)) ^ UInt32(truncatingBitPattern: k0)
  115. l ^= feistelBox[6][Int(t) & 0x3f] ^ feistelBox[4][Int(t >> 8) & 0x3f] ^ feistelBox[2][Int(t >> 16) & 0x3f] ^ feistelBox[0][Int(t >> 24) & 0x3f]
  116. t = l ^ UInt32(truncatingBitPattern: k1 >> 32)
  117. r ^= feistelBox[7][Int(t) & 0x3f] ^ feistelBox[5][Int(t >> 8) & 0x3f] ^ feistelBox[3][Int(t >> 16) & 0x3f] ^ feistelBox[1][Int(t >> 24) & 0x3f]
  118. t = ((l << 28) | (l >> 4)) ^ UInt32(truncatingBitPattern: k1)
  119. r ^= feistelBox[6][Int(t) & 0x3f] ^ feistelBox[4][Int(t >> 8) & 0x3f] ^ feistelBox[2][Int(t >> 16) & 0x3f] ^ feistelBox[0][Int(t >> 24) & 0x3f]
  120. return (l, r)
  121. }
  122. fileprivate func generateSubkeys(key: Array<UInt8>) -> Array<UInt64> {
  123. //TODO: check endianess of UInt64
  124. var subkeys = Array<UInt64>(repeating: 0, count: 16)
  125. let permutedKey = self.permute(block: UInt64(bytes: key), permutation: permutedChoice1)
  126. // rotate halves of permuted key
  127. let leftRotations = ksRotate(UInt32(permutedKey >> 28))
  128. let rightRotations = ksRotate(UInt32(permutedKey << 4) >> 4)
  129. for i in 0 ..< 16 {
  130. let pc2Input = UInt64(leftRotations[i])<<28 | uint64(rightRotations[i])
  131. // apply PC2 permutation to 7 byte input
  132. subkeys[i] = self.permute(block: pc2Input, permutation: permutedChoice2)
  133. }
  134. return subkeys
  135. }
  136. }
  137. extension DES: Cipher {
  138. public func encrypt<C: Collection>(_ bytes: C) throws -> Array<UInt8> where C.Iterator.Element == UInt8, C.IndexDistance == Int, C.Index == Int, C.SubSequence: Collection, C.SubSequence.Iterator.Element == C.Iterator.Element, C.SubSequence.Index == C.Index, C.SubSequence.IndexDistance == C.IndexDistance {
  139. for chunk in bytes.batched(by: DES.blockSize) {
  140. var b = UInt64(bytes: chunk) //TODO: check endianess
  141. self.initialPermuation(block: &b)
  142. var left = UInt32(b >> 32)
  143. left = (left << 1) | (left >> 31)
  144. var right = UInt32(truncatingBitPattern: b)
  145. right = (right << 1) | (right >> 31)
  146. for i in 0 ..< 8 {
  147. (left, right) = feistel(l: left, r: right, k0: self.subkeys[2 * i], k1: self.subkeys[2 * i + 1])
  148. }
  149. left = (left << 31) | (left >> 1)
  150. right = (right << 31) | (right >> 1)
  151. var preOutput = UInt64(right) << 32 | UInt64(left)
  152. finalPermutaion(block: &preOutput)
  153. }
  154. return []
  155. }
  156. public func decrypt<C: Collection>(_ bytes: C) throws -> Array<UInt8> where C.Iterator.Element == UInt8, C.IndexDistance == Int, C.Index == Int {
  157. return []
  158. }
  159. }