Enkripsi / dekripsi Android menggunakan AES [ditutup]


105

Apakah ada contoh yang baik tentang cara mengenkripsi dan mendekripsi gambar dan file lain dengan AES di Android?


7
Enkripsi di Android pada dasarnya tidak berbeda dengan di platform Java SE lainnya. Dan karena semua jawaban di bawah ini tidak aman, karena Anda harus memahami kriptografi sebelum mulai menerapkan atau meminjam contoh kriptografi.
Maarten Bodewes

4
Anda harus mencoba github.com/facebook/conceal ini .
Nhat Dinh

Jawaban:


131

Peringatan: Jawaban ini berisi kode yang tidak boleh Anda gunakan karena tidak aman (menggunakan SHA1PRNG untuk derivasi kunci dan menggunakan AES dalam mode ECB)

Sebagai gantinya (mulai 2016), gunakan PBKDF2WithHmacSHA1 untuk derivasi kunci dan AES dalam mode CBC atau GCM (GCM memberikan privasi dan integritas)

Anda bisa menggunakan fungsi seperti ini:

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

Dan panggil mereka seperti ini:

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

Ini harus berfungsi, saya menggunakan kode serupa dalam sebuah proyek sekarang.


9
Hei ini tidak berhasil untuk saya, saya mendapatkan pengecualian Badpadding saat mendekripsi hal yang sama.
Sanat Pandey

34
PERINGATAN Kode ini menggunakan kode buruk yang diketahui dari cuplikan Android untuk derivasi kunci. Jangan gunakan kecuali Anda ingin kehilangan data Anda. RNG unggulan bukanlah Key Derivation Function (KDF) yang baik.
Maarten Bodewes

2
@IcedDante Silakan lihat pertanyaan ini .
Maarten Bodewes

35
PERINGATAN Kode ini mungkin default ke enkripsi mode ECB di sebagian besar platform. Menggunakan enkripsi mode ECB tidak aman untuk sebagian besar data, apalagi gambar. Temukan penguin !
Maarten Bodewes

10
@Maarten Bodewes Saya melihat peringatan Anda di semua tempat, di bawah banyak posting. Bisakah Anda memberikan solusi yang baik?
Yar

16

Seperti yang disebutkan oleh Nacho.L PBKDF2WithHmacSHA1, derivasi digunakan karena lebih aman.

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
Benar, derivasi ini jauh lebih baik. Tapi sekarang Anda menggunakan IV statis, garam statis, dan jumlah iterasi yang terlalu rendah. Jadi tanpa peringatan, hasilnya masih tidak aman. Crypto sulit untuk
diperbaiki

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
Kode di atas menampilkan BadPaddingException di Android 4.2
Brijesh Thakur

1
@BrijeshThakur - baca ini
t0mm13b

12
PERINGATAN Kode ini menggunakan kode buruk yang diketahui dari Snippet Android untuk derivasi kunci. Jangan gunakan kecuali Anda ingin kehilangan data Anda. RNG unggulan bukanlah Key Derivation Function (KDF) yang baik.
Maarten Bodewes

3
Informasi lebih lanjut di sini
Maarten Bodewes

9
PERINGATAN Kode ini mungkin default ke enkripsi mode ECB di sebagian besar platform. Menggunakan enkripsi mode ECB tidak aman untuk sebagian besar data, apalagi gambar. Temukan penguin !
Maarten Bodewes

9

Pertanyaan lama tapi saya mengupgrade jawaban yang mendukung Android sebelum dan posting 4.2 dan mempertimbangkan semua perubahan terbaru menurut blog pengembang Android

Ditambah saya meninggalkan contoh kerja di repo github saya .

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

Daripada menggunakan pustaka Apache Commons Codec, apakah ada kerugian menggunakan android.util.Base64.encode(bytes, Base64.DEFAULT)dan android.util.Base64.decode(decryptedData, Base64.DEFAULT)?
ban-geoengineering

2
PERINGATAN Kode ini menggunakan kode buruk yang diketahui dari Snippet Android untuk penurunan kunci. Jangan gunakan kecuali Anda ingin kehilangan data Anda. RNG unggulan bukanlah Key Derivation Function (KDF) yang baik. (mendesah).
Maarten Bodewes

1
@MaartenBodewes perubahan apa yang harus saya lakukan?
Ricardo

7

Jika Anda mengenkripsi file teks, maka tes / sampel berikut mungkin berguna. Itu melakukan hal berikut:

  1. Buat aliran byte,
  2. membungkusnya dengan enkripsi AES,
  3. bungkus selanjutnya dengan pemrosesan teks
  4. dan terakhir buffer itu

    // 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
PERINGATAN Kode ini menggunakan mekanisme derivasi kunci yang menggunakan decoding karakter default. Jangan gunakan ini kecuali Anda ingin mengalami masalah saat mendekripsi data Anda.
Maarten Bodewes

3
@owlstead, observasi yang bagus, alangkah baiknya jika Anda menyarankan perbaikan. Contoh di atas sekarang telah diperbarui untuk menentukan pengkodean karakter dalam getKey (). Koreksi lebih lanjut dipersilakan ...
SoloPilot

