Estoy muy agradecido con cualquier ayuda. Estoy intentando convertir un rsa cryptor implementación de java en c #. Necesito cifrar los datos de la tarjeta de crédito. La plataforma que uso proporciona SDK de criptografía para javascript y android, pero necesito una implementación de C #.

    try {
      cipher = Cipher.getInstance("RSA/None/PKCS1Padding", "SC");
    } catch (SecurityException se) {
      //workaround for tests
      Log.i("Moip SDK", "No SC provider, running test profile");
      cipher = Cipher.getInstance("RSA");
    }

    BufferedReader pemReader = null;
    pemReader = new BufferedReader(new InputStreamReader(
      new ByteArrayInputStream(publicKey.getBytes("UTF-8"))));

    StringBuffer content = new StringBuffer();
    String line = null;
    while ((line = pemReader.readLine()) != null) {
      if (line.indexOf("-----BEGIN PUBLIC KEY-----") != -1) {
        while ((line = pemReader.readLine()) != null) {
          if (line.indexOf("-----END PUBLIC KEY") != -1) {
            break;
          }
          content.append(line.trim());
        }
        break;
      }
    }
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, keyFactory.generatePublic(new X509EncodedKeySpec(Base64.decode(content.toString(), Base64.DEFAULT))));
    byte[] cipherText = cipher.doFinal(toHash().getBytes());

    return Base64.encodeToString(cipherText, Base64.DEFAULT);

El código que creé mirando la implementación en java, funciona pero no se puede descifrar en la plataforma, debo estar olvidando algo. Mi implementación:

  private string Payload(string number, string expirationMonth, string expirationYear, string cvc) {
    return String.Join(
      "&",
      new List<string> {
        $"number={number}",
        $"cvc={cvc}",
        $"expirationMonth={expirationMonth}",
        $"expirationYear={expirationYear}",
      }
    );
  }

  private string Encrypt(string key, string payload) {
    var publicKey = $"<RSAKeyValue><Modulus>{key}</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
    var rsa = new RSACryptoServiceProvider(2048);
    rsa.FromXmlString(publicKey);
    var encryptedData = rsa.Encrypt(Encoding.UTF8.GetBytes(payload), RSAEncryptionPadding.Pkcs1);
    rsa.Dispose();

    return Convert.ToBase64String(encryptedData);
  }


var payload = Payload(number, expirationMonth, expirationYear, cvc);
hash = Encrypt(ClientManager.Environment.publicKeyCreditCard, payload);
0
Mateus Mendes 23 ago. 2020 a las 15:56

1 respuesta

La mejor respuesta

Bienvenido a Stackoverflow. Ejecuté sus códigos y pude cifrar y descifrar en ambas plataformas (Java y C #) con éxito.

Entonces, en mi opinión, la única razón por la que falla el descifrado al realizar el cifrado en C # es que no convirtió la clave pública correctamente.

Recomiendo usar (ya que es la clave de publicación) un convertidor en línea como https: //superdry.apphb.com/tools/online-rsa-key-converter.

Simplemente copie la clave pública en el área de texto de entrada inferior "PEM a XML" como esta (es una clave RSA no segura de 512 bits, por lo que será más corta que la suya):

-----BEGIN PUBLIC KEY-----" +
MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJn4LYaoLyuT+pD9NKI8wOvPrRjMIxGn
HbqIxUrpGsyj162fEOV4836oCZg0N8HFnt4Vivdjt8/7ZgLjeOygNGUCAwEAAQ==
-----END PUBLIC KEY-----

Y presione "Convertir" - a continuación obtendrá la clave pública en formato xml:

<RSAKeyValue><Modulus>mfgthqgvK5P6kP00ojzA68+tGMwjEacduojFSukazKPXrZ8Q5XjzfqgJmDQ3wcWe3hWK92O3z/tmAuN47KA0ZQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

La clave parcial que debe presentar a su método C # está después de Modulus:

mfgthqgvK5P6kP00ojzA68+tGMwjEacduojFSukazKPXrZ8Q5XjzfqgJmDQ3wcWe3hWK92O3z/tmAuN47KA0ZQ==

Debería estar atento al valor; en la mayoría de las ocasiones es "AQAB", pero en caso de que reciba otro valor, debe ajustar su código fuente en C #.

0
Michael Fehr 23 ago. 2020 a las 14:30