Browse Source

Fix SHA512 and SHA384 padding implementation (#321)

* Add prepare(_:allowance:) for custom allowance

- will be used for len = 128 where target is 112 (mod 128), thus
  allowance is 16 rather than default of 8.

* Fix padding of calculate64()

- set allowance to 16 bytes, and append 128-bit representation of length
  instead of 64-bit

* Add tests in SHA382 for length 112 bytes
Chris Amanse 9 years ago
parent
commit
bf92bd91d3

+ 6 - 2
Sources/CryptoSwift/HashProtocol.swift

@@ -16,6 +16,10 @@ internal protocol HashProtocol: class {
 extension HashProtocol {
     
     func prepare(_ len:Int) -> Array<UInt8> {
+        return self.prepare(len, allowance: len / 8)
+    }
+    
+    func prepare(_ len:Int, allowance: Int) -> Array<UInt8> {
         var tmpMessage = message
         
         // Step 1. Append Padding Bits
@@ -25,11 +29,11 @@ extension HashProtocol {
         var msgLength = tmpMessage.count
         var counter = 0
         
-        while msgLength % len != (len - 8) {
+        while msgLength % len != (len - allowance) {
             counter += 1
             msgLength += 1
         }
-
+        
         tmpMessage += Array<UInt8>(repeating: 0, count: counter)
         return tmpMessage
     }

+ 3 - 3
Sources/CryptoSwift/SHA2.swift

@@ -196,7 +196,7 @@ final class SHA2 : HashProtocol {
     }
     
     func calculate64() -> Array<UInt8> {
-        var tmpMessage = self.prepare(128)
+        var tmpMessage = self.prepare(128, allowance: 16)
         
         // hash values
         var hh = Array<UInt64>()
@@ -205,8 +205,8 @@ final class SHA2 : HashProtocol {
         }
 		
   
-        // append message length, in a 64-bit big-endian integer. So now the message length is a multiple of 512 bits.
-        tmpMessage += (message.count * 8).bytes(totalBytes: 64 / 8)
+        // append message length, in a 128-bit big-endian integer. So now the message length is a multiple of 1024 bits.
+        tmpMessage += (message.count * 8).bytes(totalBytes: 128 / 8)
         
         // Process the message in successive 1024-bit chunks:
         let chunkSizeBytes = 1024 / 8 // 128

+ 1 - 0
Tests/CryptoSwiftTests/HashTests.swift

@@ -80,6 +80,7 @@ final class HashTests: XCTestCase {
         
         XCTAssertEqual("The quick brown fox jumps over the lazy dog.".sha384(), "ed892481d8272ca6df370bf706e4d7bc1b5739fa2177aae6c50e946678718fc67a7af2819a021c2fc34e91bdb63409d7", "SHA384 calculation failed");
         XCTAssertEqual("".sha384(), "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", "SHA384 calculation failed")
+        XCTAssertEqual("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu".sha384(), "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039", "SHA384 calculation failed")
     }
 
     func testSHA512() {