2015-06-03 77 views
3

我有加密/解密使用下面的代碼從一個基於.NET網絡服務的數據(基於的Rijndael算法):遷移C#.NET加密/解密算法對的Ruby

/** 
* Cifra una cadena texto con el algoritmo de Rijndael 
* 
* @param plainMessage mensaje plano (sin cifrar) 
* @param p_strSpecialKey key especial 
* @return string   texto cifrado en hexadecimal 
*/ 
public static string AES_encryptString(String plainMessage, string p_strSpecialKey) { 
    string strTxtEncrypt = ""; 

    // Crear una instancia del algoritmo de Rijndael 
    try { 
    Rijndael RijndaelAlg = Rijndael.Create(); 
    RijndaelAlg.KeySize = 128; 
    RijndaelAlg.Mode = CipherMode.ECB; 
    RijndaelAlg.Padding = PaddingMode.Zeros; 

    byte[] Key = Encoding.UTF8.GetBytes(p_strSpecialKey); 
    byte[] IV = RijndaelAlg.IV; 

    int keySize = 32; 
    Array.Resize(ref Key, keySize); 

    // Establecer un flujo en memoria para el cifrado 
    MemoryStream memoryStream = new MemoryStream(); 

    // Crear un flujo de cifrado basado en el flujo de los datos 
    CryptoStream cryptoStream = new CryptoStream(memoryStream, 
    RijndaelAlg.CreateEncryptor(Key, IV), 
    CryptoStreamMode.Write); 

    // Obtener la representación en bytes de la información a cifrar 
    byte[] plainMessageBytes = Encoding.UTF8.GetBytes(plainMessage); 

    // Cifrar los datos enviándolos al flujo de cifrado 
    cryptoStream.Write(plainMessageBytes, 0, plainMessageBytes.Length); 
    cryptoStream.FlushFinalBlock(); 

    // Obtener los datos datos cifrados como un arreglo de bytes 
    byte[] cipherMessageBytes = memoryStream.ToArray(); 

    // Cerrar los flujos utilizados 
    memoryStream.Close(); 
    cryptoStream.Close(); 

    strTxtEncrypt = ByteToHex(cipherMessageBytes); 
    } catch (Exception ex) { 
    AddToFile("Error al encriptar el valor: " + plainMessage + " con la clave especial: " + p_strSpecialKey + " " + ex.ToString()); 
    } 

    return strTxtEncrypt; 
} 

/** 
* Descifra una cadena texto con el algoritmo de Rijndael 
* 
* @param encryptedMessage mensaje cifrado en hexadecimal 
* @param p_strSpecialKey key especial 
* @return string    texto descifrado (plano) 
*/ 
public static string AES_decryptString(String encryptedMessage, string p_strSpecialKey) { 
    string strDecrypt = ""; 

    // Crear una instancia del algoritmo de Rijndael 
    try { 
    Rijndael RijndaelAlg = Rijndael.Create(); 
    RijndaelAlg.KeySize = 128; 
    RijndaelAlg.Mode = CipherMode.ECB; 
    RijndaelAlg.Padding = PaddingMode.Zeros; 

    byte[] Key = Encoding.UTF8.GetBytes(p_strSpecialKey); 
    byte[] IV = RijndaelAlg.IV; 

    int keySize = 32; 
    Array.Resize(ref Key, keySize); 

    // Obtener la representación en bytes del texto cifrado 
    byte[] cipherTextBytes = HexToByteArray(encryptedMessage); 

    // Crear un arreglo de bytes para almacenar los datos descifrados 
    byte[] plainTextBytes = new byte[cipherTextBytes.Length]; 

    // Crear un flujo en memoria con la representación de bytes de la información cifrada 
    MemoryStream memoryStream = new MemoryStream(cipherTextBytes); 

    // Crear un flujo de descifrado basado en el flujo de los datos 
    CryptoStream cryptoStream = new CryptoStream(memoryStream, 
    RijndaelAlg.CreateDecryptor(Key, IV), 
    CryptoStreamMode.Read); 

    // Obtener los datos descifrados obteniéndolos del flujo de descifrado 
    int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); 

    // Cerrar los flujos utilizados 
    memoryStream.Close(); 
    cryptoStream.Close(); 

    // Retornar la representación de texto de los datos descifrados 
    strDecrypt = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).Replace("\0", ""); 
    } catch (Exception ex) { 
    AddToFile("Error al desencriptar el valor: " + encryptedMessage + " con la clave especial: " + p_strSpecialKey + " " + ex.ToString()); 
    } 

    return strDecrypt; 
} 

我已經調查了在Ruby上做同樣的事情,我找到了這個答案(How to decode Rijndael in ruby (encoded in VB.net)),但它不適用於我。另外,我不確定我有什麼價值用於iv。 Web服務爲我帶來了一個令牌,我必須使用它作爲密鑰(100%肯定),但實際上並不知道我錯過了什麼。

我使用加密的代碼是:

# /lib/crypt.rb 
module Crypt 
    ... 
    def Crypt.encrypt(data, key, iv, cipher_type) 
    aes = OpenSSL::Cipher::Cipher.new(cipher_type) 
    aes.encrypt 
    aes.key = key 
    aes.iv = iv 
    aes.update(data) + aes.final 
    end 
end 

# ../ws.rb 
... 
token = "8c5d0e6b93cf5d38d7a076b2db35ee6d" #this is a one of the tokens i received 
iv = token 
Crypt.encrypt(a_serialized_json,token,iv,"AES-128-CBC") 

,我要送,必須像一個hexdigest字符串這樣「f0997ddbb17b08913e00b6fb2541312c1cfdda85e555451a1832df076a5d4a5f7d81d8db92715eade144e9696dfbe9eea573baa8ea90cdbe5baadf32fdeb6db8c9ab6743f8eeeb508921999d7513fad3」加密序列化JSON數據。但是鏈接上描述的方法會生成一個像這樣的加密字符串「」。「

任何想法我做錯了什麼或我失蹤?

UPDATE:我想到我得到的字符串輸出是一個字節數組,我必須將此字節數組轉換爲十六進制字符串。我正在使用以下方法(https://github.com/atomicobject/hex_string/blob/master/lib/hex_string.rb)。但是,仍然不確定Cypher是否被正確配置爲充當C#代碼。

回答

0

最後,我找到了一個與C#代碼完全匹配的庫,它的編號爲ruby-mcrypthttps://github.com/kingpong/ruby-mcrypt)。我用的加密/解密代碼是這樣的:

require 'mcrypt' 

module Crypt 
    def Crypt.m_encrypt(data, key) 
    crypto = Mcrypt.new(:rijndael_128, :ecb, key, nil, :zeros) 
    encrypted_data = crypto.encrypt(data) 
    encrypted_data 
    end 

    def Crypt.m_decrypt(data, key) 
    crypto = Mcrypt.new(:rijndael_128, :ecb, key, nil, :zeros) 
    crypto.decrypt(data) 
    end 
end 

重要:本C#Rjandael庫不使用IV,因爲這個原因我放棄零參數作爲四這個Mcrypt。

這只是加密/解密部分,我也將字符串轉換爲hexa格式。希望它能幫助別人!

+0

嗨,我試圖比較C#和你的紅寶石,我的加密解密拿出完全不同的答案。是否有更多的你的ruby代碼,你沒有發佈? – Joelio

+0

我不記得確切的輸入/輸出提供了紅寶石和C#代碼,不幸的是我丟失了源代碼。唯一沒有指定的是,提供的鍵必須是相同的。也許未來版本的gem會從那時起改變輸出字符串 –