AES kullanarak Android şifreleme / şifre çözme [kapalı]


105

Android'de AES ile resim ve diğer dosyaların nasıl şifreleneceğine ve şifresinin çözüleceğine dair iyi bir örnek var mı ?


7
Android'de şifreleme, diğer Java SE platformlarından temelde farklı değildir. Ve aşağıdaki yanıtların tümü güvensiz olduğundan, kriptografi örneklerini uygulamaya veya ödünç almaya başlamadan önce kriptografiyi anlamanız gerekir.
Maarten Bodewes

Yanıtlar:


131

Uyarı: Bu yanıt, güvenli olmadığı için kullanmamanız gereken kodu içerir (anahtar türetme için SHA1PRNG'yi ve ECB modunda AES'yi kullanma)

Bunun yerine (2016 itibariyle), anahtar türetme için PBKDF2WithHmacSHA1 ve CBC veya GCM modunda AES kullanın (GCM hem gizlilik hem de bütünlük sağlar)

Bunun gibi işlevleri kullanabilirsiniz:

private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    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");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] decrypted = cipher.doFinal(encrypted);
    return decrypted;
}

Ve onları şu şekilde çağırın:

ByteArrayOutputStream baos = new ByteArrayOutputStream();  
bm.compress(Bitmap.CompressFormat.PNG, 100, baos); // bm is the bitmap object   
byte[] b = baos.toByteArray();  

byte[] keyStart = "this is a key".getBytes();
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();    

// encrypt
byte[] encryptedData = encrypt(key,b);
// decrypt
byte[] decryptedData = decrypt(key,encryptedData);

Bu işe yaramalı, şu anda bir projede benzer kod kullanıyorum.


9
Hey bu benim için çalışmıyor, aynı şifreyi çözerken Badpadding istisnası alıyorum.
Sanat Pandey

34
UYARI Bu kod, anahtar türetme için Android parçacıklarından bilinen bozuk kodu kullanıyor. Verilerinizi kaybetmek istemediğiniz sürece kullanmayın. Bir seri başı RNG olduğu değil iyi Tuş Derivasyon İşlevi (KDF).
Maarten Bodewes

2
@IcedDante Lütfen bu soruyu inceleyin .
Maarten Bodewes

35
UYARI Bu kod, çoğu platformda varsayılan olarak ECB modu şifrelemesine ayarlı olabilir. ECB modu şifrelemesini kullanmak, resimleri bırakın çoğu veri için güvenli değildir. Pengueni bulun !
Maarten Bodewes

10
@Maarten Bodewes Uyarılarınızı her yerde, manyt mesajlarının altında görüyorum. Bunun yerine lütfen iyi bir çözüm sunabilir misiniz?
Yar

17

Nacho.L tarafından belirtildiği gibi PBKDF2WithHmacSHA1 türevi daha güvenli olduğu için kullanılır.

import android.util.Base64;

import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

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

public class AESEncyption {

    private static final int pswdIterations = 10;
    private static final int keySize = 128;
    private static final String cypherInstance = "AES/CBC/PKCS5Padding";
    private static final String secretKeyInstance = "PBKDF2WithHmacSHA1";
    private static final String plainText = "sampleText";
    private static final String AESSalt = "exampleSalt";
    private static final String initializationVector = "8119745113154120";

