将c# . net加密/解密算法迁移到Ruby
本文关键字:算法 迁移 Ruby 解密 net 加密 | 更新日期: 2023-09-27 17:53:13
我必须加密/解密来自使用以下代码的基于。net的web服务的数据(基于Rijndael算法):
/**
* 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上做同样的事情的方法,我发现了这个答案(如何在Ruby中解码Rijndael(在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")
我必须发送的加密序列化json数据必须像这样的十六进制字符串"f0997ddbb17b08913e00b6fb2541312c1cfdda85e555451a1832df076a5d4a5f7d81d8db92715eade144e9696dfbe9eea573baa8ea90cdbe5baadf32fdeb6db8c9ab6743f8eeeb508921999d7513fad3"。但是链接中描述的方法会生成一个加密字符串,如"^w'x9A'x90B'xDC'f'x16'xB8'xBDt'xFBo'xD7r'x97"。
你知道我做错了什么或者我错过了什么吗?
UPDATE:我发现我得到的字符串输出是一个字节数组,我必须将这个字节数组转换为十六进制字符串。我使用以下方法(https://github.com/atomicobject/hex_string/blob/master/lib/hex_string.rb)。但是,仍然不确定Cypher是否正确配置为c#代码。
最后,我找到了一个完全匹配c#代码的库,它是ruby-mcrypt
(https://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,因此我将nil参数作为IV给Mcrypt。
这只是加密/解密部分,我也将字符串转换为十六进制格式。希望它能帮助到其他人!