【问题标题】:Why is MD5 hashing so hard and in Swift 3?为什么 MD5 散列在 Swift 3 中如此困难?
【发布时间】:2016-11-29 06:49:50
【问题描述】:

好的,所以你时不时会遇到在使用各种框架和库之前解决的问题,以及在互联网上找不到的东西,你的问题得到了相对快速和容易的解决,你也了解了为什么你的问题是一个问题首先。

但是,有时您会遇到绝对 0 意义的问题,当解决方案具有负面意义时,情况会更糟。

我的问题是我想使用 Data 并从中生成一个 MD5 哈希。

我找到了各种解决方案,但没有一个有效。

真正让我烦恼的是,对于从任何事物中获取 MD5 哈希值这样的微不足道的任务来说,解决方案似乎是多么不必要地复杂。

我正在尝试使用SoffesCryptoCommonCrypto 框架,它们看起来相当简单,对吧?对吧?

是的!

但是为什么我仍然收到错误fatal error: unexpectedly found nil while unwrapping an Optional value

据我了解,myData.md5Crypto 的扩展中提供的数据Soffes 似乎是“可选的”。但是为什么呢?

我要执行的代码是:

print(" md5 result: " + String(data: myData.md5, encoding: .utf8)!)

其中myData 100% 有数据,因为在上面的代码行之后,我将该数据发送到服务器,并且数据存在。

最重要的是,通过print(String(myData.md5.count)) 打印myData.md5.count 的计数非常有效。

所以我的问题基本上是:我如何对数据进行 MD5 散列并将其打印为字符串?

编辑:

我的尝试

行得通

MD5:在 PHP 脚本中输入字符串 test 给我 098f6bcd4621d373cade4e832627b4f6 Swift 代码"test".md5() 也给了我098f6bcd4621d373cade4e832627b4f6

那行不通

UInt8 字节数组从Data.md5() 转换为代表正确MD5 值的字符串。

我做过的不同测试如下:

var hash = ""
for byte in myData.data.md5() {
    hash +=  String(format: "%02x", byte)
}
print("loop = " + hash) //test 1

print("myData.md5().toHexString() = " +  myData.md5().toHexString()) //test 2

print("CryptoSwift.Digest.md5([UInt8](myData)) = " + CryptoSwift.Digest.md5([UInt8](myData)).toHexString()) //test 3

所有三个 500 字节测试数据的测试都给了我 MD5 值56f6955d148ad6b6abbc9088b4ae334d 而我的 PHP 脚本给了我6081d190b3ec6de47a74d34f6316ac6b

测试样本(64 字节): 原始数据:

FFD8FFE0 00104A46 49460001 01010048 00480000 FFE13572 45786966 00004D4D
002A0000 0008000B 01060003 00000001 00020000 010F0002 00000012 00000092

测试 1、2 和 3 MD5:7f0a012239d9fde5a46071640d2d8c83

PHP MD5:06eb0c71d8839a4ac91ee42c129b8ba3

PHP 代码:echo md5($_FILES["file"]["tmp_name"])

【问题讨论】:

  • 您说myDatamyData.md5 在服务器上获取数据和打印语句中的计数时都有效。仅基于此数据,并查看您的代码行,唯一突出的是您用于将其转换为字符串的编码 utf8
  • 发现 this SO question 提到 Crypto 代码中使用的 CC_MD5 函数在 Swift 中不起作用。尽管这与您关于 myData.md5 不为空的观点相矛盾。
  • 是的,这很奇怪。我现在正在尝试 CryptoSwift,我得到了同样的错误。
  • 当您说print(String(myData.md5.count)) 完美运行时,您的意思是它实际上显示了正确的计数吗?你是如何验证的。
  • 就是这样,我得到了16 的计数,但是我怎么知道这 16 个字节是什么?在打印之前我无法验证,对吧?

标签: swift swift3 cryptography md5 cryptoswift


【解决方案1】:

您的问题的简单答案是:

String(data: someData, encoding: .utf8)

如果someData 不是正确的UTF8 编码数据,则返回nil。如果您尝试像这样解开nil

String(data: someDate, encoding: .utf8)!

你得到:

致命错误:在展开可选值时意外发现 nil

因此,它的核心与散列或加密无关。

MD5(或任何散列算法)的输入和输出都是二进制数据(而不是文本或字符串)。所以 MD5 的输出不是 UTF8 编码的数据。这就是为什么上面的 String 初始化程序总是失败的原因。

如果您想在控制台中显示二进制数据,您需要将其转换为可读的表示形式。最常见的是十六进制数字或 Base 64 编码。

注意:一些加密库允许您将字符串输入到它们的哈希函数中。他们将使用某种字符编码默默地将字符串转换为二进制表示。如果编码不匹配,则哈希值在系统和编程语言之间不匹配。所以你最好试着理解他们为什么真的在后台做。

【讨论】:

    【解决方案2】:

    我使用一个名为“CryptoSwift”的库来创建哈希,以及在发送/存储数据之前对其进行加密。它非常易于使用。

    可以在此处找到 https://github.com/krzyzanowskim/CryptoSwift,您甚至可以通过将 pod 'CryptoSwift' 添加到您的 podfile 来使用 CocoaPods 安装它。

    安装后,散列Data 对象就像调用Data.md5() 一样简单!它真的很容易。它还支持SHA等其他哈希算法。

    然后您可以打印 MD5 对象,CryptoSwift 会为您将其转换为字符串。

    关于创建摘要的完整文档可以在这里找到:https://github.com/krzyzanowskim/CryptoSwift#calculate-digest

    【讨论】:

    • 我现在正在尝试 CryptoSwift,我得到了同样的错误。
    • 您尝试散列的数据来自哪里?如果它是一个编码字符串,是否可以尝试直接对该字符串进行散列?
    • 数据来自PHAssetResourceManager.requestData(),存储在外部变量中。所以我的应用程序从资产中提取数据,将该数据存储在位于外部requestDatamyData 中,然后尝试MD5 myData
    • 你可以尝试对一些数据进行 MD5,大约 512 字节,伙计?或者,在这里查看我的代码:github.com/aidv/AssetManager/blob/master/AssetManager.swift
    • 查看第 110 行。它什么也不返回,也不会导致任何问题,但是当尝试打印该值时,我在 Crypto 和 CryptoSwift 中都得到了错误。
    【解决方案3】:

    感谢 Jacob King,我尝试了一个更简单的 MD5 框架,称为 CryptoSwift。

    用户 Codo 启发我深入研究我的 PHP 脚本,因为他建议我实际上不是在对数据内容进行哈希处理,而是对文件名进行哈希处理,这是正确的。

    然而,最初的问题不是关于使用哪个框架或建议为什么我的应用程序和我的 PHP 脚本返回不同的 MD5 值。

    问题最初是关于我为什么会收到错误

    致命错误:在展开可选值时意外发现 nil

    在代码行说

    print(" md5 result: " + String(data: myData.md5, encoding: .utf8)!)
    

    所以答案是我不应该尝试转换MD5()函数的16字节数据输出,而是调用MD5()的子函数toHexString()

    所以正确的代码行应该如下所示:

    print("md5 result: " + myData.md5().toHexString())
    

    奖金

    我的 PHP 脚本现在包含以下代码:

    move_uploaded_file($_FILES["file"]["tmp_name"], $target_dir); //save data to disk
    $md5_of_data = md5_file ($target_dir); //get MD5 of saved data
    

    奖金-奖金 问题和解决方案是我正在开发的一个名为 AssetManager 的小型框架的一部分,可以在这里找到:https://github.com/aidv/AssetManager

    【讨论】:

      猜你喜欢
      • 2019-01-09
      • 2010-11-21
      • 2018-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      相关资源
      最近更新 更多