    public static String encrypt(String textToEncrypt) throws Exception {

        SecretKeySpec skeySpec = new SecretKeySpec(getRaw(plainText, AESSalt), "AES");
        Cipher cipher = Cipher.getInstance(cypherInstance);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(initializationVector.getBytes()));
        byte[] encrypted = cipher.doFinal(textToEncrypt.getBytes());
        return Base64.encodeToString(encrypted, Base64.DEFAULT);
    }

    public static String decrypt(String textToDecrypt) throws Exception {

        byte[] encryted_bytes = Base64.decode(textToDecrypt, Base64.DEFAULT);
        SecretKeySpec skeySpec = new SecretKeySpec(getRaw(plainText, AESSalt), "AES");
        Cipher cipher = Cipher.getInstance(cypherInstance);
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(initializationVector.getBytes()));
        byte[] decrypted = cipher.doFinal(encryted_bytes);
        return new String(decrypted, "UTF-8");
    }

    private static byte[] getRaw(String plainText, String salt) {
        try {
            SecretKeyFactory factory = SecretKeyFactory.getInstance(secretKeyInstance);
            KeySpec spec = new PBEKeySpec(plainText.toCharArray(), salt.getBytes(), pswdIterations, keySize);
            return factory.generateSecret(spec).getEncoded();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

}

3
Doğru, bu türetme çok daha iyi. Ama şimdi statik bir IV, statik bir tuz ve çok düşük bir yineleme sayısı kullanıyorsunuz. Yani uyarmadan sonuç hala güvensiz. Kripto, doğru yapmak için bir acıdır ...
Maarten Bodewes

13
import java.security.AlgorithmParameters;
import java.security.SecureRandom;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

class SecurityUtils {

  private static final byte[] salt = { (byte) 0xA4, (byte) 0x0B, (byte) 0xC8,
      (byte) 0x34, (byte) 0xD6, (byte) 0x95, (byte) 0xF3, (byte) 0x13 };

  private static int BLOCKS = 128;

  public static byte[] encryptAES(String seed, String cleartext)
      throws Exception {
    byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
    SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    return cipher.doFinal(cleartext.getBytes("UTF8"));
  }

  public static byte[] decryptAES(String seed, byte[] data) throws Exception {
    byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
    SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    return cipher.doFinal(data);
  }

  private static byte[] getRawKey(byte[] seed) throws Exception {
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.setSeed(seed);
    kgen.init(BLOCKS, sr); // 192 and 256 bits may not be available
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();
    return raw;
  }

  private static byte[] pad(byte[] seed) {
    byte[] nseed = new byte[BLOCKS / 8];
    for (int i = 0; i < BLOCKS / 8; i++)
      nseed[i] = 0;
    for (int i = 0; i < seed.length; i++)
      nseed[i] = seed[i];

    return nseed;
  }

  public static byte[] encryptPBE(String password, String cleartext)
      throws Exception {
    SecretKeyFactory factory = SecretKeyFactory
        .getInstance("PBKDF2WithHmacSHA1");
    KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1024, 256);
    SecretKey tmp = factory.generateSecret(spec);
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, secret);
    AlgorithmParameters params = cipher.getParameters();
    byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
    return cipher.doFinal(cleartext.getBytes("UTF-8"));
  }

  public static String decryptPBE(SecretKey secret, String ciphertext,
      byte[] iv) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
    return new String(cipher.doFinal(ciphertext.getBytes()), "UTF-8");
  }

}

4
Yukarıdaki kod, Android 4.2'de BadPaddingException'ı atıyor
Brijesh Thakur

1
@BrijeshThakur - okumak bu
t0mm13b

12
UYARI Bu kod, anahtar türetme için Android Snippet'lerinden bilinen hatalı kodu kullanıyor. Verilerinizi kaybetmek istemediğiniz sürece kullanmayın. Bir seri başı RNG olduğu değil iyi Tuş Derivasyon İşlevi (KDF).
Maarten Bodewes

3
Daha fazla bilgi burada
Maarten Bodewes

9
UYARI Bu kod, çoğu platformda varsayılan olarak ECB modu şifrelemesine ayarlı olabilir. ECB modu şifrelemesini kullanmak, resimleri bırakın çoğu veri için güvenli değildir. Pengueni bulun !
Maarten Bodewes

9

Eski soru ancak Android'in önceki sürümlerini destekleyen yanıtları yükseltiyorum ve 4.2 yazıyorum ve Android geliştiricileri bloguna göre tüm son değişiklikleri göz önünde bulunduruyorum

Ayrıca github depomda çalışan bir örnek bırakıyorum .

