অ্যান্ড্রয়েডে AES এনক্রিপশন ব্যবহার করার জন্য সেরা অনুশীলনগুলি কী কী?


90

কেন আমি এই প্রশ্ন জিজ্ঞাসা:

আমি জানি এএসডির এনক্রিপশন, এমনকি অ্যান্ড্রয়েডের জন্য প্রচুর প্রশ্ন রয়েছে। আপনি যদি ওয়েব অনুসন্ধান করেন তবে প্রচুর কোড স্নিপেট রয়েছে। তবে প্রতিটি একক পৃষ্ঠায়, প্রতিটি স্ট্যাক ওভারফ্লো প্রশ্নে, আমি বড় পার্থক্য সহ আরও একটি বাস্তবায়ন পাই।

সুতরাং আমি একটি "সেরা অনুশীলন" খুঁজতে এই প্রশ্নটি তৈরি করেছি। আমি আশা করি আমরা সবচেয়ে গুরুত্বপূর্ণ প্রয়োজনীয়তার একটি তালিকা সংগ্রহ করতে পারি এবং একটি বাস্তবায়ন সেট করতে পারি যা সত্যিই সুরক্ষিত!

আমি আরম্ভের ভেক্টর এবং সল্ট সম্পর্কে পড়ি। আমি যে সমস্ত বাস্তবায়ন পেয়েছি তার মধ্যে এই বৈশিষ্ট্যগুলি নেই। সুতরাং আপনি এটি প্রয়োজন? এটি কি সুরক্ষা অনেক বাড়ায়? আপনি কীভাবে এটি বাস্তবায়ন করবেন? যদি এনক্রিপ্ট করা ডেটা ডিক্রিপ্ট না করা যায় তবে অ্যালগরিদম ব্যতিক্রম বাড়াতে হবে? বা এটি যে অনিরাপদ এবং এটি কেবল একটি অপঠনযোগ্য স্ট্রিংটি ফেরত দেওয়া উচিত? অ্যালগরিদম কি SHA এর পরিবর্তে Bcrypt ব্যবহার করতে পারে?

এই দুটি বাস্তবায়ন সম্পর্কে আমি কী পেয়েছি? তারা ঠিক আছে? নিখুঁত বা কিছু গুরুত্বপূর্ণ জিনিস অনুপস্থিত? এর মধ্যে কী নিরাপদ?

অ্যালগরিদমের এনক্রিপশনের জন্য একটি স্ট্রিং এবং একটি "পাসওয়ার্ড" নেওয়া উচিত এবং তারপরে সেই পাসওয়ার্ড দিয়ে স্ট্রিংটি এনক্রিপ্ট করা উচিত। আউটপুটটি আবার একটি স্ট্রিং (হেক্স বা বেস 64?) হওয়া উচিত। ডিক্রিপশন অবশ্যই করা উচিত।

অ্যান্ড্রয়েডের জন্য নিখুঁত AES বাস্তবায়ন কী?

বাস্তবায়ন # 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;
        }

}

উত্স: http://pocket-for-android.1047292.n5.nabble.com এনক্রিপশন- মডেল- এবং- রিডিং-the- ড্রপবক্স- ব্যাকআপ-td4344194.html

বাস্তবায়ন # 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));
    }

}

সূত্র: http://www.tutorials-android.com/learn/How_to_encrypt_and_decrypt_strings.rhtml


আমি সমাধান 1 বাস্তবায়ন করার চেষ্টা করছি তবে এর জন্য কিছু শ্রেণির প্রয়োজন। আপনার কি সম্পূর্ণ উত্স কোড আছে?
albanx

4
না, দুঃখিত না। কিন্তু আমি এটা শুধু মুছে ফেলার মাধ্যমে কাজ পেয়েছিলাম implements ICryptoএবং পরিবর্তন throws CryptoExceptionকরার জন্য throws Exceptionইত্যাদি। সুতরাং আপনার আর এই ক্লাসগুলির প্রয়োজন হবে না।
কাওয়

তবে হেক্সএনকোডার ক্লাসটি কি অনুপস্থিত? আমি কোথায় এটি পেতে পারি?
albanx

আমার ধারণা, HexEncoder বাউন্সিস্টল লাইব্রেরির অংশ। আপনি এটি ডাউনলোড করতে পারেন। অথবা আপনি "বাইট [] থেকে হেক্স" এবং জাভাতে অন্য উপায়ে গুগল করতে পারেন।
কাওয়

