Reputation: 141
I am building a social media application and I would like some help encoding a password string to SHA512 in Swift. I found the CryptoSwift library on GitHub but I am having a hard time loading it into my Swift project and linking it to my project files. Does anyone know how to accomplish this relatively easily? Thanks in advance, Kyle
Upvotes: 7
Views: 9861
Reputation: 276
Swift 5
for string this method works for me
func SHA512(string: String) -> String {
let length = Int(CC_SHA512_DIGEST_LENGTH)
let messageData = string.data(using:.utf8)!
var digestData = Data(count: length)
_ = digestData.withUnsafeMutableBytes { digestBytes -> UInt8 in
messageData.withUnsafeBytes { messageBytes -> UInt8 in
if let messageBytesBaseAddress = messageBytes.baseAddress, let digestBytesBlindMemory = digestBytes.bindMemory(to: UInt8.self).baseAddress {
let messageLength = CC_LONG(messageData.count)
CC_SHA512(messageBytesBaseAddress, messageLength, digestBytesBlindMemory)
}
return 0
}
}
return digestData.map { String(format: "%02hhx", $0) }.joined()
}
if you only need Data remove .map { String(format: "%02hhx", $0):
func SHA512(string: String) -> Data {
let length = Int(CC_SHA512_DIGEST_LENGTH)
let messageData = string.data(using:.utf8)!
var digestData = Data(count: length)
_ = digestData.withUnsafeMutableBytes { digestBytes -> UInt8 in
messageData.withUnsafeBytes { messageBytes -> UInt8 in
if let messageBytesBaseAddress = messageBytes.baseAddress, let digestBytesBlindMemory = digestBytes.bindMemory(to: UInt8.self).baseAddress {
let messageLength = CC_LONG(messageData.count)
CC_SHA512(messageBytesBaseAddress, messageLength, digestBytesBlindMemory)
}
return 0
}
}
return digestData
}
Upvotes: 0
Reputation: 6335
You need to import C library CommonCrypto. You cannot just import CommonCrypto to your swift file since it's not a standalone module.
If you have a bridging header file, you are lucky! Just add this to that file
#import <CommonCrypto/CommonCrypto.h>
There are some articles about different ways to do that.
Then you can use this piece of code to have sha512 available for any string of your choice.
swift 5
extension String {
public var sha512: String {
let data = self.data(using: .utf8) ?? Data()
var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA512($0.baseAddress, CC_LONG(data.count), &digest)
}
return digest.map({ String(format: "%02hhx", $0) }).joined(separator: "")
}
}
Upvotes: 2
Reputation: 66
I find all of the answer ok, but if we should have a true universal solution I think we need to step it up a level.
CC_LONG
is just an UInt32
and will not support really large data structures.
This is my solution in Swift 3:
First we create a foundation:
struct Sha512 {
let context = UnsafeMutablePointer<CC_SHA512_CTX>.allocate(capacity:1)
init() {
CC_SHA512_Init(context)
}
func update(data: Data) {
data.withUnsafeBytes { (bytes: UnsafePointer<Int8>) -> Void in
let end = bytes.advanced(by: data.count)
for f in sequence(first: bytes, next: { $0.advanced(by: Int(CC_LONG.max)) }).prefix(while: { (current) -> Bool in current < end}) {
_ = CC_SHA512_Update(context, f, CC_LONG(Swift.min(f.distance(to: end), Int(CC_LONG.max))))
}
}
}
func final() -> Data {
var digest = [UInt8](repeating: 0, count:Int(CC_SHA512_DIGEST_LENGTH))
CC_SHA512_Final(&digest, context)
return Data(bytes: digest)
}
}
For convenience we do an extension for Data
:
extension Data {
func sha512() -> Data {
let s = Sha512()
s.update(data: self)
return s.final()
}
}
And last an extension for String
:
extension String {
func sha512() -> Data {
return self.data(using: .utf8)!.sha512()
}
}
This solution can be used for Sha256, MD5 etc. to get a good true universal solutions with Apple's CommonCrypto.
Upvotes: 3
Reputation: 3020
Solution for Swift 3:
extension String {
func sha512() -> String {
let data = self.data(using: .utf8)!
var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
data.withUnsafeBytes({
_ = CC_SHA512($0, CC_LONG(data.count), &digest)
})
return digest.map({ String(format: "%02hhx", $0) }).joined(separator: "")
}
}
Upvotes: 8
Reputation: 11773
Swift 3
func sha512() -> String {
let data = self.data(using: .utf8)!
var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
data.withUnsafeBytes({
_ = CC_SHA512($0, CC_LONG(data.count), &digest)
})
return digest.map({ String(format: "%02hhx", $0) }).joined(separator: "")
}
Swift 2.3
func sha512() -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
var digest = [UInt8](count:Int(CC_SHA512_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA512(data.bytes, CC_LONG(data.length), &digest)
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joinWithSeparator("")
}
Upvotes: 2