import java.nio.charset.Charset;
import java.security.AlgorithmParameters;
import java.security.SecureRandom;

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

import org.apache.commons.codec.binary.Base64;


/*
* This software is provided 'as-is', without any express or implied
* warranty.  In no event will Google be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, as long as the origin is not misrepresented.
* 
* @author: Ricardo Champa
* 
*/

public class MyCipher {

    private final static String ALGORITHM = "AES";
    private String mySecret;

    public MyCipher(String mySecret){
        this.mySecret = mySecret;
    }

    public MyCipherData encryptUTF8(String data){
        try{
            byte[] bytes = data.toString().getBytes("utf-8");
            byte[] bytesBase64 = Base64.encodeBase64(bytes);
            return encrypt(bytesBase64);
        }
        catch(Exception e){
            MyLogs.show(e.getMessage());
            return null;
        }

    }

    public String decryptUTF8(byte[] encryptedData, IvParameterSpec iv){
        try {
            byte[] decryptedData = decrypt(encryptedData, iv);
            byte[] decodedBytes = Base64.decodeBase64(decryptedData);
            String restored_data = new String(decodedBytes, Charset.forName("UTF8"));
            return restored_data;
        } catch (Exception e) {
            MyLogs.show(e.getMessage());;
            return null;
        }
    }

    //AES
    private MyCipherData encrypt(byte[] raw, byte[] clear) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITHM);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        //solved using PRNGFixes class
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] data = cipher.doFinal(clear);

        AlgorithmParameters params = cipher.getParameters();
        byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
        return new MyCipherData(data, iv);
    }

    private byte[] decrypt(byte[] raw, byte[] encrypted, IvParameterSpec iv) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITHM);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    private byte[] getKey() throws Exception{
        byte[] keyStart = this.mySecret.getBytes("utf-8");
        KeyGenerator kgen = KeyGenerator.getInstance(ALGORITHM);

        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
        //      if (android.os.Build.VERSION.SDK_INT >= 17) {
        //          sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
        //      } else {
        //          sr = SecureRandom.getInstance("SHA1PRNG");
        //      }
        sr.setSeed(keyStart);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        byte[] key = skey.getEncoded();
        return key;

    }
    ////////////////////////////////////////////////////////////
    private MyCipherData encrypt(byte[] data) throws Exception{
        return encrypt(getKey(),data);
    }
    private byte[] decrypt(byte[] encryptedData, IvParameterSpec iv) throws Exception{
        return decrypt(getKey(),encryptedData, iv);
    }
}


@HammadTariqSahi? ¿
Ricardo

Aksine Apache Commons Codec kütüphane kullanmak yerine, kullanarak herhangi bir dezavantajı var android.util.Base64.encode(bytes, Base64.DEFAULT)ve android.util.Base64.decode(decryptedData, Base64.DEFAULT)?
ban-jeomühendislik

2
UYARI Bu kod, anahtar türetme için Android Snippet'lerinden bilinen hatalı kodu kullanıyor. Verilerinizi kaybetmek istemediğiniz sürece kullanmayın. Tohumlanmış bir RNG, iyi bir Anahtar Türetme Fonksiyonu (KDF) değildir. (iç çekmek).
Maarten Bodewes

1
@MaartenBodewes hangi değişiklikleri yapmalıyım?
Ricardo

7