আপনাকে ধন্যবাদ মার্কো কিন্তু আমি সেখানে 3 পদ্ধতি নোটিশ getSecretKey, getHash, generateSaltপ্রথম বাস্তবায়ন যে অব্যবহৃত হয়। হতে পারে আমি ভুল কিন্তু এই ক্লাসটি বাস্তবে কোনও স্ট্রিং এনক্রিপ্ট করার জন্য কীভাবে ব্যবহার করা যেতে পারে?
albanx

উত্তর:


37

আপনার প্রশ্নে যে বাস্তবায়ন আপনি দিয়েছেন তা সম্পূর্ণরূপে সঠিক নয় এবং আপনি প্রদত্ত বাস্তবায়ন যেমন হয় তেমন ব্যবহার করা উচিত নয়। এরপরে, আমি অ্যান্ড্রয়েডে পাসওয়ার্ড-ভিত্তিক এনক্রিপশনের দিকগুলি নিয়ে আলোচনা করব।

কী এবং হ্যাশ

আমি লবণের সাথে পাসওয়ার্ড-ভিত্তিক সিস্টেম নিয়ে আলোচনা শুরু করব। লবণ একটি এলোমেলোভাবে উত্পাদিত নম্বর। এটি "ছাড়" নয়। বাস্তবায়ন 1 এর মধ্যে একটি generateSalt()পদ্ধতি রয়েছে যা একটি ক্রিপ্টোগ্রাফিকভাবে শক্তিশালী এলোমেলো সংখ্যা উত্পন্ন করে। যেহেতু সুরক্ষার জন্য লবণ গুরুত্বপূর্ণ, এটি তৈরি হওয়ার পরে এটি গোপন রাখা উচিত, যদিও এটি কেবল একবার উত্পাদন করা দরকার। যদি এটি কোনও ওয়েব সাইট হয় তবে লবণ গোপন রাখা অপেক্ষাকৃত সহজ, তবে ইনস্টল থাকা অ্যাপ্লিকেশনগুলির জন্য (ডেস্কটপ এবং মোবাইল ডিভাইসের জন্য), এটি আরও অনেক কঠিন হবে।

পদ্ধতিটি getHash()প্রদত্ত পাসওয়ার্ড এবং লবণের একটি হ্যাশ প্রদান করে, একটি একক স্ট্রিংয়ে সংযুক্ত। ব্যবহৃত অ্যালগরিদমটি SHA-512, যা 512-বিট হ্যাশ দেয়। এই পদ্ধতিটি একটি হ্যাশ ফেরত দেয় যা স্ট্রিংয়ের অখণ্ডতা পরীক্ষা করার জন্য দরকারী, সুতরাং এটি getHash()কেবলমাত্র একটি পাসওয়ার্ড বা কেবল একটি লবণ দিয়ে কল করে ব্যবহার করা যেতে পারে , যেহেতু এটি উভয় পরামিতিগুলিকে কেবল সম্মতি দেয়। যেহেতু এই পদ্ধতিটি পাসওয়ার্ড-ভিত্তিক এনক্রিপশন সিস্টেমে ব্যবহৃত হবে না, তাই আমি এটি নিয়ে আরও আলোচনা করব না।

পদ্ধতিটি getSecretKey(), charপাসওয়ার্ডের একটি অ্যারের থেকে একটি কী এবং হেক্স-এনকোডযুক্ত লবণের উত্স থেকে আসে generateSalt()। ব্যবহৃত অ্যালগরিদম হ'ল ফ্যাশন হিসাবে SHA-256 সহ PKCS5 থেকে PBKDF1 (আমার মনে হয়), এবং একটি 256-বিট কী প্রদান করে returns ব্রুট-ফোর্স আক্রমণটি মাউন্ট করার জন্য প্রয়োজনীয় সময় বাড়ানোর জন্য getSecretKey()বারবার পাসওয়ার্ড, লবণ এবং একটি কাউন্টারের হ্যাশগুলি তৈরি করা হয়েছে ( PBE_ITERATION_COUNTএখানে দেওয়া পুনরাবৃত্তির গণনা অবধি 100)। কী তৈরি হওয়ার সময় লবণের দৈর্ঘ্য কমপক্ষে দীর্ঘ হওয়া উচিত, এক্ষেত্রে কমপক্ষে 256 বিট। অযৌক্তিক দেরি না করে পুনরাবৃত্তি গণনাটি যথাসম্ভব সেট করা উচিত। কী ডেরাইভেশনে সল্ট এবং পুনরাবৃত্তি গণনা সম্পর্কিত আরও তথ্যের জন্য, আরএফসি 2898 এর বিভাগ 4 দেখুন ।

