Domanda

Per favore, non chiedermi perché. Ho solo questo codice in .NET che crittografa / decodifica le stringhe di dati. Ora ho bisogno di rendere "esattamente" la stessa funzionalità in Java. Ho provato diversi esempi per DESede crypt, ma nessuno di questi fornisce gli stessi risultati di questa classe in .net.

Anche se ho creato un webserbvice .net dietro ssl per servire questi due metodi scritti in .net, ma è troppo stupido da fare senza esaurire tutte le possibilità.

Forse alcuni di voi java che sono più legati nell'area avranno in testa come farcela.

Grazie !!!

public class Encryption
{
  private static byte[] sharedkey = {...};
  private static byte[] sharedvector = {...};

  public static String Decrypt(String val)
  {
    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    byte[] toDecrypt = Convert.FromBase64String(val);
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, tdes.CreateDecryptor( sharedkey, sharedvector ), CryptoStreamMode.Write);

    cs.Write(toDecrypt, 0, toDecrypt.Length);
    cs.FlushFinalBlock();
    return Encoding.UTF8.GetString(ms.ToArray());
  }

  public static String Encrypt(String val)
  {
    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    byte[] toEncrypt = Encoding.UTF8.GetBytes(val);
    MemoryStream ms = new MemoryStream();
    CryptoStream cs = new CryptoStream(ms, tdes.CreateEncryptor( sharedkey, sharedvector ), CryptoStreamMode.Write);
    cs.Write(toEncrypt, 0, toEncrypt.Length);
    cs.FlushFinalBlock();
    return Convert.ToBase64String(ms.ToArray());
  }
}

Ingresso / uscita Samle

String plain = "userNameHere:passwordHere";
Console.WriteLine("plain: " + plain);


String encrypted = Encrypt(plain);
Console.WriteLine("encrypted: " + encrypted);
// "zQPZgQHpjxR+41Bc6+2Bvqo7+pQAxBBVN+0V1tRXcOc="

String decripted = Decrypt(encrypted);
Console.WriteLine("decripted: " + decripted); 
// "userNameHere:passwordHere"
È stato utile?

Soluzione

Segue il codice, ma prima alcune note.

  1. Un diverso vettore di inizializzazione deve essere scelto per ogni messaggio. La codifica definitiva del vettore di inizializzazione non ha senso. Il IV dovrebbe essere inviato insieme al testo cifrato al destinatario del messaggio (non è segreto).
  2. Ho usato la mia classe di utilità per la codifica base-64. Puoi usare sun.misc.BASE64Encoder e sun.misc.BASE64Decoder invece, usare una libreria di terze parti come BouncyCastle o scrivere la tua.
  3. Stai usando il DES triplo a 2 tasti, dove la prima chiave e la terza chiave sono uguali. Ho modificato sharedkey per riflettere questo, poiché il codice Java DESede richiede sempre una chiave a 192 bit; spetta al generatore di chiavi gestire l'opzione di codifica.
  4. Un CBC IV ha solo 64 bit. Ho usato solo i primi 64 bit di sharedvector .

Questa classe dovrebbe interagire con la versione C #.

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Encryption
{

  private static byte[] sharedkey = {
    0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11, 
    0x12, 0x11, 0x0D, 0x0B, 0x07, 0x02, 0x04, 0x08, 
    0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11
  };

  private static byte[] sharedvector = {
    0x01, 0x02, 0x03, 0x05, 0x07, 0x0B, 0x0D, 0x11
  };

  public static void main(String... argv)
    throws Exception
  {
    String plaintext = "userNameHere:passwordHere";
    String ciphertext = encrypt(plaintext);
    System.out.println(ciphertext);
    System.out.println(decrypt(ciphertext));
  }

  public static String encrypt(String plaintext)
    throws Exception
  {
    Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sharedkey, "DESede"), new IvParameterSpec(sharedvector));
    byte[] encrypted = c.doFinal(plaintext.getBytes("UTF-8"));
    return Base64.encode(encrypted);
  }

  public static String decrypt(String ciphertext)
    throws Exception
  {
    Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sharedkey, "DESede"), new IvParameterSpec(sharedvector));
    byte[] decrypted = c.doFinal(Base64.decode(ciphertext));
    return new String(decrypted, "UTF-8");
  }

}

Output:

  

zQPZgQHpjxR + 41Bc6 + 2Bvqo7 + pQAxBBVN + 0V1tRXcOc =

     

userNameHere: passwordHere

Altri suggerimenti

Hai qualche problema,

  1. La chiave deve essere di 24 byte se si desidera generare gli stessi materiali chiave su .NET e Java.
  2. L'IV deve avere una dimensione di blocco, che è di 8 byte per Triple DES.
  3. In Java, è necessario specificare la modalità e il riempimento predefiniti, che è " DESede / CBC / NoPadding " ;.

Dopo aver apportato queste modifiche, dovresti essere in grado di decrittografarlo sul lato Java.

Ti sei assicurato che il codice .NET usi lo stesso padding del codice Java? Non vedo alcun riempimento specificato nel codice .NET, ecco perché lo chiedo.

Ti capita di avere la fonte per il codice Java, ti aiuterà a trovare gli errori.

Prova quanto segue. Per un utilizzo effettivo, otterrei una libreria base64 come il codec comune o utilizzare il codec fornito con BouncyCastle

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;

public class Encryption {

    private static SecretKey sharedkey;
    private static byte [] sharedvector;

    static {
        int keySize = 168;
        int ivSize = 8;
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
            keyGenerator.init(keySize);
            sharedkey = keyGenerator.generateKey();

            sharedvector = new byte [ivSize];
            byte [] data = sharedkey.getEncoded();

            int half = ivSize / 2;
            System.arraycopy(data, data.length-half, sharedvector, 0, half);
            System.arraycopy(sharedvector, 0, sharedvector, half, half);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    public static void main(String [] args) throws Exception {
        System.out.println(Decrypt(Encrypt("Hello World")));

    }

    public static String Encrypt(String val) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, sharedkey, new IvParameterSpec(sharedvector));

        return new sun.misc.BASE64Encoder().encode(cipher.doFinal(val.getBytes()));
    }

    public static String Decrypt(String val) throws GeneralSecurityException, IOException {
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, sharedkey, new IvParameterSpec(sharedvector));

        return new String(cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(val)));
    }

}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top