我正在开发一款社交媒体应用程序,希望能够在Swift中将密码字符串编码为SHA512。我在GitHub上找到了CryptoSwift库,但是我很难将其加载到我的Swift项目中,并将其链接到我的项目文件。是否有人知道如何相对容易地完成这个任务? 提前感谢, Kyle
我正在开发一款社交媒体应用程序,希望能够在Swift中将密码字符串编码为SHA512。我在GitHub上找到了CryptoSwift库,但是我很难将其加载到我的Swift项目中,并将其链接到我的项目文件。是否有人知道如何相对容易地完成这个任务? 提前感谢, Kyle
针对 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: "")
}
}
self.data(using: .utf8)
永远不会失败。我已经相应地修改了我的答案。 - sundanceCC_
函数?Foundation 不够用。 - Jeffbase64EncodedString()
呢?提前致谢 - ayushn21我认为所有的答案都可以,但如果我们需要一个真正通用的解决方案,我认为我们需要提高一个级别。
CC_LONG
只是一个UInt32
,不支持非常大的数据结构。
这是我在Swift 3中的解决方案:
首先,我们创建一个基础:
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)
}
}
为了方便,我们对 Data
做了扩展:
extension Data {
func sha512() -> Data {
let s = Sha512()
s.update(data: self)
return s.final()
}
}
最后是一个针对 String
的扩展:
extension String {
func sha512() -> Data {
return self.data(using: .utf8)!.sha512()
}
}
这个解决方案可以用于Sha256、MD5等技术,通过使用苹果的CommonCrypto可以得到良好的通用解决方案。
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("")
}
您需要导入C库CommonCrypto。由于它不是独立模块,因此不能只将CommonCrypto导入到您的swift文件中。
如果您有一个桥接头文件,那就太幸运了!只需将以下内容添加到该文件中:
#import <CommonCrypto/CommonCrypto.h>
然后,您可以使用此代码片段使sha512适用于您选择的任何字符串。
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: "")
}
}
Swift 5
对于字符串,这个方法对我来说很有效。
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()
}
如果您只需要数据,请删除.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
}