Question

S'il vous plaît, ne me demandez pas pourquoi. Je viens d'avoir ce code dans .NET qui chiffre / déchiffre des chaînes de données. Je dois maintenant faire «exactement» la même fonctionnalité en Java. J'ai essayé plusieurs exemples pour DESede crypt, mais aucun d'eux ne donne les mêmes résultats que cette classe en .net.

J’ai bien voulu faire un webserbvice .net derrière ssl pour servir ces deux méthodes écrites en .net mais c’est trop bête de le faire sans avoir épuisé toutes les possibilités.

Peut-être que certains d'entre vous qui êtes plus java et qui sont plus liés dans la région auront sur la tête comment le faire.

Merci !!!

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());
  }
}

Entrée / sortie 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"
Était-ce utile?

La solution

Le code suit, mais d’abord quelques notes.

  1. Un vecteur d'initialisation différent doit être choisi pour chaque message. Coder en dur le vecteur d’initialisation n’a pas de sens. Le vecteur d'initialisation doit être envoyé avec le texte chiffré au destinataire du message (ce n'est pas secret).
  2. J'ai utilisé ma propre classe d'utilitaires pour l'encodage en base 64. Vous pouvez également utiliser sun.misc.BASE64Encoder et sun.misc.BASE64Decoder , utilisez une bibliothèque tierce telle que BouncyCastle ou écrivez la vôtre.
  3. Vous utilisez un triple DES à 2 clés, où la première et la troisième clé sont identiques. J'ai modifié sharedkey pour refléter cela, car le chiffrement Java DESede nécessite toujours une clé de 192 bits; c'est au générateur de clé de gérer l'option de saisie.
  4. Un CBC IV n’a que 64 bits. J'ai utilisé uniquement les 64 premiers bits de sharedvector .

Cette classe devrait interagir avec la version 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");
  }

}

Sortie:

  

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

     

userNameHere: passwordHere

Autres conseils

Vous avez quelques problèmes,

  1. Votre clé doit comporter 24 octets si vous souhaitez générer les mêmes matériaux de clé sous .NET et Java.
  2. Le IV doit avoir une taille de bloc de 8 octets pour Triple DES.
  3. En Java, vous devez spécifier le mode et le remplissage par défaut, à savoir "DESede / CBC / NoPadding".

Une fois ces modifications apportées, vous devriez pouvoir les décrypter côté Java.

Vous êtes-vous assuré que le code .NET utilise le même remplissage que le code Java? Je ne vois aucun remplissage spécifié dans le code .NET, c'est pourquoi je demande.

Avez-vous la source du code Java, cela vous aidera à trouver des erreurs.

Essayez ce qui suit. Pour une utilisation réelle, je voudrais obtenir une bibliothèque base64 telle que le codec commons ou utiliser le codec fourni avec 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)));
    }

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top