জাভা এএস এবং আমার নিজস্ব কী ব্যবহার করছে


89

আমি নিজের কী দিয়ে AES ব্যবহার করে একটি স্ট্রিং এনক্রিপ্ট করতে চাই। তবে কীটির কিছুটা দৈর্ঘ্য নিয়ে আমার সমস্যা হচ্ছে। আপনি কি আমার কোডটি পর্যালোচনা করতে পারেন এবং আমার কী ঠিক করতে / পরিবর্তন করতে হবে তা দেখতে পারেন।

public static void main(String[] args) throws Exception {
    String username = "bob@google.org";
    String password = "Password1";
    String secretID = "BlahBlahBlah";
    String SALT2 = "deliciously salty";

    // Get the Key
    byte[] key = (SALT2 + username + password).getBytes();
    System.out.println((SALT2 + username + password).getBytes().length);

    // Need to pad key for AES
    // TODO: Best way?

    // Generate the secret key specs.
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

    // Instantiate the cipher
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

    byte[] encrypted = cipher.doFinal((secrectID).getBytes());
    System.out.println("encrypted string: " + asHex(encrypted));

    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    byte[] original = cipher.doFinal(encrypted);
    String originalString = new String(original);
    System.out.println("Original string: " + originalString + "\nOriginal string (Hex): " + asHex(original));
}

এখনই আমি একটি ব্যতিক্রম পাই " অবৈধ AES কী দৈর্ঘ্য: 86 বাইট "। আমার চাবি প্যাড করা দরকার? আমি এটা কিভাবে করব?

ইসিবি বা সিবিসির জন্য কি আমার কিছু সেট করা দরকার?

ধন্যবাদ



16
হ্যা হ্যা হাস্যকর. আমি আসলে একটি এলোমেলো লবণ পাই, কিন্তু আমি আমার প্রশ্নটি আরও পরিষ্কার করে দেওয়ার জন্য আমার কোড সাফ করেছি। এই কারণেই ভেরিয়েবলটির নাম রাখা হয়েছে SALT2। তবে অন্য যারা এই একই সমস্যাটি নিয়ে আসে এবং কোডটি অনুলিপি / পেস্ট করতে পছন্দ করে তাদের জন্য ভাল রেফারেন্স।
বার্নি পেরেজ

উত্তর:


125

সম্পাদনা করুন:

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

    SecureRandom sr = SecureRandom.getInstanceStrong();
    byte[] salt = new byte[16];
    sr.nextBytes(salt);

    PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1000, 128 * 8);
    SecretKey key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(spec);
    Cipher aes = Cipher.getInstance("AES");
    aes.init(Cipher.ENCRYPT_MODE, key);

===========

পুরানো উত্তর

আপনার কী থেকে একটি হ্যাশ তৈরি করতে আপনার SHA-1 ব্যবহার করা উচিত এবং ফলাফলটি 128 বিট (16 বাইট) এ ছাঁটা উচিত।

অতিরিক্তভাবে getBytes () এর মাধ্যমে স্ট্রিংগুলি থেকে বাইট অ্যারেগুলি তৈরি করবেন না এটি প্ল্যাটফর্মের ডিফল্ট চরসেট ব্যবহার করে। সুতরাং পাসওয়ার্ড "blaöä" বিভিন্ন প্ল্যাটফর্মের বিভিন্ন বাইট অ্যারে ফলাফল।

byte[] key = (SALT2 + username + password).getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // use only first 128 bit

SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

সম্পাদনা করুন: আপনার যদি কী আকারের 256 বিট প্রয়োজন হয় তবে আপনার "জাভা ক্রিপ্টোগ্রাফি এক্সটেনশন (জেসিই) আনলিমিটেড স্ট্রেংথ এখিনিয়ারেশন পলিসি ফাইলস" ওরাকল ডাউনলোড লিঙ্কটি ডাউনলোড করতে হবে , এসএএচএ-256 হ্যাশ হিসাবে ব্যবহার করুন এবং অ্যারেসকপি অফ লাইনটি সরিয়ে ফেলুন । "ইসিবি" হ'ল ডিফল্ট সাইফার মোড এবং "পিকেসিএস ৫ প্যাডিং" ডিফল্ট প্যাডিং। আপনি সাইফার.বিজ্ঞাপন স্ট্রিংয়ের মাধ্যমে বিভিন্ন সাইফার মোড এবং প্যাডিং মোডগুলি নিম্নলিখিত ফর্ম্যাটটি ব্যবহার করে ব্যবহার করতে পারেন : "সাইফার / মোড / প্যাডিং"