জাভার পিবিইতে প্রয়োগকরণটি ত্রুটিযুক্ত তবে যদি পাসওয়ার্ডটিতে ইউনিকোডের অক্ষর থাকে, অর্থাৎ 8 টিরও বেশি বিট উপস্থাপনের প্রয়োজন হয়। যেমনটি বলা হয়েছে PBEKeySpec, "পিকেসিএস # 5 এ সংজ্ঞায়িত পিবিই প্রক্রিয়া প্রতিটি অক্ষরের শুধুমাত্র নিম্ন ক্রমের 8 টি বিট দেখায়"। এই সমস্যাটি সমাধান করার জন্য, আপনি পাসওয়ার্ডের আগে পাসওয়ার্ডের সমস্ত 16-বিট অক্ষরের একটি হেক্স স্ট্রিং (যা কেবলমাত্র 8-বিট অক্ষর ধারণ করে) তৈরি করার চেষ্টা করতে পারেন PBEKeySpec। উদাহরণস্বরূপ, "এবিসি" "004100420043" হয়ে যায়। এটিও নোট করুন যে পিবিইকিস্পিপ "পাসওয়ার্ডটিকে চর অ্যারে হিসাবে অনুরোধ করে, তাই এটি clearPassword()সম্পন্ন হলে [সাথে ] ওভাররাইট করা যায়"। ("স্মৃতিতে স্ট্রিং সুরক্ষার জন্য" এই প্রশ্নটি দেখুন )) আমি কোনও সমস্যা দেখি না, যদিও,

জোড়া লাগানো

একটি কী তৈরি হয়ে গেলে, আমরা এটি এনক্রিপ্ট করতে এবং পাঠ্য ডিক্রিপ্ট করতে ব্যবহার করতে পারি।

বাস্তবায়ন 1-এ, সিফার অ্যালগরিদম ব্যবহৃত হয় AES/CBC/PKCS5Padding, এটি হল সিফার ব্লক চেইনিং (সিবিসি) সাইফার মোডে পিসিএস # 5-এ সংজ্ঞায়িত প্যাডিং সহ এইএস। (অন্যান্য হবে AES সাইফার মোড কাউন্টার মোড (CTR এর), ইলেকট্রনিক codebook মোড (ইসিবি), এবং গালোইস কাউন্টার মোড (জিসিএম) অন্তর্ভুক্ত। স্ট্যাক ওভারফ্লো অন্য একটি প্রশ্ন উত্তরগুলি বিস্তারিতভাবে আলোচনা বিভিন্ন হবে AES সাইফার মোড এবং ব্যবহার করা বাঞ্ছনীয় বেশী ধারণ করে। এছাড়াও সচেতন থাকুন যে সিবিসি মোড এনক্রিপশনটিতে বেশ কয়েকটি আক্রমণ রয়েছে, যার কয়েকটি আরএফসি 7457-এ উল্লিখিত হয়েছে।)

নোট করুন যে আপনার একটি এনক্রিপশন মোড ব্যবহার করা উচিত যা অখণ্ডতার জন্য এনক্রিপ্ট হওয়া ডেটাও পরীক্ষা করে (উদাহরণস্বরূপ, আরএফসি 5116-এ বর্ণিত সম্পর্কিত ডেটা , এইএডি, সহ অনুমোদিত এনক্রিপশন )। তবে, AES/CBC/PKCS5Paddingঅখণ্ডতা যাচাই করে না, তাই এটি একা বাঞ্ছনীয় নয় । এইএডি উদ্দেশ্যে, সম্পর্কিত কী আক্রমণগুলি এড়ানোর জন্য একটি সাধারণ এনক্রিপশন কী হিসাবে কমপক্ষে দ্বিগুণ দীর্ঘ সময় ব্যবহার করার পরামর্শ দেওয়া হয়: প্রথমার্ধটি এনক্রিপশন কী হিসাবে কাজ করে, এবং দ্বিতীয়ার্ধটি অখণ্ডতা পরীক্ষার জন্য কী হিসাবে কাজ করে। (এটি, এই ক্ষেত্রে, একটি পাসওয়ার্ড এবং লবণ থেকে একটি গোপন উত্পন্ন করুন এবং সেই গোপনীয়করণটি দুটি ভাগে ভাগ করুন))

