首页 文章

.NET WebService加密 - > PHP解密错误:mcrypt_encrypt():IV参数必须与块大小一样长

提问于
浏览
0

从.NET中写入的Web服务接收参数但我无法解密这些参数

参数已使用SHA1,Rijndael 256位加密 .

php代码:

$passphrase='16charskey';
$salt = '16charssat';
$iterations = 2;
$keysize = 32;

$key = pbkdf2($passphrase,$salt, $iterations, $keysize);
$text = 'my crypted text';
$iv = '16charsinitvector';
$result =  mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($text), MCRYPT_MODE_CBC, $iv)

函数pbkdf2是下一个

function pbkdf2( $p, $s, $c, $kl, $a = 'sha1' ) {
    $hl = strlen(hash($a, null, true)); # Hash length
    $kb = ceil($kl / $hl);              # Key blocks to compute
    $dk = '';                           # Derived key
    # Create key
    for ( $block = 1; $block <= $kb; $block ++ ) {
        # Initial hash for this block
        $ib = $b = hash_hmac($a, $s . pack('N', $block), $p, true);
        # Perform block iterations
        for ( $i = 1; $i < $c; $i ++ )
            # XOR each iterate
            $ib ^= ($b = hash_hmac($a, $b, $p, true));
        $dk .= $ib; # Append iterated block
    }
    # Return derived key of correct length
    return substr($dk, 0, $kl);
}

当我执行时给出警告:mcrypt_encrypt():IV参数必须与块大小一样长

我测试将$ iv的长度更改为32个字符,警告消失 . 当我将字符串$ iv更改为具有少于32个字符的任何字符串的其他字符串时,结果与$ iv为空时的结果相同 .

有任何想法吗?

UPDATED

这是加密中的WebService代码

Public Function strEncrypt( _
        ByVal strText As String _
        , ByVal strPass As String _
        , ByVal strSalt As String _
        , ByVal strHASH As String _
        , ByVal nIterations As Integer _
        , ByVal strIV As String _
        , ByVal nSize As Integer _
    ) As String

        Try
            Dim btText As Byte() = Encoding.UTF8.GetBytes(strText)
            Dim btSalt As Byte() = Encoding.UTF8.GetBytes(strSalt)
            Dim btIV As Byte() = Encoding.UTF8.GetBytes(strIV)
            Dim objPasswordDeriveBytes As PasswordDeriveBytes = New PasswordDeriveBytes(strPass, btSalt, strHASH, nIterations)
            Dim btKey As Byte() = objPasswordDeriveBytes.GetBytes(nSize / 8)
            Dim objRijndaelManaged As RijndaelManaged = New RijndaelManaged()
            objRijndaelManaged.Mode = CipherMode.CBC
            Dim objICryptoTransform As ICryptoTransform = objRijndaelManaged.CreateEncryptor(btKey, btIV)
            Dim objMemoryStream As MemoryStream = New MemoryStream()
            Dim objCryptoStream As CryptoStream = New CryptoStream(objMemoryStream, objICryptoTransform, CryptoStreamMode.Write)
            objCryptoStream.Write(btText, 0, btText.Length)
            objCryptoStream.FlushFinalBlock()
            Dim btEncrypt As Byte() = objMemoryStream.ToArray()
            objMemoryStream.Close()
            objCryptoStream.Close()
            strEncrypt = Convert.ToBase64String(btEncrypt)

        Catch ex As Exception
            strEncrypt = ""
        End Try

EDIT

我将pbkdf2调用更改为pbkdf1

function PBKDF1($pass, $salt, $count, $dklen)
{
    $t = $pass.$salt;
    $t = sha1($t, true);
    for($i=2; $i <= $count; $i++)
    {
        $t = sha1($t, true);
    }
    $t = substr($t,0,$dklen-1);
    return $t;
}

并且算法为MCRYPT_RIJNDAEL_128,这是正确的,但mcrypt_encrypt的输出和相同字符串的Web服务,具有相同的salt,iterations,keysize,passphrase,是不同的...

我没有看到差异,以获得不同的输出

1 回答

  • 1

    Artjom是对的,你应该用 MCRYPT_RIJNDAEL_128 替换 MCRYPT_RIJNDAEL_256 .

    请注意,使用静态IV并不安全 . 然而,它比在传输协议中使用CBC模式加密更安全(因为没有完整性保护,并且因为填充神谕是可能的);只有在攻击者无法更改密文时才应使用此类方案 .


    在编辑之后,您还清楚地知道您已经实现了PBKDF2而不是 PasswordDeriveBytes 提供的PBKDF1 .

相关问题