2

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

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

我的问题是我想从中Data提取并制作一个 MD5 散列。

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

实际上真正困扰我的是解决方案对于一项琐碎的任务似乎是多么不必要的复杂,因为从任何东西中获取 MD5 哈希。

我正在尝试使用CryptoandCommonCrypto框架Soffes,它们看起来相当容易,对吧?正确的?

是的!

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

据我了解,在 bymyData.md5的扩展中提供Crypto的数据Soffes似乎是“可选的”。但为什么?

我试图执行的代码是:

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

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

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

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

编辑:

我试过的

这样可行

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

那行不通

UInt8字节数组 from转换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"])

4

3 回答 3

1

您的问题的简单答案是:

String(data: someData, encoding: .utf8)

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

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

你得到:

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

所以在它的核心,它与散列或加密无关。

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

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

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

于 2016-11-29T18:01:47.003 回答
0

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

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

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

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

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

于 2016-11-29T07:11:37.463 回答
0

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

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

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

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

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

在代码行说

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

所以答案是我不应该尝试转换函数的 16 字节数据输出MD5(),而是调用被调用的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

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

于 2016-11-29T15:40:34.773 回答