জাভা বাস্তবায়ন

বাস্তবায়নের বিভিন্ন ফাংশন 1 এর এলগোরিদিমগুলির জন্য "বিসি" নামে একটি নির্দিষ্ট সরবরাহকারী ব্যবহার করে। সাধারণভাবে, তবে, নির্দিষ্ট সরবরাহকারীদের জন্য অনুরোধ করার পরামর্শ দেওয়া হয় না, যেহেতু সমস্ত সরবরাহকারী সমস্ত জাভা বাস্তবায়নে উপলব্ধ নয়, সমর্থনের অভাবে, কোড অনুলিপি এড়ানোর জন্য, বা অন্য কারণে নয়। এই পরামর্শটি বিশেষত 2018 সালের শুরুর দিকে অ্যান্ড্রয়েড পি পূর্বরূপ প্রকাশের পর থেকেই গুরুত্বপূর্ণ হয়ে উঠেছে, কারণ "বিসি" সরবরাহকারীর কিছু কার্যকারিতা সেখানে অবচয় করা হয়েছে - অ্যান্ড্রয়েড বিকাশকারীদের ব্লগে "অ্যান্ড্রয়েড পিতে ক্রিপ্টোগ্রাফি পরিবর্তনগুলি" নিবন্ধটি দেখুন see আরও দেখুন ওরাকল প্রোভাইডার পরিচিতি

সুতরাং, PROVIDERউপস্থিত থাকা উচিত না এবং স্ট্রিংটি -BCঅপসারণ করা উচিত PBE_ALGORITHM। বাস্তবায়ন 2 এই ক্ষেত্রে সঠিক।

সমস্ত ব্যতিক্রম ধরা কোনও পদ্ধতির পক্ষে এটি অনুপযুক্ত, তবে কেবল এটির ব্যতিক্রমগুলি পরিচালনা করতে পারে। আপনার প্রশ্নে প্রদত্ত বাস্তবায়নগুলি বিভিন্ন পরীক্ষিত ব্যতিক্রম ছুঁড়ে ফেলতে পারে। একটি পদ্ধতি কেবল ক্রিপ্টোএক্সেপশন সহ কেবলমাত্র সেই চেক করা ব্যতিক্রমগুলি মোড়ানোর জন্য বেছে নিতে পারে বা ক্লজটিতে সেই পরীক্ষিত ব্যতিক্রমগুলি নির্দিষ্ট করতে পারে throws। সুবিধার জন্য, ক্রিপ্টোএক্সেপশন সহ মূল ব্যতিক্রমটি মোড়ানো এখানে উপযুক্ত হতে পারে, কারণ ক্লাসগুলি নিক্ষেপ করতে পারে এমন অনেকগুলি পরীক্ষিত ব্যতিক্রম রয়েছে।

SecureRandom অ্যান্ড্রয়েডে

অ্যান্ড্রয়েড বিকাশকারী ব্লগে "কিছু সিকিউররেডম চিন্তাভাবনা" নিবন্ধে যেমন বিশদ রয়েছে তেমনি, java.security.SecureRandom2013 এর আগে অ্যান্ড্রয়েড প্রকাশের বাস্তবায়নের একটি ত্রুটি রয়েছে যা এটি সরবরাহ করে এলোমেলো সংখ্যার শক্তি হ্রাস করে। এই ত্রুটিটি নিবন্ধে বর্ণিত হিসাবে হ্রাস করা যেতে পারে।


এই ডাবল সিক্রেট জেনারেশনটি আমার মতে কিছুটা অপ্রয়োজনীয়, আপনি জেনারেটেড গোপনীয়তাকে সহজেই দুটি ভাগে ভাগ করতে পারেন, বা - যদি পর্যাপ্ত বিট না পাওয়া যায় - তবে একটি কাউন্টার যুক্ত করুন (প্রথম চাবিটির জন্য 1, দ্বিতীয় কীটির জন্য 2) গোপন এবং একটি একক হ্যাশ সঞ্চালন। সমস্ত পুনরাবৃত্তি দুবার সম্পাদন করার প্রয়োজন নেই।
মার্টেন বোদেউয়েস

