SORU
24 Aralık 2011, CUMARTESİ


En iyi Android AES şifreleme kullanarak uygulamalar nelerdir?

Neden ben bunu soruyorum:

Hatta Android için AES şifreleme ile ilgili sorular, bir sürü olduğunu biliyorum. Ve eğer Web arama varsa kod parçacıkları vardır. Ama her soru Yığın Taşması her sayfasında, büyük farklılıkları olan başka bir uygulama buldum.

Bu soruyu bulmak için yarattım "en iyi uygulama". En önemli gereksinimleri listesini toplamak ve gerçekten güvenli bir uygulama kurabiliriz umarım!

Hakkında başlatma vektörler ve tuzları okudum. Tüm uygulamaları ben bu özellikleri buldu. Bu yüzden ihtiyacınız var mı? Güvenlik çok artar? Bunu nasıl uygulamak mı? Algoritma şifreli veri çözülemez eğer özel durumlar oluşturmak gerekir? Yoksa sadece okunamayan bir dize döndürmesi gerekir güvensiz mi? Algoritma kullanmak yerine Bcrypt SHA?

Ne buldum bu iki uygulamalar hakkında? İyi mi? Mükemmel ya da bazı önemli şeyler eksik? Peki bu güvenli mi?

Algoritma bir dize ve "parola" parola ile dize şifrelemek için şifreleme ve sonra. düşecektir. Çıktı bir dize (onaltılık veya base64?) yine. Şifre çözme de olabilir, elbette olmalıdır.

Android için mükemmel AES uygulaması nedir?

Uygulama #1:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
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 AdvancedCrypto implements ICrypto {

        public static final String PROVIDER = "BC";
        public static final int SALT_LENGTH = 20;
        public static final int IV_LENGTH = 16;
        public static final int PBE_ITERATION_COUNT = 100;

        private static final String RANDOM_ALGORITHM = "SHA1PRNG";
        private static final String HASH_ALGORITHM = "SHA-512";
        private static final String PBE_ALGORITHM = "PBEWithSHA256And256BitAES-CBC-BC";
        private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
        private static final String SECRET_KEY_ALGORITHM = "AES";

        public String encrypt(SecretKey secret, String cleartext) throws CryptoException {
                try {

                        byte[] iv = generateIv();
                        String ivHex = HexEncoder.toHex(iv);
                        IvParameterSpec ivspec = new IvParameterSpec(iv);

                        Cipher encryptionCipher = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER);
                        encryptionCipher.init(Cipher.ENCRYPT_MODE, secret, ivspec);
                        byte[] encryptedText = encryptionCipher.doFinal(cleartext.getBytes("UTF-8"));
                        String encryptedHex = HexEncoder.toHex(encryptedText);

                        return ivHex   encryptedHex;

                } catch (Exception e) {
                        throw new CryptoException("Unable to encrypt", e);
                }
        }

        public String decrypt(SecretKey secret, String encrypted) throws CryptoException {
                try {
                        Cipher decryptionCipher = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER);
                        String ivHex = encrypted.substring(0, IV_LENGTH * 2);
                        String encryptedHex = encrypted.substring(IV_LENGTH * 2);
                        IvParameterSpec ivspec = new IvParameterSpec(HexEncoder.toByte(ivHex));
                        decryptionCipher.init(Cipher.DECRYPT_MODE, secret, ivspec);
                        byte[] decryptedText = decryptionCipher.doFinal(HexEncoder.toByte(encryptedHex));
                        String decrypted = new String(decryptedText, "UTF-8");
                        return decrypted;
                } catch (Exception e) {
                        throw new CryptoException("Unable to decrypt", e);
                }
        }

        public SecretKey getSecretKey(String password, String salt) throws CryptoException {
                try {
                        PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), HexEncoder.toByte(salt), PBE_ITERATION_COUNT, 256);
                        SecretKeyFactory factory = SecretKeyFactory.getInstance(PBE_ALGORITHM, PROVIDER);
                        SecretKey tmp = factory.generateSecret(pbeKeySpec);
                        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), SECRET_KEY_ALGORITHM);
                        return secret;
                } catch (Exception e) {
                        throw new CryptoException("Unable to get secret key", e);
                }
        }

        public String getHash(String password, String salt) throws CryptoException {
                try {
                        String input = password   salt;
                        MessageDigest md = MessageDigest.getInstance(HASH_ALGORITHM, PROVIDER);
                        byte[] out = md.digest(input.getBytes("UTF-8"));
                        return HexEncoder.toHex(out);
                } catch (Exception e) {
                        throw new CryptoException("Unable to get hash", e);
                }
        }

        public String generateSalt() throws CryptoException {
                try {
                        SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);
                        byte[] salt = new byte[SALT_LENGTH];
                        random.nextBytes(salt);
                        String saltHex = HexEncoder.toHex(salt);
                        return saltHex;
                } catch (Exception e) {
                        throw new CryptoException("Unable to generate salt", e);
                }
        }

        private byte[] generateIv() throws NoSuchAlgorithmException, NoSuchProviderException {
                SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);
                byte[] iv = new byte[IV_LENGTH];
                random.nextBytes(iv);
                return iv;
        }

}