Bir metin dosyasını şifreliyorsanız, aşağıdaki test / örnek faydalı olabilir. Aşağıdakileri yapar:

  1. Bir bayt akışı oluşturun,
  2. bunu AES şifrelemesiyle sarar,
  3. metin işlemeyle bir sonrakine sar
  4. ve son olarak onu tamponlar

    // AESdemo
    
    public class AESdemo extends Activity {
        boolean encryptionIsOn = true;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_aesdemo);
            // needs <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
            String homeDirName = Environment.getExternalStorageDirectory().getAbsolutePath() +
                    "/" + getPackageName();
            File file = new File(homeDirName, "test.txt");
            byte[] keyBytes = getKey("password");
    
            try {
                File dir = new File(homeDirName);
                if (!dir.exists())
                    dir.mkdirs();
                if (!file.exists())
                    file.createNewFile();
    
                OutputStreamWriter osw;
    
                if (encryptionIsOn) {
                    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
                    IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
                    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
    
                    FileOutputStream fos = new FileOutputStream(file);
                    CipherOutputStream cos = new CipherOutputStream(fos, cipher);
                    osw = new OutputStreamWriter(cos, "UTF-8");
                }
                else    // not encryptionIsOn
                    osw = new FileWriter(file);
    
                BufferedWriter out = new BufferedWriter(osw);
                out.write("This is a test\n");
                out.close();
            }
            catch (Exception e) {
                System.out.println("Encryption Exception "+e);
            }
    
            ///////////////////////////////////
            try {
                InputStreamReader isr;
    
                if (encryptionIsOn) {
                    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                    SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES");
                    IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes);
                    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
    
                    FileInputStream fis = new FileInputStream(file);
                    CipherInputStream cis = new CipherInputStream(fis, cipher);
                    isr = new InputStreamReader(cis, "UTF-8");
                }
                else
                    isr = new FileReader(file);
    
                BufferedReader in = new BufferedReader(isr);
                String line = in.readLine();
                System.out.println("Text read: <"+line+">");
                in.close();
            }
            catch (Exception e) {
                System.out.println("Decryption Exception "+e);
            }
        }
    
        private byte[] getKey(String password) throws UnsupportedEncodingException {
            String key = "";
            while (key.length() < 16)
                key += password;
            return key.substring(0, 16).getBytes("UTF-8");
        }
    }

8
UYARI Bu kod, varsayılan karakter kod çözme yöntemini kullanan bir anahtar türetme mekanizması kullanıyor. Verilerinizin şifresini çözerken sorun yaşamak istemiyorsanız bunu kullanmayın.
Maarten Bodewes

3
@owlstead, iyi bir gözlem, düzeltmeyi önermiş olsaydın güzel olurdu. Yukarıdaki örnek, getKey () 'de bir karakter kodlaması belirtecek şekilde güncellenmiştir. Daha fazla düzeltmeye açığız ...
SoloPilot

9
Üzgünüm, SecureRandomanahtar türetme için kullandıkları için çoğunlukla cevapları burada yakıyordum . Bir şifreyi nasıl başlatacağınızı öğrenmek istiyorsanız, ericksons'ın cevabını buradan kontrol edin . Statik IV (aynı anahtar için) kullanmayın ve parola -> anahtar dönüştürme için PBKDF2 kullanın. Kimliği doğrulanmamış bir şifrenin yalnızca gizlilik sağladığını ve yalnızca bir taşıma protokolünde kullanılmadığına dikkat edin. Yardım etmek istiyorsanız, diğer cevapları da yakabilirsiniz (ve yorumlarımı orada
oylayabilirsiniz

@MaartenBodewes birçok yanıtı "yaktınız", ancak bir yanıt önermiyorsunuz. Doğru cevabınız varsa, neden buraya bir tane yazmıyorsunuz?
Dika

@Dika Sanırım yukarıda bir cevaba işaret ettim. Lütfen hem kriptografi hem de şifreleme konusunda en çok cevabı gönderen kişinin çok büyük bir farkla olduğumu unutmayın . Ayrıca, belirli bir kullanım durumu için kendi başlarına kod yazmak yerine, insanları yalnızca kodu kopyalamaya yönlendiren genel sarmalayıcı kitaplıklarına karşı olduğumu unutmayın. Java kripto API'si biraz hantal olsa da oldukça iyi düşünülmüştür. Bunu kullan! Görüntü şifrelemenin özel bir yanı yoktur; temel dosya şifrelemesidir.
Maarten Bodewes

6

