¿Cómo transferir la clave pública Java RSA a la función cifrar c #?

Aug 29 2020

Desea utilizar la clave pública RSA generada en java, en la función c # para cifrar datos y descifrarlos en la función de descifrado de Java.

La clave pública de Java generada se ha reemplazado en la etiqueta Modulus en c #:

static string publicKey = "<RSAKeyValue><Modulus>MFwwDQ...wEAAQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

Función de cifrado de C #:

  static string Encrypt(string text)
    {
        const int PROVIDER_RSA_FULL = 1;
        const string CONTAINER_NAME = "Tracker";

        CspParameters cspParams;
        cspParams = new CspParameters(PROVIDER_RSA_FULL);
        cspParams.KeyContainerName = CONTAINER_NAME;
       
        RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider(512,cspParams);
        rsa1.FromXmlString(publicKey);

        byte[] textBytes = Encoding.UTF8.GetBytes(text);
        byte[] encryptedOutput = rsa1.Encrypt(textBytes, RSAEncryptionPadding.Pkcs1);
        string outputB64 = Convert.ToBase64String(encryptedOutput);

        return outputB64;
    }

Función Java Decrypt:

static String Decrypt(String encodedString,PrivateKey privKey) {
    try {
        Cipher cipher = Cipher.getInstance(cipherInstancename);
        cipher.init(Cipher.DECRYPT_MODE, privKey);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encodedString));
        return new String(decrypted, "UTF-8");
    } catch (Exception err) {
        return err.fillInStackTrace().toString();
    }
}

Primera pregunta: ¿Es correcto reemplazar la clave pública de Java en la etiqueta Modulus en la cadena XML de c #? ¿Qué pasa con la etiqueta Exponent? Usé el valor AQAB para ello.

La segunda pregunta: ¿Por qué al descifrar en Java obtuve este error?

 javax.crypto.IllegalBlockSizeException: Data must not be longer than 64 bytes

Después de investigar un poco, encontré que es un error general, ¿qué causa puede producir este tipo de error?

Respuestas

2 Topaco Aug 29 2020 at 17:12

Primera pregunta: ¿Es correcto reemplazar la clave pública de Java en la etiqueta Modulus en la cadena XML de c #?

¡No! La clave no es idéntica al módulo, pero contiene el módulo y el exponente. Por lo tanto, en su caso, ambos deben determinarse a partir de la clave generada en Java.

Se puede dar una clave pública en diferentes formatos. Por ejemplo, una clave pública generada en Java nativo normalmente tendrá el formato X.509 / SPKI y probablemente será a byte[], es decir, en codificación DER. Si byte[]está codificado en Base64 (esto corresponde al publicado MFwwDQ...wEAAQ==) y el encabezado ----- BEGIN PUBLIC KEY ----- y el pie de página ----- END PUBLIC KEY ----- se agregan (generalmente en el Cuerpo codificado en Base64 (también hay un salto de línea después de cada 64 caracteres), la clave estará en codificación PEM.

La forma más sencilla de determinar el módulo y el exponente manualmente es cargar la clave PEM en un analizador ASN.1, por ejemplo , aquí , o convertirla directamente al formato XML en un sitio web adecuado, por ejemplo, aquí .

¿Qué pasa con la etiqueta Exponent? Usé el valor AQAB para ello.

Esta pregunta ya ha sido respondida implícitamente con lo dicho anteriormente. Pero una observación: para el exponente, a menudo se elige el valor 65537 (codificado en hexadecimal 0x010001 y AQAB codificado en Base64 ). Pero este no es siempre el caso. Entonces, si el exponente de una clave existente se reemplaza ciegamente por este valor, existe una alta probabilidad de que funcione, pero no puede confiar en él, consulte, por ejemplo, aquí y aquí .

La segunda pregunta: ¿Por qué al descifrar en Java aparece este error: javax.crypto.IllegalBlockSizeException: los datos no deben tener más de 64 bytes ?

Esto ya ha sido respondido en el comentario de Michael Fehr, entre otros puntos importantes (como seguridad, rendimiento y encriptación híbrida): La longitud de la clave limita la longitud del texto sin formato, con una clave de 512 bits se puede encriptar un máximo de 64 bytes.

Además, debe tenerse en cuenta que no solo la longitud de la clave, sino también el relleno utilizado limita la longitud del texto sin formato, por ejemplo, PKCS # 1 v1.5 El relleno requiere 11 bytes, por lo que la longitud máxima del texto plano para una clave de 512 bits es 64 - 11 = 53 bytes, aquí . En el caso de OAEP, el resumen utilizado determina cuántos bytes requiere el relleno, consulte, por ejemplo, aquí . Si no se utiliza relleno (tetxbook RSA), la longitud máxima del texto plano corresponde a la longitud de la clave. En la práctica, sin embargo, el acolchado siempre debe usarse por razones de seguridad.


A partir de .NET Core 3.0, la importación de una clave X.509 / SPKI (en codificación DER) y formatos similares se admite directamente , consulte, por ejemplo, aquí y especialmente RSA.ImportSubjectPublicKey. En versiones anteriores de .NET Core y en .NET Framework, estas funciones no están disponibles, pero se puede usar BouncyCastle en su lugar.