AES Crittografia in Java e la Decrittografia in C#

Ciao ho Crittografato stringa Esadecimale e la Chiave che è stato crittografato utilizzando standard AES.
Codice:

        final String key = "=abcd!#Axd*G!pxP";
        final javax.crypto.spec.SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
        final javax.crypto.Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte [] encryptedValue = cipher.doFinal(input.getBytes());
        return new String(org.apache.commons.codec.binary.Hex.encodeHex(encryptedValue));

Ora cerco di decifrare utilizzando C#
Codice:

            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            //Assumed Mode and padding values.
            rijndaelCipher.Mode = CipherMode.ECB;
            rijndaelCipher.Padding = PaddingMode.None;

            //AssumedKeySize and BlockSize values.
            rijndaelCipher.KeySize = 0x80;
            rijndaelCipher.BlockSize = 0x80;
            //Convert Hex keys to byte Array.
            byte[] encryptedData = hexStringToByteArray(textToDecrypt);

            byte[] pwdBytes = Encoding.Unicode.GetBytes(key);
            byte[] keyBytes = new byte[0x10];
            int len = pwdBytes.Length;
            if (len > keyBytes.Length)
            {
                len = keyBytes.Length;
            }
            Array.Copy(pwdBytes, keyBytes, len);
            rijndaelCipher.Key = keyBytes;
            rijndaelCipher.IV = keyBytes;
            //Decrypt data
            byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
            str = Encoding.UTF8.GetString(plainText);

e

    static private byte[] HexToBytes(string str)
    {
        if (str.Length == 0 || str.Length % 2 != 0)
            return new byte[0];
        byte[] buffer = new byte[str.Length / 2];
        char c;
        for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)
        {
            //Convert first half of byte   
            c = str[sx];
            buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);
            //Convert second half of byte    
            c = str[++sx];
            buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));
        }
        return buffer;
    } 

ma l’uscita non è come previsto.
Si prega di segnalare dove sto andando di male?

OriginaleL’autore Test | 2011-03-14