AES / CBC / PKCS7 şifreleme / şifre çözme için, Sadece aşağıdaki kodu kopyalayıp yapıştırın SecretKeyve IVkendinizinkiyle değiştirin .

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import android.util.Base64;


public class CryptoHandler {

    String SecretKey = "xxxxxxxxxxxxxxxxxxxx";
    String IV = "xxxxxxxxxxxxxxxx";

    private static CryptoHandler instance = null;

    public static CryptoHandler getInstance() {

        if (instance == null) {
            instance = new CryptoHandler();
        }
        return instance;
    }

    public String encrypt(String message) throws NoSuchAlgorithmException,
            NoSuchPaddingException, IllegalBlockSizeException,
            BadPaddingException, InvalidKeyException,
            UnsupportedEncodingException, InvalidAlgorithmParameterException {

        byte[] srcBuff = message.getBytes("UTF8");
        //here using substring because AES takes only 16 or 24 or 32 byte of key 
        SecretKeySpec skeySpec = new 
        SecretKeySpec(SecretKey.substring(0,32).getBytes(), "AES");
        IvParameterSpec ivSpec = new 
        IvParameterSpec(IV.substring(0,16).getBytes());
        Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        ecipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec);
        byte[] dstBuff = ecipher.doFinal(srcBuff);
        String base64 = Base64.encodeToString(dstBuff, Base64.DEFAULT);
        return base64;
    }

    public String decrypt(String encrypted) throws NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException,
            InvalidAlgorithmParameterException, IllegalBlockSizeException,
            BadPaddingException, UnsupportedEncodingException {

        SecretKeySpec skeySpec = new 
        SecretKeySpec(SecretKey.substring(0,32).getBytes(), "AES");
        IvParameterSpec ivSpec = new 
        IvParameterSpec(IV.substring(0,16).getBytes());
        Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        ecipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
        byte[] raw = Base64.decode(encrypted, Base64.DEFAULT);
        byte[] originalBytes = ecipher.doFinal(raw);
        String original = new String(originalBytes, "UTF8");
        return original;
    }
}

Dosyayı kodlayabilen işlev ekler misiniz? Dönüş türü bayt [] olacaktır
Paritosh

1
Bu işlevleri sınıf adına göre çağırmanız yeterlidir. Örneğin. CryptoHandler.encrypt ("Şifrelemek istediğiniz DİZİNİZ") ve bununla aynı şekilde decrypt () de çağırabilirsiniz. Ve her iki işlev de String değerini döndürür.
Sujeet Kumar Gupta

2
Uyarı Bir anahtar bir dizi, bir anahtar değildir ve IV kullanıcı tarafından "seçilmemelidir". CBC'nin güvende olması için bir IV, bir rakibe tahmin edilemez (rastgele olandan ayırt edilemez) olmalıdır. Başka bir başarısız girişim, kriptografi almamak için 10 numaranın üzerindesiniz ve yine de "bir örnek" sunmaya hazırsınız. Bu sadece bir kod cevabıdır, ne tür bir güvenlik sağladığını açıklamaz.
Maarten Bodewes

5

Android'de AES şifreleme / şifre çözme

String encData= encrypt("keykey".getBytes("UTF-16LE"), ("0123000000000215").getBytes("UTF-16LE"));

String decData= decrypt("keykey",Base64.decode(encData.getBytes("UTF-16LE"), Base64.DEFAULT));

şifreleme işlevi