এইচএমএসি এবং লবণের তথ্যের জন্য ধন্যবাদ। আমি এবার এইচএমএসি ব্যবহার করব না তবে পরে এটি খুব কার্যকর হতে পারে। এবং সাধারণভাবে, এটি একটি ভাল জিনিস, সন্দেহ নেই।
কাব

সমস্ত সম্পাদনা এবং জাভার AES এনক্রিপশনের এটি (এখন) দুর্দান্ত ভূমিকাটির জন্য আপনাকে অনেক ধন্যবাদ!
কাওয়ান

4
এটা করা উচিত। getInstanceএকটি ওভারলোড রয়েছে যা কেবলমাত্র অ্যালগরিদমের নাম নেয়। উদাহরণ: সাইফার.জেটইনস্ট্যানস () বাউন্সি ক্যাসল সহ বেশ কয়েকটি সরবরাহকারী জাভা বাস্তবায়নে নিবন্ধভুক্ত হতে পারে এবং এই ধরণের ওভারলোড প্রদত্ত তালিকার সন্ধান করে যা তাদের প্রদত্ত অ্যালগরিদমকে কার্যকর করে। আপনার এটি চেষ্টা করে দেখা উচিত।
পিটার ও।

4
হ্যাঁ, এটি সিকিউরিটি.জেটপ্রোভিডারস () দ্বারা প্রদত্ত ক্রমটিতে সরবরাহকারীদের অনুসন্ধান করবে - যদিও এটি এখন পরীক্ষা করবে যে ডিভাইসটির দ্বারা ডিভাইস () কল করার সময় সেই সরবরাহকারীর দ্বারা কীটি গ্রহণ করা হয়েছে কিনা তা হার্ডওয়্যার সহকারী এনক্রিপশনের অনুমতি দেয়। এখানে আরো বিস্তারিত: docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/...
মার্টেন বোদেউয়েস

18

# 2 কখনই ব্যবহার করা উচিত নয় কারণ এটি সাইফারের জন্য কেবল "এইএস" (যার অর্থ পাঠ্যে ইসিবি মোড এনক্রিপশন, একটি বড় নং) রয়েছে। আমি শুধু # 1 সম্পর্কে কথা বলব।

প্রথম প্রয়োগটি এনক্রিপশনের জন্য সেরা অনুশীলনের সাথে অনুগামী বলে মনে হচ্ছে। ধ্রুবকগুলি সাধারণত ঠিক থাকে, যদিও পিবিই সম্পাদনের জন্য লবণের আকার এবং পুনরাবৃত্তির সংখ্যা উভয়ই স্বল্প দিকে। Futhermore, এটি AES-256 এর জন্য বলে মনে হচ্ছে যেহেতু PBE কী প্রজন্ম 256 কে হার্ড কোডড মান হিসাবে ব্যবহার করে (সমস্ত ধরণের পরেও লজ্জা)। এটিতে সিবিসি এবং পিকেসিএস 5 প্যাডিং ব্যবহার করা হয় যা অন্তত আপনি যা প্রত্যাশা করবেন।

সম্পূর্ণরূপে নিখোঁজ হ'ল কোনও প্রমাণীকরণ / অখণ্ডতা সুরক্ষা, যাতে আক্রমণকারী সাইফার পাঠ্য পরিবর্তন করতে পারে। এর অর্থ এই যে কোনও ক্লায়েন্ট / সার্ভার মডেলটিতে প্যাডিং ওরাকল আক্রমণগুলি সম্ভব। এর অর্থ হ'ল কোনও আক্রমণকারী এনক্রিপ্ট হওয়া ডেটা চেষ্টা ও পরিবর্তন করতে পারে। এর ফলে সম্ভবত কোথাও কোথাও ত্রুটিযুক্ত প্যাডিং বা সামগ্রীটি অ্যাপ্লিকেশনটির মাধ্যমে গৃহীত হবে না, তবে আপনি যে পরিস্থিতিতে থাকতে চান সেটি এমন নয়।

