0

How can I create a SHA256Digest, or any of the other digest types in CryptoKit, using a Data, or a hexadecimal String as the input?

In other words, how do I write the inverse of this function?

func toHex(hash: SHA256Digest) -> String {
    return String(hash.flatMap { byte in
        String(format:"%02x", byte)
    })
}

I can't find a constructor or another reasonable way to do it.

edit:

It can be done with unsafe pointers, but I still wish there were a safe way to do it.

extension Digest {
    
    func toHex() -> String {
        return String(self.flatMap { byte in
            String(format:"%02x", byte)
        })
    }
    
    static func fromHex(_ string : String) -> Self? {
        let data = UnsafeMutableRawBufferPointer.allocate(byteCount: Self.byteCount, alignment: 8)
        defer { data.deallocate() }
        let utf8 = string.utf8
        if utf8.count != 2 * Self.byteCount { return nil }
        func digit(_ i : Int) -> Int? {
            let byte = utf8[utf8.index(utf8.startIndex, offsetBy: i)]
            return Character(UnicodeScalar(byte)).hexDigitValue
        }
        for i in stride(from: 0, to: 2*Self.byteCount, by: 2) {
            guard
                let high = digit(i),
                let low = digit(i+1)
            else { return nil }
            data[i/2] = UInt8(high * 16 + low)
        }
        return data.bindMemory(to: Self.self)[0]
    }
}

Lawrence D'Anna
  • 2,998
  • 2
  • 22
  • 25
  • Have you tried `SHA256.hash(data: data)` – Ike Nov 19 '22 at 23:10
  • @ike the idea is to deserialize a hash value, not compute one. – Lawrence D'Anna Nov 21 '22 at 02:20
  • Ah, sorry. Bad reading on my part. It definitely seems like CryptoKit is really constrained and they only want us to use it in very specific ways. Out of curiosity, what's your use case? How will you use your deserialized digest? Why does it have to be in that `type`? – Ike Nov 21 '22 at 03:54

0 Answers0