2016-10-10 1 views
0

J'utilise le château gonflable et le code suivant dans C# pour chiffrer et déchiffrer des données dans C#Crypter et Décrypter utilisant Bouncy Castle en C# et php

public static string BCEncrypt(string input) 
{ 
    string keyString = "mysecretkey12345"; 
    string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString)); 
    byte[] inputBytes = Encoding.UTF8.GetBytes(input); 
    byte[] iv = new byte[16]; 

    //Set up 
    AesEngine engine = new AesEngine(); 
    CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC 
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding()); 
    //PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7 
    KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64)); 
    ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16); 

    // Encrypt 
    cipher.Init(true, keyParamWithIV); 
    byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)]; 
    int length = cipher.ProcessBytes(inputBytes, outputBytes, 0); 
    cipher.DoFinal(outputBytes, length); //Do the final block 
    return Convert.ToBase64String(outputBytes); 
} 

public static string BCDecrypt(string input) 
{ 
    string keyString = "mysecretkey12345"; 
    string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString)); 
    byte[] inputBytes = Encoding.UTF8.GetBytes(input); 
    byte[] iv = new byte[16]; 
    //Set up 
    AesEngine engine = new AesEngine(); 
    CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC 
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher); //Default scheme is PKCS5/PKCS7 
    KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64)); 
    ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16); 

    //Decrypt    
    byte[] outputBytes = Convert.FromBase64String(input); 
    cipher.Init(false, keyParamWithIV); 
    byte[] comparisonBytes = new byte[cipher.GetOutputSize(outputBytes.Length)]; 
    int length = cipher.ProcessBytes(outputBytes, comparisonBytes, 0); 
    cipher.DoFinal(comparisonBytes, length); //Do the final block 
    return System.Text.Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length); 
} 

Ce code php code J'utilise:

<? 
    function encrypt($input, $key) { 
     $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); 
     $input = Security::pkcs5_pad($input, $size); 
     $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, ''); 
     $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); 
     mcrypt_generic_init($td, $key, $iv); 
     $data = mcrypt_generic($td, $input); 
     mcrypt_generic_deinit($td); 
     mcrypt_module_close($td); 
     $data = base64_encode($data); 
     return $data; 
    } 

    function pkcs5_pad ($text, $blocksize) { 
     $pad = $blocksize - (strlen($text) % $blocksize); 
     return $text . str_repeat(chr($pad), $pad); 
    } 

    function decrypt($sStr, $sKey) { 
     $decrypted= mcrypt_decrypt(
      MCRYPT_RIJNDAEL_128, 
      $sKey, 
      base64_decode($sStr), 
      MCRYPT_MODE_ECB 
     ); 
     $dec_s = strlen($decrypted); 
     $padding = ord($decrypted[$dec_s-1]); 
     $decrypted = substr($decrypted, 0, -$padding); 
     return $decrypted; 
    } 

    echo "Input: " . $_REQUEST["inp"] . "<br>Decrypt: ". decrypt($_REQUEST["inp"], 'mysecretkey12345')."<br>"; 
    ?> 

Lorsque je tente de chiffrer une courte chaîne en utilisant C# comme "greatscott" j'obtenir le résultat suivant: dSk7z0F4JYsc0zhl95 + YMW ==

Ce déchiffre ok en utilisant le code php.

Cependant lorsque je tente de chiffrer une chaîne plus longue en utilisant le code C# tel que « ceci est une chaîne très longue » Je reçois le résultat suivant: xcL4arrFD8Fie73evfHjvUjNEmZrA9h6SmO0ZRE82Hw =

Et cela ne déchiffre pas. Si je tente de chiffrer la même chaîne « ceci est une chaîne très longue » via la fonction php Crypter Je reçois xcL4arrFD8Fie73evfHjva6yJyeUOrB8IudISDhQk24 =

Ainsi, la première moitié de la chaîne cryptée est le même, mais la seconde moitié est pas. Cela me fait penser que j'ai le rembourrage incorrect ou quelque chose.

Tout conseil serait apprécié.

Merci

+0

Utilisez openssl pour le cryptage et le décryptage en PHP. –

+3

Vous utilisez le mode ECB dans le code PHP et le mode CBC dans le code C#. En outre, vous utilisez un IV tout-zéros dans la fonction de cryptage C#, mais un IV aléatoire dans le code PHP. Vous n'envoyez pas la IV dans les deux codes. Vous avez beaucoup tort ici. –

+0

Utiliser le mode CTR. Oubliez vous entendu parler de tout autre mode. – Ben

Répondre

0

Merci pour les suggestions Luke et James. J'utilise maintenant openssl pour le cryptage et le décryptage en PHP et je génère un IV aléatoire et je le fais circuler entre les systèmes pour le décryptage.

C'est le code que je suis maintenant en utilisant:

C#

public static string BCEncrypt(string input, out string iv_base64) 
{ 
    byte[] inputBytes = Encoding.UTF8.GetBytes(input); 
    SecureRandom random = new SecureRandom(); 
    byte[] iv = new byte[16]; 
    random.NextBytes(iv); 
    iv_base64 = Convert.ToBase64String(iv); 
    string keyString = "mysecretkey12345"; 
    string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString)); 

    //Set up 
    AesEngine engine = new AesEngine(); 
    CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC 
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding()); 
    KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64)); 
    ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16); 

    // Encrypt 
    cipher.Init(true, keyParamWithIV); 
    byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)]; 
    int length = cipher.ProcessBytes(inputBytes, outputBytes, 0); 
    cipher.DoFinal(outputBytes, length); //Do the final block 
    return Convert.ToBase64String(outputBytes); 
} 

public static string BCDecrypt(string input, string iv_base64) 
{ 
    string keyString = "mysecretkey12345"; 
    string keyStringBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(keyString)); 
    byte[] inputBytes = Encoding.UTF8.GetBytes(input); 
    byte[] iv = Convert.FromBase64String(iv_base64); 
    //Set up 
    AesEngine engine = new AesEngine(); 
    CbcBlockCipher blockCipher = new CbcBlockCipher(engine); //CBC 
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), new Pkcs7Padding()); 
    KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(keyStringBase64)); 
    ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 16); 

    //Decrypt    
    byte[] outputBytes = Convert.FromBase64String(input); 
    cipher.Init(false, keyParamWithIV); 
    byte[] comparisonBytes = new byte[cipher.GetOutputSize(outputBytes.Length)]; 
    int length = cipher.ProcessBytes(outputBytes, comparisonBytes, 0); 
    cipher.DoFinal(comparisonBytes, length); //Do the final block 
    return Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length); 
} 

Le regard de côté PHP comme ceci:

$iv = base64_decode($iv_base64); 
$method = "aes-128-cbc"; 
$password = "mysecretkey12345"; 
$decrypted = openssl_decrypt($data, $method, $password,0, $iv); 

Et pour générer le iv et chiffrer une chaîne en PHP J'utilise:

$iv = openssl_random_pseudo_bytes(16) 
$encrypted = openssl_encrypt("something interesting", $method, $password,0,$iv); 

Donc, je suis maintenant capable de crypter en C# ou PHP et décrypter en C# ou PHP.

Je passe la chaîne codée iv de base 64 et la chaîne cryptée entre les deux systèmes en utilisant https.

Un commentaire sur cette solution? (Sécurité ou autre?)