ব্যতিক্রম হ্যান্ডলিং এবং ইনপুট বৈধতা বাড়ানো যেতে পারে, ব্যতিক্রম ধরা আমার বইতে সর্বদা ভুল। ফারহটারমোর, ক্লাসটি আইক্রিপ্ট প্রয়োগ করে, যা আমি জানি না। আমি জানি যে ক্লাসে পার্শ্ব প্রতিক্রিয়া ছাড়াই কেবল পদ্ধতি থাকা কিছুটা অদ্ভুত। সাধারণত, আপনি এই স্থির করতে হবে। সাইফার উদাহরণগুলির কোনও বাফারিং নেই ইত্যাদি, সুতরাং প্রতিটি প্রয়োজনীয় বস্তুটি অ্যাড-নাক্সাম তৈরি করে। তবে আপনি যে সংজ্ঞাটি বলে মনে হয় তা থেকে আপনি নিরাপদে আইক্রিপ্টোকে মুছে ফেলতে পারেন, সেক্ষেত্রে আপনি কোডটিকে অচল পদ্ধতিতে (বা আপনার পছন্দ অনুসারে পুনরায় লিখতে পারেন) এটিকে পুনরুদ্ধার করতে পারেন।

সমস্যাটি হ'ল যে কোনও মোড়ক ব্যবহারের ক্ষেত্রে সর্বদা অনুমান করে। একটি মোড়ক সঠিক বা ভুল তাই বলার জন্য আবদ্ধ। এ কারণেই আমি সর্বদা চেষ্টা করি র‌্যাপার ক্লাস উত্পন্ন করা এড়াতে। তবে কমপক্ষে এটি স্পষ্টতই ভুল বলে মনে হচ্ছে না।


এই বিস্তারিত উত্তরের জন্য আপনাকে অনেক ধন্যবাদ! আমি জানি এটি একটি লজ্জাজনক তবে আমি এখনও কোড পর্যালোচনা বিভাগটি জানতাম না: ডি এই ইঙ্গিতটির জন্য ধন্যবাদ, আমি এটি পরীক্ষা করে দেখব। তবে এই প্রশ্নটি আমার মতে এখানেও খাপ খায় কারণ আমি কেবল এই কোড স্নিপেটের একটি পর্যালোচনা চাই না। পরিবর্তে, অ্যান্ড্রয়েডে AES এনক্রিপশন বাস্তবায়নের সময় আমি আপনাকে কী কী দিকগুলি গুরুত্বপূর্ণ তা জিজ্ঞাসা করতে চাই। এবং আপনি ঠিক আবার, এই কোড স্নিপেট AES-256 এর জন্য। সুতরাং আপনি বলবেন যে এটি সাধারণভাবে AES-256 এর নিরাপদ বাস্তবায়ন? ব্যবহারের ক্ষেত্রেটি হ'ল আমি কেবল একটি ডাটাবেসে টেক্সট তথ্য নিরাপদে সংরক্ষণ করতে চাই।
কাবি

4
এটি দেখতে দুর্দান্ত লাগছে, তবে সততা যাচাই এবং প্রমাণীকরণ না করার ধারণাটি আমাকে বিরক্ত করবে। আপনার যদি পর্যাপ্ত জায়গা থাকে তবে আমি সিফারেক্সটেক্সটে একটি এইচএমএএসি যুক্ত করার জন্য গুরুত্ব সহকারে বিবেচনা করব। এটি বলেছিল যে আপনি সম্ভবত গোপনীয়তা যুক্ত করার চেষ্টা করছেন, আমি এটিকে একটি বড় প্লাস হিসাবে বিবেচনা করব, তবে সরাসরি কোনও প্রয়োজন নয়।
মার্টেন বোদেউয়েস

তবে যদি উদ্দেশ্যটি কেবল এই হয় যে অন্যদের এনক্রিপ্ট করা তথ্যে অ্যাক্সেস না থাকা উচিত, আমার এইচএমএসি দরকার নেই, তাই না? যদি তারা সিফারেক্সট পরিবর্তন করে এবং ডিক্রিপশনের "ভুল" ফলাফল জোর করে, আসলেই কোন সমস্যা নেই, আছে কি?
কাবি

