// // SHA1.swift // OAuthSwift // // Created by Dongri Jin on 1/28/15. // Copyright (c) 2015 Dongri Jin. All rights reserved. // import Foundation class SHA1 { private var message: [UInt8] fileprivate let h: [UInt32] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0] init(_ message: Data) { self.message = message.bytes } init(_ message: [UInt8]) { self.message = message } /// Common part for hash calculation. Prepare header data. func prepare(_ message: [UInt8], _ blockSize: Int, _ allowance: Int) -> [UInt8] { var tmpMessage = message // Step 1. Append Padding Bits tmpMessage.append(0x80) // append one bit (Byte with one bit) to message // append "0" bit until message length in bits ≡ 448 (mod 512) var msgLength = tmpMessage.count var counter = 0 while msgLength % blockSize != (blockSize - allowance) { counter += 1 msgLength += 1 } tmpMessage += [UInt8](repeating: 0, count: counter) return tmpMessage } func calculate() -> [UInt8] { var tmpMessage = self.prepare(self.message, 64, 64 / 8) // hash values var hh = h // append message length, in a 64-bit big-endian integer. So now the message length is a multiple of 512 bits. tmpMessage += (self.message.count * 8).bytes(64 / 8) // Process the message in successive 512-bit chunks: let chunkSizeBytes = 512 / 8 // 64 for chunk in BytesSequence(data: tmpMessage, chunkSize: chunkSizeBytes) { // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15, big-endian // Extend the sixteen 32-bit words into eighty 32-bit words: var M: [UInt32] = [UInt32](repeating: 0, count: 80) for x in 0...size let start = chunk.startIndex + (x * memorySize) let end = start + memorySize let le = chunk[start..> 8) & 0xff), UInt8((item >> 16) & 0xff), UInt8((item >> 24) & 0xff)] } return result } private func rotateLeft(_ v: UInt32, n: UInt32) -> UInt32 { return ((v << n) & 0xFFFFFFFF) | (v >> (32 - n)) } } private struct BytesSequence: Sequence where D.Iterator.Element == UInt8, D.Index == Int { let data: D let chunkSize: Int func makeIterator() -> AnyIterator { var offset = data.startIndex return AnyIterator { let end = Swift.min(self.chunkSize, self.data.count - offset) let result = self.data[offset..