在PHP的mcrypt中使用纯文本作为键和IV

时间:2015-10-29 10:45:03

标签: php encryption mcrypt tripledes

我有一个应用程序,在商定的密钥和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

我的问题是:

  1. 应该使用明文作为参数,PHP如何使用 实现/将其转换为256位字符?
  2. 如果使用CBC方法,则不应依赖于之前的方法 加密文字?
  3. 我的格式是否有TripleDES结果?因为我 通过互联网搜索,从来没有看到过结果 以这种形式加密。

2 个答案:

答案 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!