swift sha256

swift - SHA256 en veloz



md5 swift 4 (6)

Quiero usar sha256 en mi proyecto, pero tuve algunos problemas para reescribir el código ObjC para convertirlo en código. Ayudame por favor. Utilicé esta respuesta: ¿Cómo puedo calcular un hash SHA-2 (idealmente SHA 256 o SHA 512) en iOS?

Aquí está mi código

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

me da error todo porque swift no puede convertir Int a CC_LONG , por ejemplo.


Aquí está mi función simple de 3 líneas Swift 4 para esto usando Security Transforms API, que es parte de Foundation en macOS. (Desafortunadamente los programadores de iOS no pueden usar esta técnica).

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 } }


Aquí hay un método que usa la API de Transformaciones de seguridad de CoreFoundation, por lo que ni siquiera necesita vincularse a CommonCrypto. Por alguna razón, en 10.10 / Xcode 7 vincular a CommmonCrypto con Swift es drama, así que usé esto en su lugar.

Este método se lee desde un NSInputStream , que puede obtener de un archivo, o puede hacer uno que lea un NSData , o puede hacer flujos enlazados de lectura / NSData para un proceso en búfer.

// 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() } }


Funciones que le dan al SHA de 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 }

Incluir en su encabezado de puente:

#import "CommonCrypto/CommonCrypto.h"


La respuesta principal no funcionó para mí. Encontré algo en la web y lo cambié un poco y ahora funciona: D. Es para Swift 3 y 4.

Coloque esta extensión en algún lugar de su proyecto y utilícela en una cadena como esta: 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 } }

Por cierto, necesita un encabezado de puente que importe CommonCrypto. Si no tiene uno, siga estos pasos:

  1. Crear nuevo archivo -> Archivo de encabezado -> Guardar como BridgingHeader
  2. En Configuración de compilación -> Encabezado de puente de Objective-C -> agregar ProjectName/BridgingHeader.h
  3. Coloque #import <CommonCrypto/CommonHMAC.h> en su archivo de encabezado

Prefiero usar:

extension String { var sha256:String? { guard let stringData = self.data(using: String.Encoding.utf8) else { return nil } return digest(input: stringData as NSData).base64EncodedString(options: []) } 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) } }

La cadena hasded es codificada en base64.


CC_LONG convertir explícitamente entre Int y CC_LONG , porque Swift no realiza conversiones implícitas, como en (Objetivo-) C.

También debe definir hash como una matriz del tamaño requerido.

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 }

Alternativamente, puede usar NSMutableData para asignar el búfer necesario:

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 }

Actualización para 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) }