Damian Kołakowski 9 лет назад
Родитель
Сommit
1d8564bd9a

+ 0 - 1
Sources/TLS/BigNum.swift

@@ -15,7 +15,6 @@ public struct BigNum: Equatable, Comparable, CustomStringConvertible {
     // TODO/Improvments
     // TODO/Improvments
     //  - add init(...) for string literal
     //  - add init(...) for string literal
     //  - add powmod operation
     //  - add powmod operation
-    //  - fix '+' and '-' operators for negative numbers
     
     
     internal var digits = [UInt8]()
     internal var digits = [UInt8]()
     internal var signum = 0
     internal var signum = 0

+ 23 - 12
Sources/TLS/SHA1.swift

@@ -112,21 +112,32 @@ public struct SHA1 {
         
         
         // Produce the final hash value (big-endian) as a 160 bit number:
         // Produce the final hash value (big-endian) as a 160 bit number:
         
         
-        var result = [UInt8]()
+        var digest = [UInt8]()
         
         
-        let h0Big = h0.bigEndian
-        let h1Big = h1.bigEndian
-        let h2Big = h2.bigEndian
-        let h3Big = h3.bigEndian
-        let h4Big = h4.bigEndian
+        h0 = h0.bigEndian
+        h1 = h1.bigEndian
+        h2 = h2.bigEndian
+        h3 = h3.bigEndian
+        h4 = h4.bigEndian
+        
+        withUnsafePointer(&h0) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h1) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h2) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h3) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h4) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
         
         
-        result += ([UInt8(h0Big & 0xFF), UInt8((h0Big >> 8) & 0xFF), UInt8((h0Big >> 16) & 0xFF), UInt8((h0Big >> 24) & 0xFF)]);
-        result += ([UInt8(h1Big & 0xFF), UInt8((h1Big >> 8) & 0xFF), UInt8((h1Big >> 16) & 0xFF), UInt8((h1Big >> 24) & 0xFF)]);
-        result += ([UInt8(h2Big & 0xFF), UInt8((h2Big >> 8) & 0xFF), UInt8((h2Big >> 16) & 0xFF), UInt8((h2Big >> 24) & 0xFF)]);
-        result += ([UInt8(h3Big & 0xFF), UInt8((h3Big >> 8) & 0xFF), UInt8((h3Big >> 16) & 0xFF), UInt8((h3Big >> 24) & 0xFF)]);
-        result += ([UInt8(h4Big & 0xff), UInt8((h4Big >> 8) & 0xFF), UInt8((h4Big >> 16) & 0xFF), UInt8((h4Big >> 24) & 0xFF)]);
         
         
-        return result
+        return digest
     }
     }
     
     
     private static func rotateLeft(_ v: UInt32, _ n: UInt32) -> UInt32 {
     private static func rotateLeft(_ v: UInt32, _ n: UInt32) -> UInt32 {

+ 194 - 0
Sources/TLS/SHA256.swift

@@ -0,0 +1,194 @@
+//
+//  SHA256.swift
+//  Swifter
+//
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+
+#if os(Linux)
+    import Glibc
+#else
+    import Foundation
+#endif
+
+
+public struct SHA256 {
+    
+    public static func hash(_ input: [UInt8]) -> [UInt8] {
+        
+        // Alghorithm from: https://en.wikipedia.org/wiki/SHA-2
+        // http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
+        
+        var message = input
+        
+        var h0 = UInt32(littleEndian: 0x6a09e667)
+        var h1 = UInt32(littleEndian: 0xbb67ae85)
+        var h2 = UInt32(littleEndian: 0x3c6ef372)
+        var h3 = UInt32(littleEndian: 0xa54ff53a)
+        var h4 = UInt32(littleEndian: 0x510e527f)
+        var h5 = UInt32(littleEndian: 0x9b05688c)
+        var h6 = UInt32(littleEndian: 0x1f83d9ab)
+        var h7 = UInt32(littleEndian: 0x5be0cd19)
+        
+        // ml = message length in bits (always a multiple of the number of bits in a character).
+        
+        let ml = UInt64(message.count * 8)
+        
+        // append the bit '1' to the message e.g. by adding 0x80 if message length is a multiple of 8 bits.
+        
+        message.append(0x80)
+        
+        // append 0 ≤ k < 512 bits '0', such that the resulting message length in bits is congruent to −64 ≡ 448 (mod 512)
+        
+        let padBytesCount = ( message.count + 8 ) % 64
+        
+        message.append(contentsOf: [UInt8](repeating: 0, count: 64 - padBytesCount))
+        
+        // append ml, in a 64-bit big-endian integer. Thus, the total length is a multiple of 512 bits.
+        
+        var mlBigEndian = ml.bigEndian
+        withUnsafePointer(&mlBigEndian) {
+            message.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 8)))
+        }
+        
+        // Process the message in successive 512-bit chunks ( 64 bytes chunks ):
+        
+        for chunkStart in 0..<message.count/64 {
+            var words = [UInt32](repeating: 0, count: 64)
+            let chunk = message[chunkStart*64..<chunkStart*64+64]
+            
+            // Break chunk into sixteen 32-bit big-endian words w[i], 0 ≤ i ≤ 15
+            
+            for i in 0...15 {
+                let value = chunk.withUnsafeBufferPointer({ UnsafePointer<UInt32>($0.baseAddress! + (i*4)).pointee})
+                words[i] = value.bigEndian
+            }
+        
+            // Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
+            
+            for i in 16..<words.count {
+                let s0 = (rotateRight(words[i-15],  7)) ^ (rotateRight(words[i-15], 18)) ^ (words[i-15] >> 3 )
+                let s1 = (rotateRight(words[i-2 ], 17)) ^ (rotateRight(words[i-2 ], 19)) ^ (words[i-2 ] >> 10)
+                words[i] = words[i-16] &+ s0 &+ words[i-7] &+ s1
+            }
+            
+            // Initialize hash value for this chunk:
+            
+            var a = h0
+            var b = h1
+            var c = h2
+            var d = h3
+            var e = h4
+            var f = h5
+            var g = h6
+            var h = h7
+            
+
+            for i in 0...63 {
+                
+                let S0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22)
+                let S1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25)
+                
+                let ch = (e & f) ^ ((~e) & g)
+                let maj = (a & b) ^ (a & c) ^ (b & c)
+                
+                let temp1 = h &+ S1 &+ ch &+ K[i] &+ words[i]
+                let temp2 = S0 &+ maj
+                
+                h = g
+                g = f
+                f = e
+                e = d &+ temp1
+                d = c
+                c = b
+                b = a
+                a = temp1 &+ temp2
+            }
+            
+            // Add this chunk's hash to result so far:
+            
+            h0 = ( h0 &+ a )
+            h1 = ( h1 &+ b )
+            h2 = ( h2 &+ c )
+            h3 = ( h3 &+ d )
+            h4 = ( h4 &+ e )
+            h5 = ( h5 &+ f )
+            h6 = ( h6 &+ g )
+            h7 = ( h7 &+ h )
+            
+            
+            
+        }
+        
+        // Produce the final hash value (big-endian):
+        
+        var digest = [UInt8]()
+        
+        h0 = h0.bigEndian
+        h1 = h1.bigEndian
+        h2 = h2.bigEndian
+        h3 = h3.bigEndian
+        h4 = h4.bigEndian
+        h5 = h5.bigEndian
+        h6 = h6.bigEndian
+        h7 = h7.bigEndian
+        
+        withUnsafePointer(&h0) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h1) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h2) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h3) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h4) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h5) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h6) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        withUnsafePointer(&h7) {
+            digest.append(contentsOf: Array(UnsafeBufferPointer<UInt8>(start: UnsafePointer($0), count: 4)))
+        }
+        
+        
+        return digest
+    }
+    
+    private static func rotateRight(_ v : UInt32, _ n: UInt32) -> UInt32 {
+        return (v >> n) | (v << (32 - n))
+    }
+    
+    private static func rotateLeft(_ v: UInt32, _ n: UInt32) -> UInt32 {
+        return ((v << n) & 0xFFFFFFFF) | (v >> (32 - n))
+    }
+    
+    private static var K: [UInt32] = [
+        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+    ]
+}
+
+extension String {
+    
+    public func sha256() -> String {
+        return self.sha256().hex()
+    }
+    
+    public func sha256() -> [UInt8] {
+        return SHA256.hash([UInt8](self.utf8))
+    }
+}