AES এর জন্য সিটিএস এবং পিকেসিএস 5 প্যাডিং ব্যবহার করে স্ট্রিংটি হ'ল: "এইএস / সিটিএস / পিকেসিএস 5 প্যাডিং"


এটি কাজ করবে তবে এটি আমার পাসওয়ার্ডটি হ্যাশ করছে, তারপরে কেবল প্রথম কয়েকটি বিট ব্যবহার করা হবে। এটি করার ভাল আর কোন উপায় নেই?
বার্নি পেরেজ

4
মূল কারণটি উত্পন্ন করার জন্য এর চেয়ে ভাল আর কোনও উপায় নেই যে AES এর জন্য 128/192/256 বিট কী প্রয়োজন। আপনি যদি আপনার কীটি হ্যাশ না করেন এবং কেবল ইনপুটটি ছাঁটাই করেন তবে এটি কেবল প্রথম 16/24/32 বাইট ব্যবহার করবে। সুতরাং একটি হ্যাশ উত্পাদন করা একমাত্র যুক্তিযুক্ত উপায়।
mknjc

13
মনে রাখবেন যে এই উত্তরটি কোনও ভাল কী ডেরাইভেশন ফাংশন ব্যবহার করে না এবং এটি এর মতো নিরাপদ নয় । সামান্য পুরানো কী ডেরাইভেশন ফাংশনের জন্য অন্য উত্তরটি দেখুন - এবং দুর্ভাগ্যক্রমে এখনও একটি স্থির লবণ।
মার্টেন বোদেউয়েস

4
আমি এই উত্তরটি মুছে ফেলার পরামর্শ দিচ্ছি কারণ এটি অত্যন্ত খারাপ অনুশীলন। একটি উপযুক্ত কী ডেরাইভেশন ফাংশন ব্যবহার করা উচিত - কমপক্ষে PBKDF2।
বোরিস স্পাইডার

4
হ্যাঁ, উত্তরটি খুব খারাপ, যেমন মার্টেন কয়েক বছর আগে বলেছিলেন। দয়া করে এই উত্তরটি ক্রিপ্টোগ্রাফি এবং কী
ডেরিভেশন

14

কী তৈরি করার জন্য আপনার কী-জেনারেটর ব্যবহার করা উচিত,

আপনি যে সাইফারটি ব্যবহার করতে চান তার উপর নির্ভর করে AES কী দৈর্ঘ্য 128, 192 এবং 256 বিট।

টিউটোরিয়ালটি এখানে দেখুন

