vernam numeros escitala encriptar desencriptar descifrar contraseƱa como cifrar cifrado archivos java c# encryption cryptography rijndael

java - numeros - Descifre el texto codificado de C#RIJNDAEL



encriptar y desencriptar rsa en java (1)

Estoy implementando en Java la comunicación a una aplicación de terceros. Como parte del proceso de inicio de sesión, la aplicación de terceros está enviando una cadena encriptada que debo decodificar y enviar de vuelta. He pasado casi 2 días haciendo publicaciones y leyendo publicaciones, pero no encuentro la manera correcta de implementarlo.

Tengo un caso de prueba donde la cadena cifrada es "c1W2YO1vYQzu6czteEidrG0U4g5gT4h57vAlP7tdjcY =" que descifrado con la contraseña "GAT" debe devolver "101714994".

La documentación que tengo declara esto: la cadena de autorización fue encriptada con la siguiente configuración:

  • Relleno de datos de entrada: PKCS * 7
  • La matriz de bytes de la contraseña tiene 32 bytes de longitud. La cadena de contraseña se convierte en una matriz de bytes codificada en UTF-16 y la matriz de bytes se rellena con ceros de hasta 32 bytes de longitud. Las contraseñas más largas se truncan.

Este es el ejemplo de C # de cómo descifrar la cadena de autorización:

/// <summary> /// Decrypts a string. /// </summary> /// <param name="content">The string to decrypt.</param> /// <param name="password">The password to use.</param> /// <returns>The decrypted string.</returns> private static string DecryptString(string content, string password) { Rijndael aes; byte[] retVal = null; byte[] contentBytes; byte[] passwordBytes; byte[] ivBytes; try { //Get the content as byte[] contentBytes = Convert.FromBase64String(content); //Create the password and initial vector bytes passwordBytes = new byte[32]; ivBytes = new byte[16]; Array.Copy(Encoding.Unicode.GetBytes(password), passwordBytes, Encoding.Unicode.GetBytes(password).Length); Array.Copy(passwordBytes, ivBytes, 16); //Create the cryptograpy object aes = Rijndael.Create(); aes.Key = passwordBytes; aes.IV = ivBytes; aes.Padding = PaddingMode.PKCS7; //Decrypt retVal = aes.CreateDecryptor().TransformFinalBlock(contentBytes, 0, contentBytes.Length); } catch { } aes = null; contentBytes = null; passwordBytes = null; ivBytes = null; return Encoding.Unicode.GetString(retVal) }

Este es mi procedimiento de Java para descifrar la cadena:

private String decryptAuthorizationString(String authString, String password) { try { //Force the test string authString = "c1W2YO1vYQzu6czteEidrG0U4g5gT4h57vAlP7tdjcY="; //Force the test password password = "GAT"; //Create the password and initial vector bytes byte[] passwordBytes= new byte[32]; byte[] b= password.getBytes("UTF-8"); int len= b.length; if (len > passwordBytes.length) len = passwordBytes.length; System.arraycopy(b, 0, passwordBytes, 0, len); byte[] ivBytes= new byte[16]; System.arraycopy(passwordBytes, 0, ivBytes, 0, 16); //Get the authString as byte[] byte[] authBytes = new BASE64Decoder().decodeBuffer(authString); InputStream inputStream = new ByteArrayInputStream(authBytes); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // If you have Bouncycastle library installed, you can use // Rijndael/CBC/PKCS7PADDING directly. Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS7PADDING", "BC"); // convertedSecureString and initVector must be byte[] with correct length cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(passwordBytes, "AES"), new IvParameterSpec(ivBytes)); CipherInputStream cryptoStream = new CipherInputStream(inputStream, cipher); byte[] buffer = new byte[1024]; len = cryptoStream.read(buffer, 0, buffer.length); while (len > 0) { outputStream.write(buffer, 0, len); len = cryptoStream.read(buffer, 0, buffer.length); } outputStream.flush(); cryptoStream.close(); String resStr = outputStream.toString("UTF-8"); return resStr; //<<--- resStr must be "101714994" } catch (Throwable t) { } return null; }

El procedimiento se ejecuta sin ningún error pero el resultado no es el que necesito. Cualquier ayuda será muy apreciada.


No necesita el BouncyCastleProvider para esto, ya que AES ya está incluido en Java. Sin embargo, el relleno PKCS # 7 está incorrectamente indicado por "PKCS5Padding" , por lo que "AES/CBC/PKCS7Padding" no se puede indicar sin Bouncy Castle.

La codificación Unicode predeterminada de .NET es en realidad más compatible con UTF-16LE. Deja que Microsoft no se quede con los nombres estándar (aunque es posible que lo hayan precedido).

Java JCE no se basa realmente en la transmisión como las clases C #, por lo que es mejor evitar la transmisión por completo.

He reescrito tu código de muestra para mostrar cómo codificarlo correctamente en Java (sin embargo, necesitarás ser compatible con Java 7). No coloque excepciones debajo de la tabla, AssertError en AssertError o RuntimeException .

He usado el descodificador Bouncy Castle Base 64, ya que ese fue el disponible tanto para ti como para mí (pero por lo demás esto es independiente de Bouncy). Java 8 tiene una clase base 64 incluida.

Así que sin más preámbulos:

import static java.nio.charset.StandardCharsets.UTF_16LE; import java.security.GeneralSecurityException; import java.util.Arrays; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.util.encoders.Base64; public class AuthenticationStringDecrypter { private static final String AES_CBC_PKCS5PADDING = "AES/CBC/PKCS5PADDING"; private static final int KEY_SIZE = 256; public static void main(final String[] args) throws Exception { System.out.println(decryptAuthorizationString( "c1W2YO1vYQzu6czteEidrG0U4g5gT4h57vAlP7tdjcY=", "GAT")); } private static String decryptAuthorizationString(final String authString, final String password) { try { // --- check if AES-256 is available if (Cipher.getMaxAllowedKeyLength(AES_CBC_PKCS5PADDING) < KEY_SIZE) { throw new IllegalStateException("Unlimited crypto files not present in this JRE"); } // --- create cipher final Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING); // --- create the key and initial vector bytes final byte[] passwordEncoded = password.getBytes(UTF_16LE); final byte[] keyData = Arrays.copyOf(passwordEncoded, KEY_SIZE / Byte.SIZE); final byte[] ivBytes = Arrays.copyOf(keyData, cipher.getBlockSize()); // --- init cipher cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyData, "AES"), new IvParameterSpec(ivBytes)); // --- decode & decrypt authentication string final byte[] authBytes = Base64.decode(authString); final byte[] decryptedData = cipher.doFinal(authBytes); // WARNING: may still decrypt to wrong string if // authString or password are incorrect - // BadPaddingException may *not* be thrown return new String(decryptedData, UTF_16LE); } catch (BadPaddingException | IllegalBlockSizeException e) { // failure to authenticate return null; } catch (final GeneralSecurityException e) { throw new IllegalStateException( "Algorithms or unlimited crypto files not available", e); } } }