Kaynak: http://pocket-for-android.1047292.n5.nabble.com/Encryption-method-and-reading-the-Dropbox-backup-td4344194.html

Uygulama #2:

import java.security.SecureRandom;

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

/**
 * Usage:
 * <pre>
 * String crypto = SimpleCrypto.encrypt(masterpassword, cleartext)
 * ...
 * String cleartext = SimpleCrypto.decrypt(masterpassword, crypto)
 * </pre>
 * @author ferenc.hechler
 */
public class SimpleCrypto {

    public static String encrypt(String seed, String cleartext) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] result = encrypt(rawKey, cleartext.getBytes());
        return toHex(result);
    }

    public static String decrypt(String seed, String encrypted) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed(seed);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        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");
        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;
    }

    public static String toHex(String txt) {
        return toHex(txt.getBytes());
    }
    public static String fromHex(String hex) {
        return new String(toByte(hex));
    }

    public static byte[] toByte(String hexString) {
        int len = hexString.length()/2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i  )
            result[i] = Integer.valueOf(hexString.substring(2*i, 2*i 2), 16).byteValue();
        return result;
    }

    public static String toHex(byte[] buf) {
        if (buf == null)
            return "";
        StringBuffer result = new StringBuffer(2*buf.length);
        for (int i = 0; i < buf.length; i  ) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }
    private final static String HEX = "0123456789ABCDEF";
    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
    }

}

Kaynak: http://www.tutorials-android.com/learn/How_to_encrypt_and_decrypt_strings.rhtml

CEVAP
30 Aralık 2011, Cuma


Anahtarları ve Karıştırır

Tuzları ile parola tabanlı bir sistemi tartışmaya başlayacak. Tuz, rastgele oluşturulmuş bir sayıdır. "Değildir". çıkarılabilir Uygulama 1 şifreleme açısından güçlü bir rasgele sayı üretir generateSalt() bir yöntem içerir. Tuz güvenliği için önemli olduğu için, bunu sadece bir kez oluşturulan gerekir rağmen oluşturulan, sonra gizli tutulmalıdır. Eğer bu bir Web sitesi, nispeten kolay tutmak için tuz sır, ama yüklü uygulamaları (masaüstü ve mobil aygıtlar), bu çok daha zor gibi uygulamaları kabul değil sır saklamanın.

Yöntemi getHash() verilen parola ve tuz, tek bir dize halinde birleştirilmiş bir karma döndürür. Kullanılan algoritma 512-bit bir karma döndüren SHA-512. Bu yöntem döndürür bir karma faydalı denetleme bir dize bütünlüğü, bu yüzden belki de kullanılan çağırarak getHash() sadece bir şifre ya da sadece bir tuz beri sadece birleştirir, her iki parametre.

getSecretKey() Diğer taraftan, bir parola ve tuz bir anahtar türetir yöntemi. Kullanılan algoritma hash fonksiyonu ve döner olarak SHA-256, 256-bit anahtar ile PKCS5 gelen PBKDF1 (sanırım). getSecretKey() oluşturduğu bir anahtar ile tekrar tekrar üreten sağlamalarının şifresini, tuz, ve bir zaman sayacı (yineleme sayısı verilen PBE_ITERATION_COUNT, burada 100) artırmak zaman gerekli mount bir kaba kuvvet saldırı. Tuz uzunluğu en az sürece anahtarı oluşturulan olarak, bu durumda, en az 256 bit olmalıdır. Yineleme sayısı mümkün olduğunca uzun süre gecikme neden olmadan ayarlanmalıdır. 1000 ya da daha fazla olmalı, eğer çok daha fazla sayıda gecikme nedeni değilse bile, kullanılmalıdır rağmen. Anahtar türetme tuz ve yineleme sayar hakkında daha fazla bilgi için, RFC2898 Bölüm 4'e bakın.

Java PBE uygulanması, ancak, eğer şifre Unicode karakterler içeriyorsa, bu fazla 8 bit gerektiren temsil edilmesi için kusurludur. PBEKeySpec, belirtildiği gibi "PBE mekanizması #5 AMAÇ da tanımlanan düşük sipariş her karakter 8 bit görünüyor". Bu soruna geçici bir çözüm bulmak için, onaltılık bir dize yalnızca 8-bit karakter içeren () 16-bit şifre karakter yaratma PBEKeySpec geçirmeden önce deneyebilirsiniz. Örneğin, "ABC" "004100420043" oluyor. Aslında, belki de kullanın bir karakter dizisi için bir parametre olarak şifre beri güvenlik nedeniyle, PBEKeySpec "istekleri şifre olarak bir karakter dizisi, yani geçersiz kılınabilir [clearPassword()] ne zaman bitti".

Şifreleme

