SHA256 in swift

匿名 (未验证) 提交于 2019-12-03 02:11:02

问题:

I want to use sha256 in my project, but I had some troubles rewriting objC code to swift code. Help me please. I used this answer: How can I compute a SHA-2 (ideally SHA 256 or SHA 512) hash in iOS?

Here's my code

var hash : [CUnsignedChar] CC_SHA256(data.bytes, data.length, hash) var res : NSData = NSData.dataWithBytes(hash, length: CC_SHA256_DIGEST_LENGTH) 

it gives me error everything because swift cannot convert Int to CC_LONG, for example.

回答1:

You have to convert explicitly between Int and CC_LONG, because Swift does not do implicit conversions, as in (Objective-)C.

You also have to define hash as an array of the required size.

func sha256(data : NSData) -> NSData {     var hash = [UInt8](count: Int(CC_SHA256_DIGEST_LENGTH), repeatedValue: 0)     CC_SHA256(data.bytes, CC_LONG(data.length), &hash)     let res = NSData(bytes: hash, length: Int(CC_SHA256_DIGEST_LENGTH))     return res } 

Alternatively, you can use NSMutableData to allocate the needed buffer:

func sha256(data : NSData) -> NSData {     let res = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))     CC_SHA256(data.bytes, CC_LONG(data.length), UnsafeMutablePointer(res.mutableBytes))     return res } 

Update for Swift 3:

func sha256(data : Data) -> Data {     var hash = [UInt8](repeating: 0,  count: Int(CC_SHA256_DIGEST_LENGTH))     data.withUnsafeBytes {         _ = CC_SHA256($0, CC_LONG(data.count), &hash)     }     return Data(bytes: hash) } 


回答2:

The top answer didn't work for me. I found something in the web and changed it a bit and now it works :D. It's for Swift 3 and 4.

Put this extension somewhere in your project and use it on a string like this: mystring.sha256()

extension String {      func sha256() -> String{         if let stringData = self.data(using: String.Encoding.utf8) {             return hexStringFromData(input: digest(input: stringData as NSData))         }         return ""     }      private func digest(input : NSData) -> NSData {         let digestLength = Int(CC_SHA256_DIGEST_LENGTH)         var hash = [UInt8](repeating: 0, count: digestLength)         CC_SHA256(input.bytes, UInt32(input.length), &hash)         return NSData(bytes: hash, length: digestLength)     }      private  func hexStringFromData(input: NSData) -> String {         var bytes = [UInt8](repeating: 0, count: input.length)         input.getBytes(&bytes, length: input.length)          var hexString = ""         for byte in bytes {             hexString += String(format:"%02x", UInt8(byte))         }          return hexString     }  } 

By the way you need a Bridging Header that imports CommonCrypto. If you don't have one follow these steps:

  1. Create new File -> Header File -> Save as BridgingHeader
  2. In Build Settings -> Objective-C Bridging Header -> add ProjectName/BridgingHeader.h
  3. Put #import <CommonCrypto/CommonHMAC.h> in your Header File


回答3:

Functions giving the SHA from NSData & String (Swift 3):

func sha256(_ data: Data) -> Data? {     guard let res = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH)) else { return nil }     CC_SHA256((data as NSData).bytes, CC_LONG(data.count), res.mutableBytes.assumingMemoryBound(to: UInt8.self))     return res as Data }  func sha256(_ str: String) -> String? {     guard         let data = str.data(using: String.Encoding.utf8),         let shaData = sha256(data)         else { return nil }     let rc = shaData.base64EncodedString(options: [])     return rc } 

Include in your bridging header:

#import "CommonCrypto/CommonCrypto.h" 


回答4:

Here's my simple 3-line Swift 4 function for this using the Security Transforms API, which is part of Foundation on macOS. (Unfortunately iOS programmers cannot use this technique.)

import Foundation  extension Data {     public func sha256Hash() -> Data {         let transform = SecDigestTransformCreate(kSecDigestSHA2, 256, nil)         SecTransformSetAttribute(transform, kSecTransformInputAttributeName, self as CFTypeRef, nil)         return SecTransformExecute(transform, nil) as! Data     } } 


回答5:

Here's a method that uses the CoreFoundation Security Transforms API, so you don't even need to link to CommonCrypto. For some reason in 10.10/Xcode 7 linking to CommmonCrypto with Swift is drama so I used this instead.

This method reads from an NSInputStream, which you can either get from a file, or you can make one that reads an NSData, or you can make bound reader/writer streams for a buffered process.

// digestType is from SecDigestTransform and would be kSecDigestSHA2, etc  func digestForStream(stream : NSInputStream,     digestType type : CFStringRef, length : Int) throws -> NSData {      let transform = SecTransformCreateGroupTransform().takeRetainedValue()      let readXform = SecTransformCreateReadTransformWithReadStream(stream as CFReadStreamRef).takeRetainedValue()      var error : Unmanaged<CFErrorRef>? = nil      let digestXform : SecTransformRef = try {         let d = SecDigestTransformCreate(type, length, &error)         if d == nil {             throw error!.takeUnretainedValue()         } else {             return d.takeRetainedValue()         }     }()      SecTransformConnectTransforms(readXform, kSecTransformOutputAttributeName,         digestXform, kSecTransformInputAttributeName,         transform, &error)     if let e = error { throw e.takeUnretainedValue() }      if let output = SecTransformExecute(transform, &error) as? NSData {         return output     } else {         throw error!.takeUnretainedValue()     } } 


文章来源: SHA256 in swift
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!