যদি এটি আপনার ঝুঁকিপূর্ণ পরিস্থিতিতে না হয়, তবে তা ঠিক। তারা যদি সাইফার টেক্সট (প্যাডিং ওরাকল অ্যাটাক) পরিবর্তন করার পরে যদি কোনওভাবে সিস্টেমে পুনরাবৃত্তি ডিক্রিপ্ট ট্রিগার করতে পারে তবে তারা কীটি না জেনে ডেটা ডিক্রিপ্ট করতে পারে। কীগুলি নেই এমন কোনও সিস্টেমে যদি তারা কেবল ডেটা ধরে রাখে তবে তারা এটি করতে পারে না। তবে সে কারণেই এইচএমএসি যুক্ত করা সর্বদা সেরা অনুশীলন। ব্যক্তিগতভাবে, আমি AES-128 এবং এইচএমএএসি সমন্বিত AES-256 এর চেয়ে নিরাপদ একটি সিস্টেম বিবেচনা করব - তবে যেমনটি বলা হয়েছে, সম্ভবত এটির প্রয়োজন নেই।
মার্টেন বোদেউয়েস

4
আপনি যদি সত্যতা চান তবে কেন গ্যালোইস / কাউন্টার-মোডে (এইএস-জিসিএম) এএস ব্যবহার করবেন না?
কিমভাইস

1

আপনি একটি চমত্কার আকর্ষণীয় প্রশ্ন জিজ্ঞাসা করেছেন। সমস্ত অ্যালগরিদমের মতো সিফার কীটি হ'ল "সিক্রেট সস", যেহেতু এটি একবার জনসাধারণের কাছে জানা হয়ে গেছে, অন্য সব কিছু খুব বেশি। সুতরাং আপনি গুগলের দ্বারা এই দস্তাবেজের উপায়গুলি সন্ধান করুন

সুরক্ষা

গুগল ইন-অ্যাপ্লিকেশন বিলিং এছাড়াও সুরক্ষা সম্পর্কে ধারণা দেয় যা অন্তর্দৃষ্টিপূর্ণ

বিলিং_বেস্ট_প্র্যাকটিসেস


এই লিঙ্কগুলির জন্য ধন্যবাদ! "সাইফার কীটি বাইরে থাকলে, সমস্ত কিছুর বাইরে চলে যায়" বলতে কী বোঝায়?
কাওয়ান

আমার অর্থ হ'ল এনক্রিপশন কীটি সুরক্ষিত হওয়া দরকার, যদি কেউ এটি ধরে রাখতে পারে তবে আপনার এনক্রিপ্ট হওয়া ডেটা প্লেইন্টেক্সটের মতোই ভাল। আপনি যদি আমার উত্তরটি একটি ডিগ্রীতে সহায়ক বলে মনে করেন তবে দয়া করে আপ করুন
---)

0

বাউনসিস্টল লাইটওয়েট এপিআই ব্যবহার করুন। এটি পিবিই এবং লবণ সহ 256 এইএস সরবরাহ করে।
এখানে নমুনা কোড, যা ফাইলগুলি এনক্রিপ্ট / ডিক্রিপ্ট করতে পারে।

