0

I am a newbie to encryption and hashing algorithms. I need to Hash a string with a secret key using the SHA-256 algorithm. I tried multiple links from stack overflow and some other tutorials as well, Using those links, the output I received in iOS is different from the output I am getting in Android. I have used the same string and secret key on both platforms.

Android Code Snippet -

MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(secret_key);
byte[] channelKeyLong = digest.digest(message.getBytes("utf-8"));

INPUT -

secret_key = "35285324354d562c245b031232115124372e5242394f51301f62224e1e432910"
message = "Guest"

OUTPUT = "99D71664BD5A35E0185C020BACB709DEB24A81555E275CA9328F8CB4E6F186C3"

iOS Code snipet -

extension String {
  func generateSHA256(key: String) -> String {
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
        CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), key, key.count, self, self.count, &digest)
        let data = Data(bytes: digest)
        return data.map { String(format: "%02hhx", $0) }.joined()
    }
}

INPUT -

secret_key = "35285324354d562c245b031232115124372e5242394f51301f62224e1e432910"
message = "Guest"

IMPLEMENTATION -> OUTPUT = message.generateSHA256(secret_key)

`OUTPUT = "944a37b9768970c5da4f35295008470603391223a05d2b17eed668f1678d447c"'

Please suggest any other method which I can implement in iOS to produces the same output as received in android.

Piyush Bansal
  • 1,635
  • 4
  • 16
  • 39
Tarun9573
  • 1
  • 3
  • try to use this library: https://github.com/krzyzanowskim/CryptoSwift – Moayad Al kouz Sep 20 '18 at 09:36
  • I have also gone through CryptoSwift Library, but can't find any way to replicate the output of android. If you can provide any code snipet, it will be helpful. – Tarun9573 Sep 20 '18 at 09:49
  • 1
    I think HMAC is different from a hash function. Have you tried using `CC_SHA256_Init()`, `CC_SHA256_Update()`, and `CC_SHA256_Final()`? – Mats Sep 20 '18 at 11:36
  • Hi Mats, can you provide some sample code which can result in same output. That will be really helpfull. Thanks – Tarun9573 Sep 21 '18 at 08:48
  • I also tried the CC_SHA256 functions 'CC_SHA256_Init(), CC_SHA256_Update(), and CC_SHA256_Final()' but no success. – Tarun9573 Sep 21 '18 at 10:47

3 Answers3

3

Your Android code and your iOS code is not equivalent.

Your Android code simply computes the SHA256 digest of your key value concatenation with your message.

You are first calling update with your key and then calling digest with your messsge. The documentation states:

Performs a final update on the digest using the specified array of bytes, then completes the digest computation. That is, this method first calls update(input), passing the input array to the update method, then calls digest().

Your iOS code, on the other hand, is computing a HMAC of your message using the supplied key. This is not the same thing.

You need to compute the SHA256 in the same way that you do on Android;

  • Use CC_SHA256_Init
  • call CC_SHA256_Update with your key and message
  • Call CC_SHA256_Final to get the hash

Probably easier in Swift is to use SwiftyRSA. All you need to do then is create an instance of ClearMessage initialised with your concatenation key and message and then call the digest function on it.

David Rönnqvist
  • 56,267
  • 18
  • 167
  • 205
Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • Hi Paulw11, Can you provide some code snippet for the same. It will really help a lot. Thanks in advance. – Tarun9573 Sep 21 '18 at 06:53
1

Don't know about how the android doing SHA-256 but for the iOS I can say, the code you are doing is perfect and the results is right. You should update your question to: "How can I get "SHA-256 for Android same as the iOS"

You can check for SHA-256 HashMap online here

Just enter the input and secret key and select SHA-256 from list.

secret_key = "35285324354d562c245b031232115124372e5242394f51301f62224e1e432910"
message = "Guest"

You will see the output, which is same as the one you getting from the iOS Code in your question.

944a37b9768970c5da4f35295008470603391223a05d2b17eed668f1678d447c

Hope it helps!

Bhavin Kansagara
  • 2,866
  • 1
  • 16
  • 20
  • But my dear friend, the android result is working fine with an iOT device. I need to match my output to get iOS app work with the device :( – Tarun9573 Sep 20 '18 at 11:10
0

Try this !

    private func hash(_ key: String, message: String) -> String {
    var container = Container32.initialize()
    var context = CC_SHA256_CTX()
    
    CC_SHA256_Init(&context)

    let keyBytes = Data(base64Encoded: key)!
    
    _ = keyBytes.withUnsafeBytes { buffer in
        CC_SHA256_Update(&context, buffer.baseAddress, CC_LONG(buffer.count))
    }
    
    CC_SHA256_Update(&context, message, CC_LONG(message.lengthOfBytes(using: .utf8)))
    
    Container32.withBaseAddress(&container) { pointer in
        CC_SHA256_Final(pointer, &context)
    }
    return Container32.string(container);
}



// MARK: - Container32 -

private enum Container32 {
    
    static func initialize() -> Allocation {
        return (
            0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0
        )
    }
    
    static func withBaseAddress(_ allocation: inout Allocation, body: (UnsafeMutablePointer<UInt8>) -> Void) {
        withUnsafeMutableBytes(of: &allocation) { buffer in
            let baseAddress = buffer.baseAddress!.bindMemory(to: UInt8.self, capacity: 32)
            body(baseAddress)
        }
    }
    
    static func string(_ allocation: Allocation) -> String {
        String(format: "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
               allocation.0,  allocation.1,  allocation.2,  allocation.3,
               allocation.4,  allocation.5,  allocation.6,  allocation.7,
               allocation.8,  allocation.9,  allocation.10, allocation.11,
               allocation.12, allocation.13, allocation.14, allocation.15,
               
               allocation.16, allocation.17, allocation.18, allocation.19,
               allocation.20, allocation.21, allocation.22, allocation.23,
               allocation.24, allocation.25, allocation.26, allocation.27,
               allocation.28, allocation.29, allocation.30, allocation.31
        )
    }
    
}

// MARK: - Allocation -

    extension Container32 {
    typealias Allocation = (
        UInt8, UInt8, UInt8, UInt8,
        UInt8, UInt8, UInt8, UInt8,
        UInt8, UInt8, UInt8, UInt8,
        UInt8, UInt8, UInt8, UInt8,
        UInt8, UInt8, UInt8, UInt8,
        UInt8, UInt8, UInt8, UInt8,
        UInt8, UInt8, UInt8, UInt8,
        UInt8, UInt8, UInt8, UInt8
    )
}

Do not forget to add the "import CommonCrypto"

OverD
  • 2,612
  • 2
  • 14
  • 29
  • Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, **can you [edit] your answer to include an explanation of what you're doing** and why you believe it is the best approach? – Jeremy Caney Feb 27 '23 at 00:17