2010-10-18 59 views
0

我有一些用Perl編寫的加密代碼(也是PHP中的代碼片段) - 但我無法獲得用VB.NET編寫的與第三方一起工作的版本。在PHP如何將以下加密代碼從Perl(或PHP)轉換爲VB.NET?

/** 
* @param string $plaintext 
* @return string encrypted token 
* 
* Relies on the Mcrypt module 
*/ 
function encrypt($plaintext, $apiKey) 
{ 
    // Initialize mcrypt module (AES, 128-bit key, CBC) 
    $handle = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); 
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($handle), MCRYPT_DEV_URANDOM); 

    // PKCS#5 padding 
    $blocksize = mcrypt_enc_get_block_size($handle); 
    $padsize = $blocksize - (strlen($plaintext) % $blocksize); 
    $plaintext .= str_repeat(chr($padsize), $padsize); 

    // encrypt 
    mcrypt_generic_init($handle, $apiKey, $iv); 
    $ciphertext = mcrypt_generic($handle, $plaintext); 

    // clean up 
    mcrypt_generic_deinit($handle); 
    mcrypt_module_close($handle); 

    return base64_encode($iv. $ciphertext); 
} 

例在Perl

package Sitemaker::API::Crypt; 

    use warnings; 
    use strict; 
    use base qw(Exporter); 

    use Crypt::CBC; 
    use MIME::Base64; 

    our @EXPORT = qw(
     encrypt 
     decrypt 
    ); 

    =head2 encrypt($key, $iv, $arg1[,$arg2][,...] ) 

    This encrypts the argumenst (which must all be values, not references) with 
    the key (which must be 16 characters long) 

    =cut 
    sub encrypt { 
     my ($key, $iv, @args) = @_; 
     my $args = join('|', @args); 

     my $cipher = Crypt::CBC->new(
      -cipher => 'Rijndael', 
      -blocksize => 16, 
      -keysize => 16, 
      -header => 'none', 
      -padding => 'standard', 
      -iv => $iv, 
      -literal_key => 1, 
      -key => $key, 
     ); 

     my $binary_token = $cipher->encrypt($args); 

     return encode_base64($iv . $binary_token); 
    } 
1; 

實例所以我試圖重新在VB.NET一樣,但我不認爲它的工作,如我張貼到服務,只是得到錯誤。在VB.NET中的加密方法是...

Public Function EncrpytIt(ByVal Key As String, ByVal IV As String, ByVal arrParams As String()) As String 
     Dim plainTextBytes As Byte() 
     plainTextBytes = Encoding.ASCII.GetBytes(Join(arrParams, "~")) 

     Dim outputBytes As Byte() 

     Dim symmetricKey As New System.Security.Cryptography.RijndaelManaged() 
     With symmetricKey 
      .Key = Encoding.ASCII.GetBytes(Key) 
      .IV = Encoding.ASCII.GetBytes(IV) 
      .Mode = CipherMode.CBC 
      .BlockSize = 128 
      .KeySize = 128 
      .Padding = PaddingMode.PKCS7 
     End With 
     Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(symmetricKey.Key, symmetricKey.IV) 
     Using msEncrypt As New MemoryStream() 
      Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write) 
       csEncrypt.Write(plainTextBytes, 0, plainTextBytes.Length) 
       csEncrypt.FlushFinalBlock() 
      End Using 
      outputBytes = msEncrypt.ToArray 
     End Using 
     Return IV & Convert.ToBase64String(outputBytes) 
    End Function 

這是行爲方式相同,還是我必須改變vb.net代碼中的設置?

回答

2

我看到的第一件事情是,在PHP和Perl的情況下,基數64使用加密數據對連接的IV字符串進行編碼,而在VB中,返回IV的連接字符串和基本64編碼輸出的加密。

你需要return語句改成這樣:

Return Convert.ToBase64String(Encoding.ASCII.GetBytes(IV) & outputBytes) 

而且,似乎有點用的填充方案不一致的 - 至少在PHP和VB.NET版本之間。根據PHP示例中的註釋 - 即使用PKCS#5並且您的Visual Basic代碼使用PKCS#7。我不確定Perl的上下文中'標準'的含義。

+0

這是最後一行的一個很好的地方。我不知道如何獲得vb.net中PKCS#5的填充,所以我可能不得不打開另一個問題。 – digiguru 2010-10-18 19:52:29