Soy nuevo en criptografía. Tengo un api proporcionado por un banco. Los bancos dicen que están utilizando el algoritmo RSA con 2048 bits. Usamos esta API primero para obtener la clave pública. Aquí está la clave pública de muestra (algunos caracteres actualizados para seguridad),
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgqvmScnvYGpQ+exGe9OM2tYM+JGjEZbQ
VxQsnBQ7tfSTc6gSsUSFZdASD7Jrr2Mo1EvcBW+wyuENvS5G+d65EGv2lKlFb7iCgVF2RGw5dDdS
kD7hF1lCnXA6TNi7hMwQWeCInEMTeD1ZR52KvRK4jmLr3EWyujTP/h0oyOpBRc5dvoCOgyi7eSXG
q7uUWUOOZNnTtW/fIixdNQJ28Kz5Mf4HykHZxIPTtjg6I1jZgBdVL6pYgwA2oyHGEOe2ObB6ZeTB
9+meHuTxyIRUtTPSNSK0bfHYT56TwruwgJwnrHjvvM07Lzah69wLvhWAiR2mPQb6juG2zCaU5Mad
sesEuQIDAQAB
Este se parece a la cadena Base 64. La longitud es 397. Supongo que esto es Módulo y Exponente es AQAB. Cuando convierto esta Base64 en bytes, se convierten en 294 y (294 * 8) 2352 bits. ¿Por qué 2352 y no 2048 bits?
En realidad, estoy cifrando una cadena y enviándola a la API del Banco tanto en Java como en C #. En Java lo estoy haciendo,
public class RSAUtility {
public static String encrypt(String plainText, String key){
try{
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decode(key, Base64.DEFAULT)));
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeToString(cipher.doFinal(plainText.getBytes("UTF-8")),Base64.DEFAULT);
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
Funciona muy bien en java. Pero en C # estoy haciendo esto y no funciona. Cualquier experto puede ayudarme, por favor.
var keyXml = "<RSAKeyValue><Modulus>" + key + "</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
EncrptedValue = CryptUtils.Encrypt(keyXml, "MyString", RsaKeyLengths.Bit2048);
public static string Encrypt(string publicKey, string data, RsaKeyLengths length = RsaKeyLengths.Bit2048)
{
// full array of bytes to encrypt
byte[] bytesToEncrypt;
// worker byte array
byte[] block;
// encrypted bytes
byte[] encryptedBytes;
// length of bytesToEncrypt
var dataLength = 0;
// number of bytes in key
var keySize = 0;
// maximum block length to encrypt
var maxLength = 0;
// how many blocks must we encrypt to encrypt entire message?
var iterations = 0;
// the encrypted data
var encryptedData = new StringBuilder();
// instantiate the crypto provider with the correct key length
var rsaCryptoServiceProvider = new RSACryptoServiceProvider((int)length);
// initialize the RSA object from the given public key
rsaCryptoServiceProvider.FromXmlString(publicKey);
// convert data to byte array
bytesToEncrypt = Encoding.Unicode.GetBytes(data);
// get length of byte array
dataLength = bytesToEncrypt.Length;
// convert length of key from bits to bytes
keySize = (int)length / 8;
// .NET RSACryptoServiceProvider uses SHA1 Hash function
// use this to work out the maximum length to encrypt per block
maxLength = ((keySize - 2) - (2 * SHA1.Create().ComputeHash(bytesToEncrypt).Length));
// how many blocks do we need to encrypt?
iterations = dataLength / maxLength;
// encrypt block by block
for (int index = 0; index <= iterations; index++)
{
// is there more than one full block of data left to encrypt?
if ((dataLength - maxLength * index) > maxLength)
{
block = new byte[maxLength];
}
else
{
block = new byte[dataLength - maxLength * index];
}
// copy the required number of bytes from the array of bytes to encrypt to our worker array
Buffer.BlockCopy(bytesToEncrypt, maxLength * index, block, 0, block.Length);
// encrypt the current worker array block of bytes
encryptedBytes = rsaCryptoServiceProvider.Encrypt(block, true);
// RSACryptoServiceProvider reverses the order of encrypted bytesToEncrypt after encryption and before decryption.
// Undo this reversal for compatibility with other implementations
Array.Reverse(encryptedBytes);
// convert to base 64 string
encryptedData.Append(Convert.ToBase64String(encryptedBytes));
}
return encryptedData.ToString();
}