【问题标题】:Unexpectedly nil hashing a password出乎意料地对密码进行哈希处理
【发布时间】:2018-08-03 20:45:14
【问题描述】:

我正在尝试使用 SHA256 方法对密码进行哈希处理:

class CryptoHandler {

    static func sha256(_ str: String) -> String? {
        let data = str.data(using: String.Encoding.utf8)
        let shaData = sha256(data!)
        let rc = String(data: shaData, encoding: String.Encoding.utf8) as String?
        return rc
    }

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


    static func getHashedPassword (pwd: String) -> String{
        let hash = sha256(pwd)
        return hash!
    }
}

当我尝试执行getHashedPassword ("0123456789") 时,return hash! 行中出现以下错误:

线程 1:致命错误:打开包装时意外发现 nil 可选值

为什么会这样?我该如何解决?

【问题讨论】:

  • 你怎么知道 shaData 是编码为字符串的数据?只有这样 shaData 才能用 .utf8 解码为字符串。您可能想要将您的 shaData 表示为字符串,但是有很多方法可以将 Data 表示为字符串。您可以将其十六进制编码为字符串,也可以对其进行 base64 编码,等等。最好将每个可选项强制放在那里,看看它在哪里崩溃,看看你的假设是什么不起作用。然后让 sha256 函数返回一个字符串,因为如果你不能依赖哈希函数来一直工作,那么它有什么价值?
  • let rc = String(data: shaData, encoding: String.Encoding.utf8) as String? 这是我收到 nil 值的地方。因此该转换无法正常工作。 @目的。我只需要获取字符串,然后减去前 16 个值,最后将其保存在数据库中。
  • 告诉我为什么你认为 shaData、底层位和字节是 .utf8-String 的表示?如果它只是随机数据怎么办,该函数怎么可能返回不为零?然后您可以查看如何将数据编码为十六进制表示。或者一个 base64——无论你想要字符串表示的样子。
  • 我已将那行更改为 let rc = shaData.base64EncodedString(options: []),现在我没有收到 nil 值。我收到一个 Base64Enconded 字符串。但是,仍然需要解码。
  • 你的意思是你想从base64-representation回到Data-representation?为此,您可以使用the way back

标签: swift sha256


【解决方案1】:

发生崩溃是因为您无法从加密的Data 创建String。您必须使用base64hex 表示。

这段代码创建了一个hex 编码的字符串,并且根本不使用可选项。

class CryptoHandler {

    static func sha256(_ str: String) -> String {
        let data = Data(str.utf8)
        let shaData = sha256(data)
        return shaData.hexString
    }

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

    static func getHashedPassword (pwd: String) -> String{
        let hash = sha256(pwd)
        return hash
    }
}

extension Data {
    var hexString : String {
        return self.map{ String(format:"%02x", $0) }.joined()
    }
}

CryptoHandler.getHashedPassword(pwd:"0123456789")

【讨论】:

  • 不必编码。我只需要它来创建一个字符串的 sha256。与此页面相同。 link
  • 确实必须被编码。在链接的站点上,数据是十六进制字符串编码的。我将代码添加为Data extension
  • 完美。这就是我一直在寻找的。非常感谢!
【解决方案2】:
let rc = String(data: shaData, encoding: String.Encoding.utf8) as String?

将返回 nil 值,并且您将强制在 getHashedPassword 方法中使用 hash 常量末尾的 return hash! 感叹号编译一个值。

您可以通过接受可选值来修改getHashedPassword 方法来修复它

例如:

static func getHashedPassword (pwd: String) -> String? 
{
   let hash = sha256(pwd)
   return hash 
} 

【讨论】:

  • 我该如何解决?
  • 在 getHashedPassword 方法中提供可选的返回类型。例如:静态函数 getHashedPassword(密码:字符串)-> 字符串? { 让哈希 = sha256(pwd) 返回哈希 }
  • 我认为您可能没有使用散列函数作为密码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-06
  • 2010-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多