+ 8 - 0
XCode/Swifter.xcodeproj/project.pbxproj

@@ -160,6 +160,9 @@
 		7CDF26FF1D5CD64600666F69 /* SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CDF26E31D5CD64600666F69 /* SHA1.swift */; };
 		7CDF26FF1D5CD64600666F69 /* SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CDF26E31D5CD64600666F69 /* SHA1.swift */; };
 		7CE0B9EF1D5BBAAD0070D292 /* SwifterTestsHMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CE0B9EE1D5BBAAD0070D292 /* SwifterTestsHMAC.swift */; };
 		7CE0B9EF1D5BBAAD0070D292 /* SwifterTestsHMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CE0B9EE1D5BBAAD0070D292 /* SwifterTestsHMAC.swift */; };
 		7CE0B9F01D5BBAAD0070D292 /* SwifterTestsHMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CE0B9EE1D5BBAAD0070D292 /* SwifterTestsHMAC.swift */; };
 		7CE0B9F01D5BBAAD0070D292 /* SwifterTestsHMAC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CE0B9EE1D5BBAAD0070D292 /* SwifterTestsHMAC.swift */; };
+		7CFEA3541D5DFDA9009A9BF7 /* SHA256.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CFEA3531D5DFDA9009A9BF7 /* SHA256.swift */; };
+		7CFEA3551D5DFDA9009A9BF7 /* SHA256.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CFEA3531D5DFDA9009A9BF7 /* SHA256.swift */; };
+		7CFEA3561D5DFDA9009A9BF7 /* SHA256.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CFEA3531D5DFDA9009A9BF7 /* SHA256.swift */; };
 		98630C071A1C9A9D00478D08 /* login.html in Resources */ = {isa = PBXBuildFile; fileRef = 98630C061A1C9A9D00478D08 /* login.html */; };
 		98630C071A1C9A9D00478D08 /* login.html in Resources */ = {isa = PBXBuildFile; fileRef = 98630C061A1C9A9D00478D08 /* login.html */; };
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
 
 
@@ -295,6 +298,7 @@
 		7CDF26E21D5CD64600666F69 /* RSA.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSA.swift; sourceTree = "<group>"; };
 		7CDF26E21D5CD64600666F69 /* RSA.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSA.swift; sourceTree = "<group>"; };
 		7CDF26E31D5CD64600666F69 /* SHA1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SHA1.swift; sourceTree = "<group>"; };
 		7CDF26E31D5CD64600666F69 /* SHA1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SHA1.swift; sourceTree = "<group>"; };
 		7CE0B9EE1D5BBAAD0070D292 /* SwifterTestsHMAC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsHMAC.swift; sourceTree = "<group>"; };
 		7CE0B9EE1D5BBAAD0070D292 /* SwifterTestsHMAC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsHMAC.swift; sourceTree = "<group>"; };
+		7CFEA3531D5DFDA9009A9BF7 /* SHA256.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SHA256.swift; sourceTree = "<group>"; };
 		98630C061A1C9A9D00478D08 /* login.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = login.html; sourceTree = "<group>"; };
 		98630C061A1C9A9D00478D08 /* login.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = login.html; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
 
 
@@ -570,6 +574,7 @@
 				7CDF26E21D5CD64600666F69 /* RSA.swift */,
 				7CDF26E21D5CD64600666F69 /* RSA.swift */,
 				7CDF26E31D5CD64600666F69 /* SHA1.swift */,
 				7CDF26E31D5CD64600666F69 /* SHA1.swift */,
 				7C00AABD1D5D374700EDA547 /* HEX.swift */,
 				7C00AABD1D5D374700EDA547 /* HEX.swift */,