9
Maaf, saya kebanyakan membakar jawaban di sini, karena itu digunakan SecureRandomuntuk derivasi kunci. Jika Anda ingin tahu cara membuat cipher, periksa jawaban ericksons di sini . Jangan gunakan IV statis (untuk kunci yang sama), dan gunakan PBKDF2 untuk sandi -> konversi kunci. Perhatikan bahwa cipher yang tidak diautentikasi hanya memberikan kerahasiaan, dan hanya jika tidak digunakan dalam protokol transport. Jika Anda ingin membantu, Anda juga dapat membakar jawaban lain (dan pilih komentar saya di sana) :)
Maarten Bodewes

@MaartenBodewes Anda "membakar" banyak jawaban, tetapi Anda tidak mengajukan jawaban. Jika Anda memiliki jawaban yang benar, mengapa Anda tidak menulisnya di sini?
Dika

@Dika Saya rasa saya menunjukkan jawaban di atas. Harap diingat bahwa saya dengan margin yang sangat besar , orang yang memposting jawaban paling banyak pada kriptografi dan enkripsi. Juga perlu diingat bahwa saya agak menentang pustaka pembungkus generik yang hanya mengarahkan orang untuk menyalin kode daripada menulis kode sendiri untuk kasus penggunaan tertentu. Java crypto API dipikirkan dengan baik, jika sedikit rumit. Gunakan itu! Tidak ada yang istimewa tentang enkripsi gambar; itu enkripsi file dasar.
Maarten Bodewes

5

AES mengenkripsi / mendekripsi di android

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

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

fungsi enkripsi

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

fungsi dekripsi

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 mengenkripsi / mendekripsi di c #

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

            Console.ReadKey();
        }

fungsi enkripsi

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

fungsi dekripsi

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

buat md5

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

1
MD5 bukan hash sandi atau Fungsi Penurunan Kunci Berbasis Sandi. Jika Anda menggunakan kata sandi, gunakan dengan benar.
Maarten Bodewes

5

Untuk enkripsi / dekripsi AES / CBC / PKCS7, Cukup Salin dan tempel kode berikut dan ganti SecretKeydan IVdengan milik Anda.

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

Apakah Anda menambahkan fungsi yang dapat menyandikan file? Jenis pengembalian akan menjadi byte []
Paritosh

1
Anda hanya perlu memanggil fungsi-fungsi ini dengan nama kelas. misalnya. CryptoHandler.encrypt ("STRING ANDA yang ingin Anda enkripsi") dan yang sama seperti ini, Anda juga dapat memanggil decrypt (). Dan kedua fungsi tersebut mengembalikan String.
Sujeet Kumar Gupta

2
Peringatan Kunci bukanlah string, kunci dan IV tidak boleh "dipilih" oleh pengguna. Sebuah IV harus tidak dapat diprediksi (tidak dapat dibedakan dari acak) menjadi musuh CBC untuk diamankan. Upaya gagal lainnya, Anda lebih dari # 10 untuk tidak mendapatkan kriptografi dan masih bersedia memberikan "contoh". Ini adalah jawaban hanya kode juga, tidak menjelaskan jenis keamanan yang diberikannya.
Maarten Bodewes

2

API sederhana untuk melakukan enkripsi AES di Android. Ini adalah mitra Android untuk pustaka AESCrypt Ruby dan Obj-C (dengan default yang sama):

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


7
Bisakah Anda menjelaskan sedikit bagaimana pustaka ini dapat digunakan untuk memecahkan masalah? Hanya menyalin deskripsi GitHub dan menambahkan tautan ke sana tidak terlalu membantu, dan jawaban Anda bisa jauh lebih baik dengan beberapa penjelasan.
JonasCz

1

Berikut adalah potongan kode sederhana yang berfungsi untuk Enkripsi dan Dekripsi AES.

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

Sekarang , telepon encryptMessage()ataudecryptMessage() untuk AESOperasi yang diinginkan dengan parameter yang diperlukan.

Juga , tangani pengecualian selama AESoperasi.

Semoga membantu ...


1
Garam statis dan IV tidak aman.
Maarten Bodewes

0

Untuk menambahkan kastil goyang ke proyek Android: https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16/1.45

Tambahkan baris ini di Aktivitas Utama Anda:

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


Saya tidak berpikir Anda membutuhkan Bouncy untuk ini; ini hanya akan memastikan bahwa Anda tidak dapat menggunakan akselerasi perangkat keras dan mematikan kinerja untuk file besar (seperti gambar). Mengkodekan kunci dalam basis 64 adalah ide yang buruk; menyimpannya di penyimpanan kunci jauh lebih baik.
Maarten Bodewes

0

Coba dengan kode di bawah ini, ini berfungsi untuk saya.

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
Kode Crypto seharusnya tidak hanya berfungsi, itu harus aman. Dapatkah Anda menunjukkan jenis keamanan yang disediakan kode Anda (atau dalam kasus ini, tidak disediakan?)
Maarten Bodewes
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.