এখানে পাসওয়ার্ড ভিত্তিক এনক্রিপশনের কোড রয়েছে, এতে সিস্টেমে.ইনের মাধ্যমে পাসওয়ার্ডটি প্রবেশ করা হচ্ছে আপনি চান সঞ্চিত পাসওয়ার্ডটি ব্যবহার করতে এটি পরিবর্তন করতে পারেন।

        PBEKeySpec pbeKeySpec;
        PBEParameterSpec pbeParamSpec;
        SecretKeyFactory keyFac;

        // Salt
        byte[] salt = {
            (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
            (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
        };

        // Iteration count
        int count = 20;

        // Create PBE parameter set
        pbeParamSpec = new PBEParameterSpec(salt, count);

        // Prompt user for encryption password.
        // Collect user password as char array (using the
        // "readPassword" method from above), and convert
        // it into a SecretKey object, using a PBE key
        // factory.
        System.out.print("Enter encryption password:  ");
        System.out.flush();
        pbeKeySpec = new PBEKeySpec(readPassword(System.in));
        keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

        // Create PBE Cipher
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

        // Initialize PBE Cipher with key and parameters
        pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

        // Our cleartext
        byte[] cleartext = "This is another example".getBytes();

        // Encrypt the cleartext
        byte[] ciphertext = pbeCipher.doFinal(cleartext);

4
কী জেনারেটরটি ব্যবহার করে আমি কীভাবে পাসওয়ার্ড দিয়ে কী তৈরি করব? আমি পাসওয়ার্ডের ভিত্তিতে একই কী উত্পন্ন করতে চাই। সুতরাং আমি পরে স্ট্রিং ডিক্রিপ্ট করতে পারেন।
বার্নি পেরেজ

আপনার কথা বলার বিষয়টি হ'ল পাসওয়ার্ড ভিত্তিক এনক্রিপশন AES নয়। আমি আমার উত্তরটি
পিবিই

4
পরিবর্তে PBEKDF2 কী জেনারেটরটি ব্যবহার করে ব্যবহার করুন, SecretKeyFactoryআরও ডেট টু ডেট এনক্রিপশনের জন্য "PBKDF2WithHmacSHA1" স্ট্রিং ব্যবহার করুন ।
মার্টেন বোদেউয়েস

12
প্রকৃতপক্ষে এই উত্তরের ব্যবহৃত সমস্ত ক্রিপ্টোগ্রাফিক আদিমগুলি পুরানো , নিশ্চিত MD5 এবং DES। চিন্তা - ভাবনা.
মার্টেন বোদেউয়েস

MD5 এবং DES দুর্বল সাইফার স্যুট এবং এভিড হওয়া উচিত
এটম ৮৮

6
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;
import java.io.BufferedReader;
import java.io.FileReader;

public class AESFile 
{
private static String algorithm = "AES";
private static byte[] keyValue=new byte[] {'0','2','3','4','5','6','7','8','9','1','2','3','4','5','6','7'};// your key

    // Performs Encryption
    public static String encrypt(String plainText) throws Exception 
    {
            Key key = generateKey();
            Cipher chiper = Cipher.getInstance(algorithm);
            chiper.init(Cipher.ENCRYPT_MODE, key);
            byte[] encVal = chiper.doFinal(plainText.getBytes());
            String encryptedValue = new BASE64Encoder().encode(encVal);
            return encryptedValue;
    }

    // Performs decryption
    public static String decrypt(String encryptedText) throws Exception 
    {
            // generate key 
            Key key = generateKey();
            Cipher chiper = Cipher.getInstance(algorithm);
            chiper.init(Cipher.DECRYPT_MODE, key);
            byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedText);
            byte[] decValue = chiper.doFinal(decordedValue);
            String decryptedValue = new String(decValue);
            return decryptedValue;
    }

//generateKey() is used to generate a secret key for AES algorithm
    private static Key generateKey() throws Exception 
    {
            Key key = new SecretKeySpec(keyValue, algorithm);
            return key;
    }

    // performs encryption & decryption 
    public static void main(String[] args) throws Exception 
    {
        FileReader file = new FileReader("C://myprograms//plaintext.txt");
        BufferedReader reader = new BufferedReader(file);
        String text = "";
        String line = reader.readLine();
    while(line!= null)
        {
            text += line;
    line = reader.readLine();
        }
        reader.close();
    System.out.println(text);

            String plainText = text;
            String encryptedText = AESFile.encrypt(plainText);
            String decryptedText = AESFile.decrypt(encryptedText);

            System.out.println("Plain Text : " + plainText);
            System.out.println("Encrypted Text : " + encryptedText);
            System.out.println("Decrypted Text : " + decryptedText);
    }
}

4
হতে পারে আরও কিছু ব্যাখ্যা পাঠ্য যুক্ত করুন।
ক্রিসজি

প্রশ্ন, keyValueবাইট অ্যারের সাথে থাকার মানে কী? আমি দেখছি এটি কী তৈরি করতে ব্যবহৃত হচ্ছে, কেন? SecretKeyপরিবর্তে মত ব্যবহার করে কিছু করা যেতে পারে ? যদি তাই হয়, কিভাবে?
অস্টিন

@ ম্যান্ড্রেইক, "প্লেইনটেক্সট। টেক্সট" ফাইলটির সামগ্রী এনক্রিপ্ট করা হবে। উপরের যুক্তিটি ফাইলটিতে ডেটা / বার্তা এনক্রিপ্ট করে যা ফাইলরেডার কনস্ট্রাক্টারে যুক্তি হিসাবে পড়ে is
শঙ্কর মুর্তি 30'19

2

এই WL কাজ।

public class CryptoUtils {

    private  final String TRANSFORMATION = "AES";
    private  final String encodekey = "1234543444555666";
    public  String encrypt(String inputFile)
            throws CryptoException {
        return doEncrypt(encodekey, inputFile);
    }


    public  String decrypt(String input)
            throws CryptoException {
    // return  doCrypto(Cipher.DECRYPT_MODE, key, inputFile);
    return doDecrypt(encodekey,input);
    }

    private  String doEncrypt(String encodekey, String inputStr)   throws CryptoException {
        try {

            Cipher cipher = Cipher.getInstance(TRANSFORMATION);

            byte[] key = encodekey.getBytes("UTF-8");
            MessageDigest sha = MessageDigest.getInstance("SHA-1");
            key = sha.digest(key);
            key = Arrays.copyOf(key, 16); // use only first 128 bit

            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

            byte[] inputBytes = inputStr.getBytes();     
            byte[] outputBytes = cipher.doFinal(inputBytes);

            return Base64Utils.encodeToString(outputBytes);

        } catch (NoSuchPaddingException | NoSuchAlgorithmException
                | InvalidKeyException | BadPaddingException
                | IllegalBlockSizeException | IOException ex) {
            throw new CryptoException("Error encrypting/decrypting file", ex);
       }
     }


    public  String doDecrypt(String encodekey,String encrptedStr) { 
          try {     

              Cipher dcipher = Cipher.getInstance(TRANSFORMATION);
              dcipher = Cipher.getInstance("AES");
              byte[] key = encodekey.getBytes("UTF-8");
              MessageDigest sha = MessageDigest.getInstance("SHA-1");
              key = sha.digest(key);
              key = Arrays.copyOf(key, 16); // use only first 128 bit

              SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

              dcipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            // decode with base64 to get bytes

              byte[] dec = Base64Utils.decode(encrptedStr.getBytes());  
              byte[] utf8 = dcipher.doFinal(dec);

              // create new string based on the specified charset
              return new String(utf8, "UTF8");

          } catch (Exception e) {

            e.printStackTrace();

          }
      return null;
      }
 }

2

MD5, AES, কোন প্যাডিং নেই

import static javax.crypto.Cipher.DECRYPT_MODE;
import static javax.crypto.Cipher.ENCRYPT_MODE;
import static org.apache.commons.io.Charsets.UTF_8;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class PasswordUtils {

    private PasswordUtils() {}

    public static String encrypt(String text, String pass) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            Key key = new SecretKeySpec(messageDigest.digest(pass.getBytes(UTF_8)), "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(ENCRYPT_MODE, key);

            byte[] encrypted = cipher.doFinal(text.getBytes(UTF_8));
            byte[] encoded = Base64.getEncoder().encode(encrypted);
            return new String(encoded, UTF_8);

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            throw new RuntimeException("Cannot encrypt", e);
        }
    }

    public static String decrypt(String text, String pass) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            Key key = new SecretKeySpec(messageDigest.digest(pass.getBytes(UTF_8)), "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(DECRYPT_MODE, key);

            byte[] decoded = Base64.getDecoder().decode(text.getBytes(UTF_8));
            byte[] decrypted = cipher.doFinal(decoded);
            return new String(decrypted, UTF_8);

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            throw new RuntimeException("Cannot decrypt", e);
        }
    }
}

কৌণিকভাবে সিক্রেটকিএসপেকের মতো সুরক্ষিত কী কীভাবে তৈরি করবেন (আয়নিক 4);
নিতিন কারালে

0
    byte[] seed = (SALT2 + username + password).getBytes();
    SecureRandom random = new SecureRandom(seed);
    KeyGenerator generator;
    generator = KeyGenerator.getInstance("AES");
    generator.init(random);
    generator.init(256);
    Key keyObj = generator.generateKey();
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.