| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- //
- // SHA1.swift
- // CryptoSwift
- //
- // Created by Marcin Krzyzanowski on 16/08/14.
- // Copyright (c) 2014 Marcin Krzyzanowski. All rights reserved.
- //
- import Foundation
- final class SHA1 : HashProtocol {
- var size:Int = 20 // 160 / 8
- let message: NSData
-
- init(_ message: NSData) {
- self.message = message
- }
-
- private let h:[UInt32] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]
-
- func calculate() -> NSData {
- let tmpMessage = self.prepare(64)
-
- // 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.appendBytes((self.message.length * 8).bytes(64 / 8));
-
- // Process the message in successive 512-bit chunks:
- let chunkSizeBytes = 512 / 8 // 64
- var leftMessageBytes = tmpMessage.length
- for var i = 0; i < tmpMessage.length; i = i + chunkSizeBytes, leftMessageBytes -= chunkSizeBytes {
- let chunk = tmpMessage.subdataWithRange(NSRange(location: i, length: min(chunkSizeBytes,leftMessageBytes)))
- // 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](count: 80, repeatedValue: 0)
- for x in 0..<M.count {
- switch (x) {
- case 0...15:
- var le:UInt32 = 0
- chunk.getBytes(&le, range:NSRange(location:x * sizeofValue(M[x]), length: sizeofValue(M[x])));
- M[x] = le.bigEndian
- break
- default:
- M[x] = rotateLeft(M[x-3] ^ M[x-8] ^ M[x-14] ^ M[x-16], n: 1) //FIXME: n:
- break
- }
- }
-
- var A = hh[0]
- var B = hh[1]
- var C = hh[2]
- var D = hh[3]
- var E = hh[4]
-
- // Main loop
- for j in 0...79 {
- var f: UInt32 = 0;
- var k: UInt32 = 0
-
- switch (j) {
- case 0...19:
- f = (B & C) | ((~B) & D)
- k = 0x5A827999
- break
- case 20...39:
- f = B ^ C ^ D
- k = 0x6ED9EBA1
- break
- case 40...59:
- f = (B & C) | (B & D) | (C & D)
- k = 0x8F1BBCDC
- break
- case 60...79:
- f = B ^ C ^ D
- k = 0xCA62C1D6
- break
- default:
- break
- }
-
- let temp = (rotateLeft(A,n: 5) &+ f &+ E &+ M[j] &+ k) & 0xffffffff
- E = D
- D = C
- C = rotateLeft(B, n: 30)
- B = A
- A = temp
- }
-
- hh[0] = (hh[0] &+ A) & 0xffffffff
- hh[1] = (hh[1] &+ B) & 0xffffffff
- hh[2] = (hh[2] &+ C) & 0xffffffff
- hh[3] = (hh[3] &+ D) & 0xffffffff
- hh[4] = (hh[4] &+ E) & 0xffffffff
- }
-
- // Produce the final hash value (big-endian) as a 160 bit number:
- let buf: NSMutableData = NSMutableData();
- for item in hh {
- var i:UInt32 = item.bigEndian
- buf.appendBytes(&i, length: sizeofValue(i))
- }
-
- return buf.copy() as! NSData;
- }
- }
|