Bir anahtar oluşturulur sonra, ve metin şifresini çözmek için kullanabiliriz. Uygulama 1, şifreleme algoritması kullanılan Şifreleme AES Blok şifreleme modu, dolgu tanımlanan ile Zincirleme#5 AMAÇ AES/CBC/PKCS5Padding. Bu algoritma, 128, 192 veya 256 bit son iki boyutları her zaman tüm uygulamalarda kullanılabilir durumda olmasa da anahtarları kabul eder.

AES aşağıdaki bazı birkaç şifre modları, destekler.

  • CBC bir şifreleme modu her blok düz metin kombine (XOR) ile önceki (şifrelenmiş) blok önce şifreleme ve ilk blok kombine (XOR) olarak adlandırılan bir başlatma vektörü (veya IV) önce şifreleme. Java uygulaması, rastgele bir IV oluşturulur (İvParameterSpec sınıfı ile) ve şifre metni başında yer. IV İV_LENGTH verilen 16 bayt (128 bit) uzunluğunda,. Bu tam olarak bir AES blok olarak aynı uzunlukta.
  • ECB modu (varsayılan AES modu) aynı bloklar aynı anahtar ile şifrelenmiş olacağından tavsiye edilmez. Bu kullanım Ugh yapmak diğer çoğu şifreleme modları için temel teşkil ediyor olsa hiç IV kullanarak eşdeğerdir.
  • Sayaç modu (TO), 16-bayt IV her bloktan sonra 1 tarafından artan bir sayaç. Her blok için, tezgahın şifrelenir ve kombine (XOR) bu bloğu ile şifreli metin veya düz metin üretmektir.
  • Galois counter mode (HGK) bütünlüğünü koruma sağlar, ancak tüm Java sürümleri, açık konuşmak gerekirse bir şifre yerine bir mod, tavsiye edilir bir "benzersiz" IV sağlamak için kendi güvenlik.

Eğer şifrelenmiş metin yabancılar için kullanılabilir, o zaman bir ileti uygulama yapılacak ise kimlik kodu, ya da MAC, şifreli veri (ve isteğe bağlı ek parametreler) bütünlüğünü korumak için tavsiye edilir. Popüler burada karma tabanlı SHA-1, SHA-256, veya diğer güvenli hash fonksiyonları tabanlı Mac'ler veya HMACs,. Eğer bir MAC kullanılır, ancak, kullanarak gizli bir işte en az iki kat daha uzun olarak normal bir şifreleme anahtarı tavsiye edilir, önlemek için ilgili anahtar saldırılar: ilk yarı servisi olarak şifreleme anahtarı ve ikinci yarı görür gibi anahtar MAC. (Yani, bu durumda, bir parola ve tuz tek bir sır oluşturmak ve iki gizli bölme.)

Java Uygulaması

Uygulama 1'de çeşitli fonksiyonları belirli bir sağlayıcı, yani kullanır"", BC algoritmaları için. Genel olarak, olsa da, belirli bir istek için tavsiye edilmez tüm sağlayıcılar tüm Java uygulamaları mevcut olduğundan sağlayıcıları, Introduction to Oracle Providersbkz. Böylece, PROVIDER bulunmamalıdır ve string -BC muhtemelen kaldırılmalıdır PBE_ALGORITHM. Uygulama 2 bu açıdan doğru değildir.

Bir yöntem için uygun olmayan tüm özel durumları yakalamak için değil de, sadece özel durumlar işlemek için olabilir. Çeşitli şifreleme sınıfları kontrol özel durumlar çeşitli atabilir. Bir yöntem CryptoException ile yalnızca kontrol istisnalar sarın, ya da bu kontrol özel durumları belirtmek için throws yan seçin. Kolaylık sağlamak için, CryptoException ile orijinal durum sarma potansiyel olarak çok var, çünkü burada, kontrol istisna sınıfları atabilir uygun olabilir.

getHash yöntemi artı tuz şifre UTF-8 sürümü karıştırır. Kullanılan olmayacak beri parola tabanlı şifreleme sistemi, daha fazla tartışmayacağım.

getSecretKey yöntem, ancak, generateSalt() döndü gibi parolayı char bir dizi ve hex-kodlanmış bir tuz, bir anahtar bir isimdir. Ben sadece PBEKeySpec ile söz konusu sorunlar nedeniyle, getSecretKey bir Dize yerine parola, char bir dizi geçmek zorunda tavsiye ederim geçici tercihen yukarıda bahsedilen. Herhangi bir sorun olsa da, temsil eden görmüyorum hex-kodlanmış bir dize olarak bir tuz.

encrypt decrypt yöntemleri düz metin UTF-8 kodlu bir sürüm kullanın ve hex-kodlanmış bir metne dön. Şifreleyici metin de olabilir base-64 (beri tam temsili gerekmez mi önemli olduğu sürece şifreli ve kullanılan aynı arada her iki encrypt decrypt) ama eğer kullandığınız bir MAC, tavsiye ederim uygulama MAC için şifreli mesajı bayt dizisi yerine, hex veya base-64 gösterimi.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Erica Griffin

    Erica Griffi

    8 HAZİRAN 2009
  • laptopmag

    laptopmag

    25 Ocak 2008
  • Shantanu Sood

    Shantanu Soo

    3 Kasım 2008