public void encrypt(InputStream fin, OutputStream fout, String password) {
    try {
        PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(new SHA256Digest());
        char[] passwordChars = password.toCharArray();
        final byte[] pkcs12PasswordBytes = PBEParametersGenerator.PKCS12PasswordToBytes(passwordChars);
        pGen.init(pkcs12PasswordBytes, salt.getBytes(), iterationCount);
        CBCBlockCipher aesCBC = new CBCBlockCipher(new AESEngine());
        ParametersWithIV aesCBCParams = (ParametersWithIV) pGen.generateDerivedParameters(256, 128);
        aesCBC.init(true, aesCBCParams);
        PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(aesCBC, new PKCS7Padding());
        aesCipher.init(true, aesCBCParams);

        // Read in the decrypted bytes and write the cleartext to out
        int numRead = 0;
        while ((numRead = fin.read(buf)) >= 0) {
            if (numRead == 1024) {
                byte[] plainTemp = new byte[aesCipher.getUpdateOutputSize(numRead)];
                int offset = aesCipher.processBytes(buf, 0, numRead, plainTemp, 0);
                final byte[] plain = new byte[offset];
                System.arraycopy(plainTemp, 0, plain, 0, plain.length);
                fout.write(plain, 0, plain.length);
            } else {
                byte[] plainTemp = new byte[aesCipher.getOutputSize(numRead)];
                int offset = aesCipher.processBytes(buf, 0, numRead, plainTemp, 0);
                int last = aesCipher.doFinal(plainTemp, offset);
                final byte[] plain = new byte[offset + last];
                System.arraycopy(plainTemp, 0, plain, 0, plain.length);
                fout.write(plain, 0, plain.length);
            }
        }
        fout.close();
        fin.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

public void decrypt(InputStream fin, OutputStream fout, String password) {
    try {
        PKCS12ParametersGenerator pGen = new PKCS12ParametersGenerator(new SHA256Digest());
        char[] passwordChars = password.toCharArray();
        final byte[] pkcs12PasswordBytes = PBEParametersGenerator.PKCS12PasswordToBytes(passwordChars);
        pGen.init(pkcs12PasswordBytes, salt.getBytes(), iterationCount);
        CBCBlockCipher aesCBC = new CBCBlockCipher(new AESEngine());
        ParametersWithIV aesCBCParams = (ParametersWithIV) pGen.generateDerivedParameters(256, 128);
        aesCBC.init(false, aesCBCParams);
        PaddedBufferedBlockCipher aesCipher = new PaddedBufferedBlockCipher(aesCBC, new PKCS7Padding());
        aesCipher.init(false, aesCBCParams);

        // Read in the decrypted bytes and write the cleartext to out
        int numRead = 0;
        while ((numRead = fin.read(buf)) >= 0) {
            if (numRead == 1024) {
                byte[] plainTemp = new byte[aesCipher.getUpdateOutputSize(numRead)];
                int offset = aesCipher.processBytes(buf, 0, numRead, plainTemp, 0);
                // int last = aesCipher.doFinal(plainTemp, offset);
                final byte[] plain = new byte[offset];
                System.arraycopy(plainTemp, 0, plain, 0, plain.length);
                fout.write(plain, 0, plain.length);
            } else {
                byte[] plainTemp = new byte[aesCipher.getOutputSize(numRead)];
                int offset = aesCipher.processBytes(buf, 0, numRead, plainTemp, 0);
                int last = aesCipher.doFinal(plainTemp, offset);
                final byte[] plain = new byte[offset + last];
                System.arraycopy(plainTemp, 0, plain, 0, plain.length);
                fout.write(plain, 0, plain.length);
            }
        }
        fout.close();
        fin.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

ধন্যবাদ! এটি সম্ভবত একটি ভাল এবং সুরক্ষিত সমাধান তবে আমি তৃতীয় পক্ষের সফ্টওয়্যারটি ব্যবহার করতে চাই না। আমি নিশ্চিত যে নিজেরাই নিরাপদ উপায়ে AES প্রয়োগ করা সম্ভব হবে।
কাবি

4
পার্শ্ব চ্যানেল আক্রমণগুলির বিরুদ্ধে সুরক্ষা অন্তর্ভুক্ত করতে চাইলে নির্ভর করে। সাধারণত, আপনার নিজেরাই ক্রিপ্টোগ্রাফিক অ্যালগরিদমগুলি প্রয়োগ করা বেশ নিরাপদ বলে ধরে নেওয়া উচিত ume যেমন এইএস সিবিসি ওরাকলের জাভা রানটাইম লাইবগুলিতে উপলভ্য, সম্ভবত কোনও অ্যালগরিদম অনুপলব্ধ থাকলে সেগুলি ব্যবহার করা এবং বাউন্সি ক্যাসল লাইব্রেরিগুলি ব্যবহার করা ভাল।
মার্টেন বোদেউয়েস

এটির সংজ্ঞাটি মিস bufকরছি (আমি সত্যই আশা করি এটি কোনও staticক্ষেত্র নয়)। এটি উভয়ের মতোই দেখায় encrypt()এবং decrypt()ইনপুটটি 1024 বাইটের একাধিক হলে সঠিকভাবে চূড়ান্ত ব্লকটি প্রক্রিয়া করতে ব্যর্থ হবে।
টিসি।

0

আমি এখানে একটি দুর্দান্ত বাস্তবায়ন পেয়েছি: http://nelenkov.blogspot.fr/2012/04/ using-password-based-encryption-on.html এবং https://github.com/nelenkov/android-pbe এটিও সহায়ক ছিল অ্যান্ড্রয়েডের জন্য যথেষ্ট AES প্রয়োগের জন্য আমার সন্ধানে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.