4 Replies
  1. 8

    Del codice ha un grosso problema: Si sta mescolando le codifiche di caratteri!

    In Java si chiama key.getBytes(), senza argomenti. Questo metodo restituisce la codifica UTF-8 o CP1252/ISO 8859-1 dati a seconda del sistema operativo e il charset di default in Java.

    Su C# lato si utilizza Encoding.Unicode.GetBytes(key)“Unicode”.Net è un sinonimo di caratteri a doppio byte alias UTF-16 (Little-Endian). Quindi si utilizza una chiave diversa in C#.

    Si dovrebbe essere in grado di vedere la differenza confrontando il numero di byte in Java e C#:

    Java: "=abcd!#Axd*G!pxP".getBytes().length = 16

    C#: Encoding.Unicode.GetBytes("=abcd!#Axd*G!pxP").Length = 32

    Mi consiglia vivamente di utilizzare matrici di byte invece di Stringhe per la definizione di una chiave di crittografia.

    Aggiorna: un’Altra differenza è che l’impostazione di un vettore di inizializzazione (IV) in C# che non si fanno in Java. Come si utilizza BCE IV non dovrebbe essere usato, ma se si cambia la CBC, per esempio, questo fa una grande differenza.

    Ho saputo che Codifica utilizzata è: “ISO-8859-1” Così ho cambiato il valore di chiave di decrittografia logica: byte[] pwdBytes = System.Di testo.La codifica.GetEncoding(“ISO-8859-1”).GetBytes(chiave); ma ancora non funziona. Ho “Imbottitura non è valido e non può essere rimosso” eccezione.
    Hai cambiato il codice Java per Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); come Chris Thompson proposto?
    BCE dovrebbe essere utilizzato solo per la cifratura di chiavi e altri dati che possono essere considerati casuali, si prega di avvisare per utilizzare CBC e un diverso IV per ogni pezzo di dati cifrati con la stessa chiave. Probabilmente è più utile per specificare PKCS#5 imbottitura; senza imbottitura significa che la lunghezza dei dati codificati devono essere implicitamente noto.

    OriginaleL’autore Robert

  2. 4

    Avevo bisogno di qualcosa non solo per C#, ma anche Silverlight e Windows Phone 7 compatibile. E ho sicuramente malato di mancanza completa di esempi di qualcosa di accettabile, sia in Java e C# (e Base64).

    Codice non è niente di eccezionale, ma funziona. Non esitate a migliorare su di esso, come ho contrassegnato questo come comunità wiki, ma assicurarsi di verificare, prima di inoltrare qualsiasi tipo di modifiche.

    Ecco il codice C#:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Security.Cryptography;
    using System.IO;
    //Author: Doguhan Uluca
    //Website: www.deceivingarts.com
    
    namespace DeceivingArts.Common
    {
        public class Encryptor
        {
            private string _seed = "";
    
            public Encryptor(string seed)
            {
            _seed = seed;
            }
    
            public string Encrypt<TSymmetricAlgorithm>(string input) where TSymmetricAlgorithm : SymmetricAlgorithm, new()
            {
                var pwdBytes = Encoding.UTF8.GetBytes(_seed);
                using(TSymmetricAlgorithm sa = new TSymmetricAlgorithm())
                {
                    ICryptoTransform saEnc = sa.CreateEncryptor(pwdBytes, pwdBytes);
    
                    var encBytes = Encoding.UTF8.GetBytes(input);
    
                    var resultBytes = saEnc.TransformFinalBlock(encBytes, 0, encBytes.Length);
    
                    return Convert.ToBase64String(resultBytes);
                }
            }
    
            public string Decrypt<TSymmetricAlgorithm>(string input) where TSymmetricAlgorithm : SymmetricAlgorithm, new()
            {
                var pwdBytes = Encoding.UTF8.GetBytes(_seed);
                using(TSymmetricAlgorithm sa = new TSymmetricAlgorithm())
                {
                    ICryptoTransform saDec = sa.CreateDecryptor(pwdBytes, pwdBytes);
    
                    var encBytes = Convert.FromBase64String(input);
    
                    var resultBytes = saDec.TransformFinalBlock(encBytes, 0, encBytes.Length);
                    return Encoding.UTF8.GetString(resultBytes);
                }
            }
        }
    }

    Ecco Android compatibile codice Java:

    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    /**
     * Usage:
     * <pre>
     * String crypto = SimpleCrypto.encrypt(masterpassword, cleartext)
     * ...
     * String cleartext = SimpleCrypto.decrypt(masterpassword, crypto)
     * </pre>
     * @author ferenc.hechler
     * @author Doguhan Uluca
     */
    public class Encryptor {
    
        public static String encrypt(String seed, String cleartext) throws Exception {
                byte[] rawKey = getRawKey(seed.getBytes());
                byte[] result = encrypt(rawKey, cleartext.getBytes());
                return toBase64(result);
        }
    
        public static String decrypt(String seed, String encrypted) throws Exception {
                byte[] rawKey = getRawKey(seed.getBytes());
                byte[] enc = fromBase64(encrypted);
                byte[] result = decrypt(rawKey, enc);
                return new String(result);
        }
    
        private static byte[] getRawKey(byte[] seed) throws Exception {
            SecretKey skey = new SecretKeySpec(seed, "AES");
    
            byte[] raw = skey.getEncoded();
    
            return raw;
        }
    
        private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(raw);
    
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec);
            byte[] encrypted = cipher.doFinal(clear);
            return encrypted;
        }
    
        private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(raw);
    
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
            byte[] decrypted = cipher.doFinal(encrypted);
            return decrypted;
        }
    
        public static String toBase64(byte[] buf)
        {
            return Base64.encodeBytes(buf);
        }
    
        public static byte[] fromBase64(String str) throws Exception
        {
            return Base64.decode(str);
        }
    }

    Per il Base64 di conversione, si prega di vedere l’eccellente attuazione a http://iharder.net/base64.

    Spero che questo salva le persone ore.

    -1 per essere cattivo crypto 1) utilizzando la strana terminologia, seed la password 2) si utilizza la password come IV. Non che. Avete bisogno di un nuovo casuale IV per la crittografia. 3) Si utilizza una password direttamente chiave, senza un’adeguata KDF 4) manca l’autenticazione => vulnerabile a imbottitura oracoli
    Grazie per l’ottimo feedback. Io non sono un crypto esperto. Siete la maggior parte del benvenuto per modificare la risposta e l’aggiornamento del codice per adattare le norme di buon crypto – sono sicuro che piacerebbe aiutare la comunità a un sacco.
    Esattamente come hai usato/call the Encrypt<TSymmetricAlgorithm>(string input)..... metodo in C#. Ho provato ad utilizzare Decrypt5<TSymmetricAlgorithm>("myEncryptedStringxyzabcblahblah"); ma mi dava un errore. Dicendo che non posso usare una classe astratta. Mi chiede di sbagliato? Ciò che non è una classe astratta che posso utilizzare? Grazie.
    deve essere di tipo SymmetricAlgorithm e concreta attuazione. Ecco la documentazione relativa pagina: msdn.microsoft.com/en-us/library/… Ecco la concreta tipi che implementano: Sistema.Di sicurezza.Crittografia.Aes, Sistema.Di sicurezza.Crittografia.DES, Sistema.Di sicurezza.Crittografia.RC2, Sistema.Di sicurezza.Crittografia.Rijndael, Sistema.Di sicurezza.Crittografia.TripleDES. In modo che una chiamata di esempio sarebbe come Encrypt<System.Security.Cryptography.TripleDES>('your input').

    OriginaleL’autore

  3. 2

    Provare questa combinazione:

    aesAlg.Mode = CipherMode.ECB;   
    aesAlg.Padding = PaddingMode.PKCS7;   
    //aesAlg.IV; - use default (not assign)   

    OriginaleL’autore Alf

  4. 0

    Ho il sospetto che l’errore è che non specifica di un riempimento o la modalità di funzionamento in Java lato di questa equazione. Io non sono sicuro di quello che in Java AES implementazione di default, ma vorrei iniziare, specificando sia quando si ottiene la cifra. Per esempio:

    Cipher.getInstance("<algorithm>/<mode of operation>/<padding>");

    Devi cercare supportati imbottitura schemi e le modalità di funzionamento per AES in Java e quindi assicurarsi che si configura il codice C# per utilizzare la stessa configurazione.

    Ho provato con tutte le possibili combinazioni di Modalità e imbottitura. ma non funziona. Anche provato a chiamare la Sicurezza.getProvider(“SunJCE); per conoscere la modalità di default e imbottitura, non è sicuro che kery posso ottenere le informazioni relative alla modalità predefinita e imbottitura usata in Java AES. tuttavia la crittografia e la decrittografia logica scritto in java funziona con questo tipo di crittografia. Ma quando cerco di decifrare in C# con il codice fornito, sono in grado di decifrare la stringa.

    OriginaleL’autore Chris Thompson

Lascia un commento