我有一个应用程序,在商定的密钥和IV上使用CBC方法在TripleDES加密中的供应商应用程序之间交换数据。我的应用程序是一个VB.NET应用程序,而供应商的应用程序是一个PHP网页。奇怪的是,我似乎无法匹配供应商应用程序的输出。
密钥和初始向量以明文形式提供给我们两个人。有趣的是,在供应商的应用程序中,他们不会将密钥和IV哈希或转换为256位密钥和128位IV。他们只是在PHP中使用 mcrypt 插件在代码中使用明文格式。
$key = 'plaintextkey';
$iv = 'plaintextIV'
$enc = mcrypt_encrypt(MCRYPT_3DES, $key, $string, MCRYPT_MODE_CBC, $iv)
它产生了一个有趣的文字,例如:
û!‰+«°z0"üÐÑn
我的问题是:
答案 0 :(得分:2)
如果明文用作参数,PHP如何实现/将其转换为256位字符?
使用三个DES和三次(不同)DES密钥对DES的应用三次。一个DES密钥长56位,带有奇偶校验位64位。因此,3DES密钥应该由三个不同的 DES密钥组成,这些密钥应该产生一个192位密钥。
密钥应该具有高熵,因此有必要暴力破解相当大的密钥空间。如果密钥是密码,则这相当容易,因为密码具有固有格式和有限的字符集。这就是为什么密钥需要从密码派生的原因。这通常使用PBKDF2,bcrypt或scrypt(使用随机生成的盐和数千或数百万次/高成本因子的大量迭代)来完成。
现在,mcrypt做出了一些可疑的决定。例如,它通过将0x00字节填充到下一个有效大小或将它们裁剪为下一个有效大小,愉快地接受(在早期PHP版本中)无效密钥和IV。这就是为什么使用“plaintextkey”并不是一个好主意。对于第二个密钥,某些字节将产生0x00字节,对于第三个密钥,将产生完整的0x00字节。
mcrypt是弃用软件,不应再使用了。您可以在PHP中使用OpenSSL扩展,也可以使用libsodium或defuse / php-encryption等众多优秀加密库之一。
如果使用CBC方法,是否应该依赖于先前加密的文本?
您可以使用最后一个密文块作为下一次加密的IV,但这只会使加密代码复杂化。你真的应该每次使用一个随机的IV,只需将它添加到密文。它不一定是秘密,而是不可预测的。您可以将它与之前的随机盐一起存放。另见:Why use an Initialization Vector (IV)?
我的格式是否有TripleDES结果?因为当我在互联网上搜索时,从来没有看到过这种形式的加密加密。
现代密码(格式保留加密是一个值得注意的例外)产生的密文应为indistinguishable from random "noise"。因此,您可能会收到不可打印的字符,例如\ x01等等,作为密文的一部分。您想要打印密文,然后需要使用Hex或Base 64在示例中编码为某种可打印格式。
答案 1 :(得分:0)
感谢Artjom的回答,提到你需要添加几个0,直到密钥和IV分别达到24和8的长度。以下是VB.NET代码,以防有人需要它。
Dim byteKey As Byte() = System.Text.Encoding.UTF8.GetBytes("myplaintextkey")
Dim byteVector As Byte() = System.Text.Encoding.UTF8.GetBytes("myplaintextiv")
Dim base64Key As String = Convert.ToBase64String(byteKey)
Dim base64Vector As String = Convert.ToBase64String(byteVector)
Dim key As Byte() = Convert.FromBase64String(base64Key)
Dim iv As Byte() = Convert.FromBase64String(base64Vector)
Dim encryptor As SymmetricEncryptor = New SymmetricEncryptor() 'Note, this an internal library
Try
encryptor.Provider = New System.Security.Cryptography.TripleDESCryptoServiceProvider
encryptor.Encoder = System.Text.Encoding.UTF8
encryptor.Provider.Mode = CipherMode.CBC
encryptor.Provider.Padding = PaddingMode.Zeros
'Add missing zeros to key and IV
If key.Length < 24 Then
Dim i As Integer = key.Length
ReDim Preserve key(23)
While i < 24
key(i) = 0
i += 1
End While
ElseIf key.Length > 24 Then
ReDim Preserve key(23)
End If
If iv.Length < 8 Then
Dim i As Integer = iv.Length
ReDim Preserve iv(8)
While i < 8
iv(i) = 0
i += 1
End While
ElseIf iv.Length > 8 Then
ReDim Preserve iv(8)
End If
encryptor.IV = iv
encryptor.Key = key
Dim output As String = encryptor.Encrypt(output)
Console.Write(output)
Catch ex As Exception
Console.Write(ex.Message)
End Try
我希望它可以帮助某人,再次感谢Artjom!