-1

I am trying to convert a string to SHA512 MD5 hash with Bas64 encoding. I tried below code for the same but it is returning wrong string.

func sha512Base64(string: String) -> String {
        let digest = NSMutableData(length: Int(CC_SHA512_DIGEST_LENGTH))!
        if let data = string.data(using: String.Encoding.utf8) {
    
            let value =  data as NSData
            let uint8Pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: digest.length)
            CC_SHA512(value.bytes, CC_LONG(data.count), uint8Pointer)
    
        }
        return digest.base64EncodedString(options: NSData.Base64EncodingOptions([]))
    }

Please suggest me the exact solution or the defects in above method.

Thanks in advance.

Sanat Pandey
  • 4,081
  • 17
  • 75
  • 132

2 Answers2

2

I rewrote your code a little. Try this

func sha512Base64(string: String) -> String? {
    guard let data = string.data(using: String.Encoding.utf8) else {
        return nil
    }

    var digest = Data(count: Int(CC_SHA512_DIGEST_LENGTH))
    _ = digest.withUnsafeMutableBytes { digestBytes -> UInt8 in
        data.withUnsafeBytes { messageBytes -> UInt8 in
            if let mb = messageBytes.baseAddress, let db = digestBytes.bindMemory(to: UInt8.self).baseAddress {
                let length = CC_LONG(data.count)
                CC_SHA512(mb, length, db)
            }
            return 0
        }
    }
    return digest.base64EncodedString()
}

I like this answer https://stackoverflow.com/a/52120827

with his approach you can use it like

"123".hashed(.sha512, output: .base64)
Oleg B
  • 176
  • 7
1

In your question title you mention SHA512 and MD5 these are two different things. Since your code appears to try to calculate SHA512, I am going to assume that is what you want.

When you're calling into C functions you can use appropriately typed Swift arrays to save you a lot of headaches. Leveraging this you can rewrite you code as follows:

func sha512Base64(string: String) -> String {
    guard let data = string.data(using: .utf8) else {
        fatalError("Failed to convert string to data")
    }
    var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
    let dataArray = Array(data)
    CC_SHA512(dataArray, CC_LONG(data.count), &digest)
    return Data(digest).base64EncodedString()
}

I should mention, if you can use Apple's CryptoKit, it's much easier:

import CryptoKit

func sha512Base64(string: String) -> String {
    guard let data = string.data(using: .utf8) else {
        fatalError("Failed to convert string to data")
    }
    let hash = SHA512.hash(data: data)
    return Data(hash).base64EncodedString()
}

CryptoKit is supported from iOS 13.0 onwards.

idz
  • 12,825
  • 1
  • 29
  • 40