added iOS source code
[wl-app.git] / iOS / Pods / OAuthSwift / Sources / SHA1.swift
1 //
2 //  SHA1.swift
3 //  OAuthSwift
4 //
5 //  Created by Dongri Jin on 1/28/15.
6 //  Copyright (c) 2015 Dongri Jin. All rights reserved.
7 //
8
9 import Foundation
10
11 class SHA1 {
12
13     private var message: [UInt8]
14
15     fileprivate let h: [UInt32] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
16
17     init(_ message: Data) {
18         self.message = message.bytes
19     }
20     init(_ message: [UInt8]) {
21         self.message = message
22     }
23
24     /// Common part for hash calculation. Prepare header data.
25     func prepare(_ message: [UInt8], _ blockSize: Int, _ allowance: Int) -> [UInt8] {
26         var tmpMessage = message
27
28         // Step 1. Append Padding Bits
29         tmpMessage.append(0x80) // append one bit (Byte with one bit) to message
30
31         // append "0" bit until message length in bits ≡ 448 (mod 512)
32         var msgLength = tmpMessage.count
33         var counter = 0
34
35         while msgLength % blockSize != (blockSize - allowance) {
36             counter += 1
37             msgLength += 1
38         }
39
40         tmpMessage += [UInt8](repeating: 0, count: counter)
41
42         return tmpMessage
43     }
44
45     func calculate() -> [UInt8] {
46         var tmpMessage = self.prepare(self.message, 64, 64 / 8)
47
48         // hash values
49         var hh = h
50
51         // append message length, in a 64-bit big-endian integer. So now the message length is a multiple of 512 bits.
52         tmpMessage += (self.message.count * 8).bytes(64 / 8)
53
54         // Process the message in successive 512-bit chunks:
55         let chunkSizeBytes = 512 / 8 // 64
56         for chunk in BytesSequence(data: tmpMessage, chunkSize: chunkSizeBytes) {
57             // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15, big-endian
58             // Extend the sixteen 32-bit words into eighty 32-bit words:
59             var M: [UInt32] = [UInt32](repeating: 0, count: 80)
60             for x in 0..<M.count {
61                 switch x {
62                 case 0...15:
63
64                     let memorySize = MemoryLayout<UInt32>.size
65                     let start = chunk.startIndex + (x * memorySize)
66                     let end = start + memorySize
67                     let le = chunk[start..<end].toUInt32
68                     M[x] = le.bigEndian
69                 default:
70                     M[x] = rotateLeft(M[x-3] ^ M[x-8] ^ M[x-14] ^ M[x-16], n: 1)
71                 }
72             }
73
74             var A = hh[0]
75             var B = hh[1]
76             var C = hh[2]
77             var D = hh[3]
78             var E = hh[4]
79
80             // Main loop
81             for j in 0...79 {
82                 var f: UInt32 = 0
83                 var k: UInt32 = 0
84
85                 switch j {
86                 case 0...19:
87                     f = (B & C) | ((~B) & D)
88                     k = 0x5A827999
89                 case 20...39:
90                     f = B ^ C ^ D
91                     k = 0x6ED9EBA1
92                 case 40...59:
93                     f = (B & C) | (B & D) | (C & D)
94                     k = 0x8F1BBCDC
95                 case 60...79:
96                     f = B ^ C ^ D
97                     k = 0xCA62C1D6
98                 default:
99                     break
100                 }
101
102                 let temp = (rotateLeft(A, n: 5) &+ f &+ E &+ M[j] &+ k) & 0xffffffff
103                 E = D
104                 D = C
105                 C = rotateLeft(B, n: 30)
106                 B = A
107                 A = temp
108
109             }
110
111             hh[0] = (hh[0] &+ A) & 0xffffffff
112             hh[1] = (hh[1] &+ B) & 0xffffffff
113             hh[2] = (hh[2] &+ C) & 0xffffffff
114             hh[3] = (hh[3] &+ D) & 0xffffffff
115             hh[4] = (hh[4] &+ E) & 0xffffffff
116         }
117
118         // Produce the final hash value (big-endian) as a 160 bit number:
119         var result = [UInt8]()
120         result.reserveCapacity(hh.count / 4)
121         hh.forEach {
122             let item = $0.bigEndian
123             result += [UInt8(item & 0xff), UInt8((item >> 8) & 0xff), UInt8((item >> 16) & 0xff), UInt8((item >> 24) & 0xff)]
124         }
125
126         return result
127     }
128
129     private func rotateLeft(_ v: UInt32, n: UInt32) -> UInt32 {
130         return ((v << n) & 0xFFFFFFFF) | (v >> (32 - n))
131     }
132
133 }
134
135 private struct BytesSequence<D: RandomAccessCollection>: Sequence where D.Iterator.Element == UInt8, D.Index == Int {
136     let data: D
137     let chunkSize: Int
138
139     func makeIterator() -> AnyIterator<D.SubSequence> {
140         var offset = data.startIndex
141         return AnyIterator {
142             let end = Swift.min(self.chunkSize, self.data.count - offset)
143             let result = self.data[offset..<offset + end]
144             offset = offset.advanced(by: result.count)
145             if !result.isEmpty {
146                 return result
147             }
148             return nil
149         }
150     }
151
152 }