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
-
1I beliebe CryptoSwift is the easy way :) – gutenmorgenuhu May 17 '15 at 06:05
-
2What problems do you have exactly with using CryptoSwift? – You don't necessarily need a 3rd party framework, you can also use Apple's CommonCrypto with thin Swift wrappers. Examples: http://stackoverflow.com/questions/25023376/how-can-i-hash-a-nsstring-to-sha512 (your own question :), http://stackoverflow.com/questions/6228092/how-can-i-compute-a-sha-2-ideally-sha-256-or-sha-512-hash-in-ios, http://stackoverflow.com/questions/25761344/how-to-crypt-string-to-sha1-with-swift, http://stackoverflow.com/questions/25388747/sha256-in-swift. – Martin R May 17 '15 at 07:40
-
@MartinR Thanks for sharing! This answer really helped! This is the article that answered my question (http://stackoverflow.com/questions/25761344/how-to-crypt-string-to-sha1-with-swift). All I had to do was change out SHA1 to SHA512. – TechnologyGuy May 17 '15 at 16:46
-
See [MD2, MD4, MD5, SHA1, SHA224, SHA256, SHA384, SHA512](http://stackoverflow.com/documentation/swift/7885/cryptographic-hashing/25614/md2-md4-md5-sha1-sha224-sha256-sha384-sha512-swift-3) in the Documentations section – zaph Mar 08 '17 at 13:07
-
It is best to avoid using CryptoSwift, amoung other things it is 500 to 1000 times slower than Common Crypto based implementations. Apple's Common Crypto is FIPS certified and as such has been well vetted, using CryptoSwift is taking a chance on correctness and security. – zaph Mar 09 '17 at 13:38
5 Answers
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: "")
}
}

- 2,930
- 1
- 20
- 25
-
Wondering how `self.data(using: .utf8)` could ever fail given that `self` must be a valid `String`. – zaph Mar 09 '17 at 13:44
-
Yes, you are right. Swift strings are always unicode strings, so `self.data(using: .utf8)` can never fail. I adapted my answer accordingly. – sundance Mar 10 '17 at 08:00
-
In a playground, what must I import to get access to `CC_` funcs? Foundation is not enough. – Jeff Jun 20 '17 at 17:30
-
It is not possible to use CommonCrypto directly in a playground because you cannot add a bridging header. But I read that it is possible by adding a framework with CommonCrypto in a bridging header: https://stackoverflow.com/a/42674951/5804550 – sundance Jun 21 '17 at 13:37
-
Hello @sundance, Thanks for your answer. I don't quite understand what "%02hhx" means in the String(format:) call; I was wondering if you could you please explain that briefly. Also, why would you need to iterate over the bytes and convert them to a string using String(format:) instead of just using a `base64EncodedString()`? Thanks in advance – ayushn21 Jul 23 '17 at 23:42
-
Typically, hashes are not encoded as base64 string but as hexadecimal string, so this is what my function returns. The digest consists of 512 bit, which is stored as 64 byte array and returned as 128 character hexadecimal string. The digest is here mapped to a string array, where each byte is formatted to a hexadecimal string. The format `%02hhx` comes from `printf` formatting in C++ (see http://www.cplusplus.com/reference/cstdio/printf/). `%` is the starting symbol, `02` enforces two output characters, `hh` defines the input as byte and `x` sets the output to hexadecimal. – sundance Aug 08 '17 at 14:43
-
@sundance please help here https://stackoverflow.com/questions/66757704/aes256-encryption-in-swift-string-not-matching – Amit Mar 23 '21 at 05:40
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.

- 56
- 3
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("")
}

- 11,183
- 13
- 64
- 87
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: "")
}
}

- 6,177
- 4
- 32
- 43
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
}

- 266
- 1
- 5
- 13