2010-12-01 24 views
18

Şu anda php mcrypt tarafından şifrelenmiş bir mesajın şifresini çözmek için biraz problem yaşıyorum. php kodu, aşağıdaki gibidir:Çapraz platform (php ile C# .NET) şifreleme/şifre çözme Rijndael ile

<?php 
    //$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 
    $iv = "45287112549354892144548565456541"; 
    $key = "anjueolkdiwpoida"; 
    $text = "This is my encrypted message"; 
    $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv); 
    $crypttext = urlencode($crypttext); 
    $crypttext64=base64_encode($crypttext); 
    print($crypttext64) . "\n<br/>"; 
?> 

şifrelenmiş mesaj daha sonra ASP.NET platformu (C#) gönderilir. Ancak, şifre çözme sırasını koruyarak sorun yaşıyorum (base64 urldecode kod çözme). ASP.NET'te vardı kodu aşağıdaki gibidir (iv ve anahtar php aynıdır):

public string Decode(string str) 
{ 
    byte[] decbuff = Convert.FromBase64String(str); 
    return System.Text.Encoding.UTF8.GetString(decbuff); 
} 

static public String DecryptRJ256(string cypher, string KeyString, string IVString) 
{ 

    string sRet = ""; 
    RijndaelManaged rj = new RijndaelManaged(); 
    UTF8Encoding encoding = new UTF8Encoding(); 


    try 
    { 
     //byte[] message = Convert.FromBase64String(cypher); 
     byte[] message = encoding.GetBytes(cypher); 

     byte[] Key = encoding.GetBytes(KeyString); 
     byte[] IV = encoding.GetBytes(IVString); 

     rj.Padding = PaddingMode.Zeros; 
     rj.Mode = CipherMode.CBC; 
     rj.KeySize = 256; 
     rj.BlockSize = 256; 
     rj.Key = Key; 
     rj.IV = IV; 
     MemoryStream ms = new MemoryStream(message); 

     using (CryptoStream cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read)) 
     { 
      using (StreamReader sr = new StreamReader(cs)) 
      { 
       sRet = sr.ReadToEnd(); 
      } 
     } 

    } 
    finally 
    { 
     rj.Clear(); 
    } 

    return sRet; 


} 

string temp = DecryptRJ256(Server.UrlDecode(Decode(cypher)), keyString, ivString); 

I having I php şifrelenmiş mesajın alınan sonra, dönüştürülmüş olmasıdır bunu byte [] içine ve daha sonra UTF8 kodlanmış dizgeye geri dönüştürerek bu kodu değiştirebilirim. sonra sonucu, dizeyi byte [] 'a geri dönüştürdüğüm ve şifre çözme işleminde çalıştırdığım işleve besliyorum. Ancak, istenilen sonucu elde edemiyorum ... herhangi bir fikir?

Şimdiden teşekkürler.

+0

için 'Eğer' base64_encode' önce şifreli veri urlencode'. – Powerlord

cevap

31

Her iki tarafta da sorunları görebiliyorum.

Lütfen kodlama sırasında ne aldığınızı değil, bir dizi bayt olduğunu unutmayın. Yani PHP'de cyphertext'i deraltmak zorunda değilsiniz.

base64 kodlaması sizin için yeterlidir. Eğer base64_encode help açtığınızda

base64_encode base64 ile verilen verileri kodlar görüyoruz. Bu kodlama götürmesine

Bir şey daha hayatta ikili veri hale getirmek için tasarlanmış olduğunu - mesajınız doğru uzunlukta .net içinde çözülür olduğu, el dolgu karakterleri ile ekler gerekiyor. RijndaelManaged için varsayılan doldurma modu PKCS7'dir, 'bununla sopa yapalım. Kaynak dizginizi, kodlama bayt sayısı sayısına eşit karakter kodlarıyla bile genişletmek zorundasınız. C# tarafında

<?php 
    $iv = "45287112549354892144548565456541"; 
    $key = "anjueolkdiwpoida"; 
    $text = "This is my encrypted message"; 

    // to append string with trailing characters as for PKCS7 padding scheme 
    $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 
    $padding = $block - (strlen($text) % $block); 
    $text .= str_repeat(chr($padding), $padding); 

    $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv); 

    // this is not needed here    
    //$crypttext = urlencode($crypttext); 

    $crypttext64=base64_encode($crypttext); 
    print($crypttext64) . "\n<br/>"; 
?> 

Eğer base64 [] bayt dize [] için bayt için yayın yapmak var. Sen [] bayt için base64 gelen ilk dönüşümü yapmak sadece var. Unutmayın, base64 dizge değil, ikili veri olan şifreli metni tutuyor. Ayrıca, RijndaelManaged'in IDisposable olduğunu lütfen unutmayın, bu yüzden() yapısını kullanarak sardım. MSDN'de belirtildiği gibi Close() çağırmak gereklidir, ancak yeterli değildir. Bunun sonucunda
public byte[] Decode(string str) 
{ 
    var decbuff = Convert.FromBase64String(str); 
    return decbuff; 
} 

static public String DecryptRJ256(byte[] cypher, string KeyString, string IVString) 
{ 
    var sRet = ""; 

    var encoding = new UTF8Encoding(); 
    var Key = encoding.GetBytes(KeyString); 
    var IV = encoding.GetBytes(IVString); 

    using (var rj = new RijndaelManaged()) 
    { 
     try 
     { 
      rj.Padding = PaddingMode.PKCS7; 
      rj.Mode = CipherMode.CBC; 
      rj.KeySize = 256; 
      rj.BlockSize = 256; 
      rj.Key = Key; 
      rj.IV = IV; 
      var ms = new MemoryStream(cypher); 

      using (var cs = new CryptoStream(ms, rj.CreateDecryptor(Key, IV), CryptoStreamMode.Read)) 
      { 
       using (var sr = new StreamReader(cs)) 
       { 
        sRet = sr.ReadLine(); 
       } 
      } 
     } 
     finally 
     { 
      rj.Clear(); 
     } 
    } 

    return sRet; 
} 

, C# Aşağıdaki kod size ilk dizeyi döndürür: Sen gerekmez

var iv = "45287112549354892144548565456541"; 
var key = "anjueolkdiwpoida"; 
var cypher = "u+rIlHB/2rrT/u/qFInnlEkg2unhizsNzGVb9O54sP8="; 

var temp = DecryptRJ256(Decode(cypher), key, iv); 
+0

Bunu denedim ve işe yarıyor! Göndermiş olman harika. – Yuki

+0

Örnekler için aferin. Kodunu şifre çözme ile tamamladım ve her şeyi bir [gist] (https://gist.github.com/2036829) –

+0

içine koydum. Bu kodu denedim, C# uygulamasının çalıştığı yerde POST'tan $ anahtarını kabul ediyorum. Şifrelenmiş dizgenin şifresini çözme Bu algoritma için geçerli olmayan istisna tarafından belirlenen bir anahtar atılır.Lütfen bana yardım edin http://stackoverflow.com/questions/10160690/php-encryption-and-decryption-with-data-from-post-method-using-c-sharp – techno

İlgili konular