private static String encrypt(byte[] key, byte[] clear) throws Exception
    {
        MessageDigest md = MessageDigest.getInstance("md5");
        byte[] digestOfPassword = md.digest(key);

        SecretKeySpec skeySpec = new SecretKeySpec(digestOfPassword, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(clear);
        return Base64.encodeToString(encrypted,Base64.DEFAULT);
    }

şifre çözme işlevi

private static String decrypt(String key, byte[] encrypted) throws Exception
    {
        MessageDigest md = MessageDigest.getInstance("md5");
        byte[] digestOfPassword = md.digest(key.getBytes("UTF-16LE"));

        SecretKeySpec skeySpec = new SecretKeySpec(digestOfPassword, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        return new String(decrypted, "UTF-16LE");
    }

AES c # ile şifreleme / şifre çözme

 static void Main(string[] args)
        {
            string enc = encryptAES("0123000000000215", "keykey");
            string dec = decryptAES(enc, "keykey");

            Console.ReadKey();
        }

şifreleme işlevi

 public static string encryptAES(string input, string key)
        {
            var plain = Encoding.Unicode.GetBytes(input);

            // 128 bits
            AesCryptoServiceProvider provider = new AesCryptoServiceProvider();
            provider.KeySize = 128;
            provider.Mode = CipherMode.ECB;
            provider.Padding = PaddingMode.PKCS7;

            provider.Key = CalculateMD5Hash(key);

            var enc = provider.CreateEncryptor().TransformFinalBlock(plain, 0, plain.Length);
            return Convert.ToBase64String(enc);
        }

şifre çözme işlevi

public static string decryptAES(string encryptText, string key)
{
    byte[] enc = Convert.FromBase64String(encryptText);
    // 128 bits
    AesCryptoServiceProvider provider = new AesCryptoServiceProvider();
    provider.KeySize = 128;
    provider.Mode = CipherMode.ECB;
    provider.Padding = PaddingMode.PKCS7;

    provider.Key = CalculateMD5Hash(key);


    var dec = provider.CreateDecryptor().TransformFinalBlock(enc, 0, enc.Length);
    return Encoding.Unicode.GetString(dec);
}

md5 oluştur

 public static byte[] CalculateMD5Hash(string input)
        {
            MD5 md5 = MD5.Create();
            byte[] inputBytes = Encoding.Unicode.GetBytes(input);
            return md5.ComputeHash(inputBytes);
        }

1
MD5 bir parola karması veya Parola Tabanlı Anahtar Türetme İşlevi değildir. Parola kullanıyorsanız, doğru kullanın.
Maarten Bodewes

2

Android'de AES şifreleme gerçekleştirmek için basit API. Bu, AESCrypt kitaplığı Ruby ve Obj-C'nin Android karşılığıdır (aynı varsayılanlarla):

https://github.com/scottyab/AESCrypt-Android


7
Bu kitaplığın sorunu çözmek için nasıl kullanılabileceğini biraz genişletebilir misiniz? Sadece GitHub açıklamasını kopyalamak ve ona bir bağlantı eklemek o kadar da yardımcı olmaz ve cevabınız bazı açıklamalarla çok daha iyi olabilir.
JonasCz - Monica'yı eski durumuna getir

1

İşte AES Şifreleme ve Şifre Çözme için çalışan basit kod parçacığı.

import android.util.Base64;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class AESEncryptionClass {

    private static String INIT_VECTOR_PARAM = "#####";
    private static String PASSWORD = "#####";
    private static String SALT_KEY = "#####";

    private static SecretKeySpec generateAESKey() throws NoSuchAlgorithmException, InvalidKeySpecException {

        // Prepare password and salt key.
        char[] password = new String(Base64.decode(PASSWORD, Base64.DEFAULT)).toCharArray();
        byte[] salt = new String(Base64.decode(SALT_KEY, Base64.DEFAULT)).getBytes(StandardCharsets.UTF_8);

        // Create object of  [Password Based Encryption Key Specification] with required iteration count and key length.
        KeySpec spec = new PBEKeySpec(password, salt, 64, 256);

        // Now create AES Key using required hashing algorithm.
        SecretKey key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(spec);

        // Get encoded bytes of secret key.
        byte[] bytesSecretKey = key.getEncoded();

        // Create specification for AES Key.
        SecretKeySpec secretKeySpec = new SecretKeySpec(bytesSecretKey, "AES");
        return secretKeySpec;
    }

    /**
     * Call this method to encrypt the readable plain text and get Base64 of encrypted bytes.
     */
    public static String encryptMessage(String message) throws BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException {

        byte[] initVectorParamBytes = new String(Base64.decode(INIT_VECTOR_PARAM, Base64.DEFAULT)).getBytes(StandardCharsets.UTF_8);

        Cipher encryptionCipherBlock = Cipher.getInstance("AES/CBC/PKCS5Padding");
        encryptionCipherBlock.init(Cipher.ENCRYPT_MODE, generateAESKey(), new IvParameterSpec(initVectorParamBytes));

        byte[] messageBytes = message.getBytes();
        byte[] cipherTextBytes = encryptionCipherBlock.doFinal(messageBytes);
        String encryptedText = Base64.encodeToString(cipherTextBytes, Base64.DEFAULT);
        return encryptedText;
    }

    /**
     * Call this method to decrypt the Base64 of encrypted message and get readable plain text.
     */
    public static String decryptMessage(String base64Cipher) throws BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException {

        byte[] initVectorParamBytes = new String(Base64.decode(INIT_VECTOR_PARAM, Base64.DEFAULT)).getBytes(StandardCharsets.UTF_8);

        Cipher decryptionCipherBlock = Cipher.getInstance("AES/CBC/PKCS5Padding");
        decryptionCipherBlock.init(Cipher.DECRYPT_MODE, generateAESKey(), new IvParameterSpec(initVectorParamBytes));

        byte[] cipherBytes = Base64.decode(base64Cipher, Base64.DEFAULT);
        byte[] messageBytes = decryptionCipherBlock.doFinal(cipherBytes);
        String plainText = new String(messageBytes);
        return plainText;
    }
}

Şimdi arayın encryptMessage()veya gerekli parametrelerle decryptMessage()istediğiniz AESİşlemi yapın.

AyrıcaAES işlemler sırasında istisnaları da ele alın .

Umarım yardımcı olmuştur ...


1
Statik tuz ve IV güvenli değildir.
Maarten Bodewes

0

Android projesine şişme kale eklemek için: https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16/1.45

Bu satırı Ana Aktivitenize ekleyin:

static {
    Security.addProvider(new BouncyCastleProvider());
}

public class AESHelper {

    private static final String TAG = "AESHelper";

    public static byte[] encrypt(byte[] data, String initVector, String key) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            Cipher c = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            SecretKeySpec k = new SecretKeySpec(Base64.decode(key, Base64.DEFAULT), "AES");
            c.init(Cipher.ENCRYPT_MODE, k, iv);
            return c.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static byte[] decrypt(byte[] data, String initVector, String key) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            Cipher c = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            SecretKeySpec k = new SecretKeySpec(Base64.decode(key, Base64.DEFAULT), "AES");
            c.init(Cipher.DECRYPT_MODE, k, iv);
            return c.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static String keyGenerator() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(192);

        return Base64.encodeToString(keyGenerator.generateKey().getEncoded(),
                Base64.DEFAULT);
    }
}


Bunun için Bouncy'e ihtiyacınız olduğunu sanmıyorum; yalnızca donanım hızlandırmayı kullanamayacağınızdan ve büyük dosyalar için (görüntüler gibi) performansı öldüremeyeceğinizden emin olur. Temel 64'te anahtarı kodlamak kötü bir fikirdir; bir anahtar deposunda saklamak çok daha iyidir.
Maarten Bodewes

0

Benim için çalışıyor aşağıdaki kodla deneyin.

public static String decrypt(String encrypted) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
    byte[] key = your Key in byte array;
    byte[] input = salt in byte array;

    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(input);
    Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    ecipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);

    byte[] raw = Base64.decode(encrypted, Base64.DEFAULT);
    byte[] originalBytes = ecipher.doFinal(raw);

    String original = new String(originalBytes, "UTF8");
    return original;
}

1
Kripto kodu sadece çalışmamalı, güvenli olmalıdır. Kodunuzun ne tür bir güvenlik sağladığını (veya bu durumda sağlamadığını)
belirtebilir
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.