为什么MD5哈希在Swift 3中如此困难?

为什么MD5哈希在Swift 3中如此困难?,swift,swift3,cryptography,md5,cryptoswift,Swift,Swift3,Cryptography,Md5,Cryptoswift,好的,所以你偶尔会遇到你在使用各种框架和库以及互联网上的其他东西之前已经解决的问题,你的问题得到了相对快速和简单的解决,你也了解了为什么你的问题最初是个问题 然而,有时你会遇到完全没有意义的问题,当解决方案有负面意义时,情况更糟 我的问题是,我想获取数据,并对其进行MD5哈希 我找到了各种各样的解决办法,但没有一种有效 真正让我烦恼的是,对于一项琐碎的任务,比如从任何东西中获取MD5哈希值,解决方案似乎有多么复杂,这是不必要的 我正试图通过Soffes使用Crypto和CommonCrypto框

好的,所以你偶尔会遇到你在使用各种框架和库以及互联网上的其他东西之前已经解决的问题,你的问题得到了相对快速和简单的解决,你也了解了为什么你的问题最初是个问题

然而,有时你会遇到完全没有意义的问题,当解决方案有负面意义时,情况更糟

我的问题是,我想获取
数据
,并对其进行MD5哈希

我找到了各种各样的解决办法,但没有一种有效

真正让我烦恼的是,对于一项琐碎的任务,比如从任何东西中获取MD5哈希值,解决方案似乎有多么复杂,这是不必要的

我正试图通过
Soffes
使用
Crypto
CommonCrypto
框架,它们看起来相当简单,对吗?对吧?

对!

但是为什么我仍然收到错误
致命错误:在展开可选值时意外发现nil

据我所知,
Soffes
Crypto
扩展中的
myData.md5
提供的数据似乎是“可选的”。但是为什么呢

我尝试执行的代码是:

print(" md5 result: " + String(data: myData.md5, encoding: .utf8)!)
其中
myData
中100%包含数据,因为在上述代码行之后,我将该数据发送到服务器,并且数据存在

除此之外,通过
print(String(myData.md5.count))
打印
myData.md5.count的计数非常有效

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

编辑:

我尝试过的

有效

MD5:在PHP脚本中调用字符串
test
可以得到
098F6BC4621D373CADE4E832627B4F6
Swift代码
“test”.md5()
也给了我
098F6BC4621D373CADE4E832627B4F6

这不起作用

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
print("md5 result: " + myData.md5().toHexString())
使用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”])

我使用一个名为“CryptoSwift”的库来创建散列,以及在发送/存储数据之前对数据进行加密。它很容易使用

可以在这里找到它,您甚至可以通过将
pod'CryptoSwift'
添加到您的pod文件中,将其与cocoapod一起安装

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

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


关于创建摘要的完整文档可以在这里找到:

多亏了Jacob King,我尝试了一个更简单的MD5框架,名为CryptoSwift

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

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

最初的问题是我为什么会出错

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

在代码行中说

print(" md5 result: " + String(data: myData.md5, encoding: .utf8)!)
所以答案是,我不应该尝试转换
MD5()
函数的16字节数据输出,而是调用
MD5()
的子函数
toHexString()

因此,正确的代码行应该如下所示:

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
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的小框架的一部分,可以在这里找到:

您的问题的简单答案是:

String(data: someData, encoding: .utf8)
如果
someData
不是正确的UTF8编码数据,则返回
nil
。如果您尝试像这样展开
nil

String(data: someDate, encoding: .utf8)!
你会得到:

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

所以在它的核心,它与哈希或加密无关

MD5(或任何哈希算法)的输入和输出都是二进制数据(而不是文本或字符串)。因此,MD5的输出不是UTF8编码的数据。因此,为什么上面的字符串初始值设定项总是失败

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


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

你说
myData
myData.md5
都是有效的,因为你在服务器上获取数据和print语句中的计数。仅基于此数据,并查看您的代码行,唯一突出的是用于将其转换为字符串的编码
utf8
。发现其中提到加密代码中使用的
CC_MD5
函数在Swift中不起作用。尽管这与您关于
myData.md5