+				7CFEA3531D5DFDA9009A9BF7 /* SHA256.swift */,
 			);
 			);
 			path = TLS;
 			path = TLS;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -883,6 +888,7 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				7CFEA3541D5DFDA9009A9BF7 /* SHA256.swift in Sources */,
 				7C31962B1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31962B1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C3196191CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7C3196191CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7CDF26E91D5CD64600666F69 /* BigNum.swift in Sources */,
 				7CDF26E91D5CD64600666F69 /* BigNum.swift in Sources */,
@@ -921,6 +927,7 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				7CFEA3551D5DFDA9009A9BF7 /* SHA256.swift in Sources */,
 				7C31962C1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31962C1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31961A1CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7C31961A1CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7CDF26EA1D5CD64600666F69 /* BigNum.swift in Sources */,
 				7CDF26EA1D5CD64600666F69 /* BigNum.swift in Sources */,
@@ -992,6 +999,7 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				7CFEA3561D5DFDA9009A9BF7 /* SHA256.swift in Sources */,
 				7C31962D1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31962D1CC2C68F00DF5406 /* Socket.swift in Sources */,
 				7C31961B1CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7C31961B1CC2C68F00DF5406 /* HttpResponse.swift in Sources */,
 				7CDF26EB1D5CD64600666F69 /* BigNum.swift in Sources */,
 				7CDF26EB1D5CD64600666F69 /* BigNum.swift in Sources */,

+ 9 - 0
XCode/SwifterTestsCommon/SwifterTestsStringExtensions.swift

@@ -38,6 +38,15 @@ class SwifterTestsStringExtensions: XCTestCase {
             "a377b0c42d685fdc396e29a9eda7101d900947ca")
             "a377b0c42d685fdc396e29a9eda7101d900947ca")
     }
     }
     
     
+    func testSHA256() {
+        XCTAssertEqual("".sha256(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
+        XCTAssertEqual("abc".sha256(), "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
+        XCTAssertEqual("hello".sha256(), "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824")
+        
+        XCTAssertEqual("hello".sha256(), "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824")
+        XCTAssertEqual("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ornare orci in metus egestas, sed ornare ante sagittis. Etiam pellentesque mauris ac tincidunt interdum. Mauris nec arcu non dolor venenatis placerat. Pellentesque condimentum feugiat lacus ac maximus. Fusce ut nibh lobortis, porta eros ut, rhoncus tellus. Suspendisse nec molestie quam. Nunc dapibus quam felis, viverra blandit nisi auctor quis. Fusce nisl ante, interdum sed congue ac, ullamcorper sit amet purus. Curabitur vestibulum commodo lobortis.".sha256(), "ea7da36063c95f557374fe98975f0b3cab900772c019747918232a0c0127e6db")
+    }
+    
     func testMD5() {
     func testMD5() {
         
         
         // Values from: https://tools.ietf.org/html/rfc1321
         // Values from: https://tools.ietf.org/html/rfc1321