জাভা এএস / সিবিসি ডিক্রিপশনের পরে প্রাথমিক বাইটস ভুল


116

নিম্নলিখিত উদাহরণটিতে ভুল কী?

সমস্যাটি হ'ল ডিক্রিপ্ট করা স্ট্রিংয়ের প্রথম অংশটি বোকা। তবে বাকিটা ঠিক আছে, আমি পেয়েছি ...

Result: eB6OgeS��i are you? Have a nice day.
@Test
public void testEncrypt() {
  try {
    String s = "Hello there. How are you? Have a nice day.";

    // Generate key
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    kgen.init(128);
    SecretKey aesKey = kgen.generateKey();

    // Encrypt cipher
    Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);

    // Encrypt
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);
    cipherOutputStream.write(s.getBytes());
    cipherOutputStream.flush();
    cipherOutputStream.close();
    byte[] encryptedBytes = outputStream.toByteArray();

    // Decrypt cipher
    Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());
    decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);

    // Decrypt
    outputStream = new ByteArrayOutputStream();
    ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);
    CipherInputStream cipherInputStream = new CipherInputStream(inStream, decryptCipher);
    byte[] buf = new byte[1024];
    int bytesRead;
    while ((bytesRead = cipherInputStream.read(buf)) >= 0) {
        outputStream.write(buf, 0, bytesRead);
    }

    System.out.println("Result: " + new String(outputStream.toByteArray()));

  } 
  catch (Exception ex) {
    ex.printStackTrace();
  }
}

48
গুরুতর প্রকল্পে এই প্রশ্নের কোনও উত্তর ব্যবহার করবেন না! এই প্রশ্নে প্রদত্ত সমস্ত উদাহরণ প্যাডিং ওরাকল থেকে ঝুঁকির সাথে সামগ্রিকভাবে খুব খারাপ ক্রিপ্টোগ্রাফি ব্যবহার। আপনি নীচে যে কোনও স্নিপেট ব্যবহার করে আপনার প্রকল্পে গুরুতর ক্রিপ্টোগ্রাফি দুর্বলতা প্রবর্তন করবেন।
HoLyVieR

16
@HoLyVieR, নিম্নলিখিত উক্তিগুলি সম্পর্কে: "আপনার নিজের ক্রিপ্টোগ্রাফি গ্রন্থাগারটি বিকাশ করা উচিত নয়" এবং "আপনার কাঠামোর সরবরাহ করে এমন একটি উচ্চ স্তরের API ব্যবহার করুন।" এখানে কেউ তাদের নিজস্ব ক্রিপ্টোগ্রাফি লাইব্রেরি বিকাশ করছে না। জাভা ফ্রেমওয়ার্কটি সরবরাহ করে আমরা ইতিমধ্যে বিদ্যমান, উচ্চ স্তরের এপিআই ব্যবহার করছি। আপনি স্যার বন্যভাবে ভুল।
k170

10
@ মার্টেনবোডওয়েস, কেবলমাত্র আপনি উভয়ই একমত হওয়ার অর্থ এই বোঝায় না যে আপনি উভয়ই সঠিক। ভাল বিকাশকারীরা উচ্চ স্তরের এপিআই মোড়ানো এবং নিম্ন স্তরের এপিআই পুনর্লিখনের মধ্যে পার্থক্য জানেন know ভাল পাঠকগণ লক্ষ্য করবেন যে ওপি একটি "সাধারণ জাভা এইএস এনক্রিপ্ট / ডিক্রিপ্ট উদাহরণ" চেয়েছিল এবং ঠিক সেটাই পেয়েছিল । আমি অন্যান্য উত্তরগুলির সাথেও একমত নই, এই কারণেই আমি আমার নিজের একটি উত্তর পোস্ট করেছি। আপনার ছেলেরাও একই চেষ্টা করা উচিত এবং আপনার দক্ষতার সাথে আমাদের সকলকে আলোকিত করা উচিত।
k170

6
@ হোলিভিআরআর এটি হ'ল সত্যই আমি এখন অবধি সবচেয়ে অবাস্তব জিনিসটি পড়েছি S লোকেরা কী বলতে পারে এবং তারা কী বিকাশ করতে পারে না তা বলতে আপনি কে?
টেডট্রিপিন

14
আমি এখনও @HOLyVieR এর কোনও উদাহরণ দেখতে পাচ্ছি না। আসুন কিছু, বা লাইব্রেরি পয়েন্টার দেখুন? মোটেও গঠনমূলক নয়।
ড্যানিয়েলজিমেনেজ

উত্তর:


245

আমার সহ অনেক লোক এই তথ্য তৈরির ক্ষেত্রে অনেকগুলি সমস্যার মুখোমুখি হয় যেমন কিছু বেস হারিয়ে যেমন বেস 64৪, রূপান্তরকরণ ভেক্টর, চরিত্র সেট ইত্যাদি ভুলে যাওয়ার কারণে আমি একটি সম্পূর্ণ কার্যকরী কোড তৈরি করার কথা ভেবেছিলাম।

আশা করি এটি আপনার সকলের জন্য কার্যকর হবে: সংকলন করতে আপনার অতিরিক্ত অ্যাপাচি কমন্স কোডেক জারের দরকার যা এখানে পাওয়া যায়: http://commons.apache.org/proper/commons-codec/download_codec.cgi

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

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

public class Encryptor {
    public static String encrypt(String key, String initVector, String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());
            System.out.println("encrypted string: "
                    + Base64.encodeBase64String(encrypted));

            return Base64.encodeBase64String(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static String decrypt(String key, String initVector, String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) {
        String key = "Bar12345Bar12345"; // 128 bit key
        String initVector = "RandomInitVector"; // 16 bytes IV

        System.out.println(decrypt(key, initVector,
                encrypt(key, initVector, "Hello World")));
    }
}

47
আপনি যদি ২ য় পক্ষের অ্যাপাচি কমন্স কোডেক লাইব্রেরির উপর নির্ভর করতে না চান আপনি বেস 6464 এনকোডিং / ডিকোডিং সম্পাদনের জন্য জেডিকে'র জাভ্যাক্স.এক্সএমএল.ড্যাট্যাটাইপ কনভার্টার ব্যবহার করতে পারেন : System.out.println("encrypted string:" + DatatypeConverter.printBase64Binary(encrypted)); byte[] original = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted));
curd0

8
আপনি কি ধ্রুবক IV ব্যবহার করছেন ?!
ভায়ান্না

36
জাভা 8 এর মধ্যে ইতিমধ্যে বেস 64 রয়েছে: java.util.Base64.getDecoder () এবং java.util.Base64.getEncoder ()
Hristo Stoyanov

11
চতুর্থটি গোপন থাকতে হবে না, তবে এটি সিবিসি মোডের জন্য অপ্রত্যাশিত হতে হবে (এবং সিটিআর জন্য অনন্য)। এটি সিফেরটেক্সট সহ পাঠানো যেতে পারে। এটি করার একটি সাধারণ উপায় হ'ল চতুর্থটি সিফারেক্সটেক্সে উপসর্গ করা এবং ডিক্রিপশন করার আগে এটি কেটে ফেলে। এটির মাধ্যমে উত্পন্ন করা উচিতSecureRandom
আর্টজম বি।

6
একটি পাসওয়ার্ড কী নয়। একটি চতুর্থ এলোমেলো হওয়া উচিত।
মার্টেন বোদেউয়েস

40

এখানে ছাড়া একটি সমাধান Apache Commons Codec's Base64:

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

public class AdvancedEncryptionStandard
{
    private byte[] key;

    private static final String ALGORITHM = "AES";

    public AdvancedEncryptionStandard(byte[] key)
    {
        this.key = key;
    }

    /**
     * Encrypts the given plain text
     *
     * @param plainText The plain text to encrypt
     */
    public byte[] encrypt(byte[] plainText) throws Exception
    {
        SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        return cipher.doFinal(plainText);
    }

    /**
     * Decrypts the given byte array
     *
     * @param cipherText The data to decrypt
     */
    public byte[] decrypt(byte[] cipherText) throws Exception
    {
        SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);

        return cipher.doFinal(cipherText);
    }
}

ব্যবহারের উদাহরণ:

byte[] encryptionKey = "MZygpewJsCpRrfOr".getBytes(StandardCharsets.UTF_8);
byte[] plainText = "Hello world!".getBytes(StandardCharsets.UTF_8);
AdvancedEncryptionStandard advancedEncryptionStandard = new AdvancedEncryptionStandard(
        encryptionKey);
byte[] cipherText = advancedEncryptionStandard.encrypt(plainText);
byte[] decryptedCipherText = advancedEncryptionStandard.decrypt(cipherText);

System.out.println(new String(plainText));
System.out.println(new String(cipherText));
System.out.println(new String(decryptedCipherText));

ছাপে:

Hello world!
դ;��LA+�ߙb*
Hello world!

5
@ চাঁদপ্রিয়ঙ্কারের মতো এটি একটি নিখুঁত কার্যকরী উদাহরণ। কিন্তু কেন এর একটি স্বাক্ষর সংজ্ঞায়িত encrypt(String)এবং encrypt(byte[] )। এনক্রিপশন (ডিক্রিপশনও খুব বেশি) একটি বাইট ভিত্তিক প্রক্রিয়া (এইএস যাইহোক)। এনক্রিপশন বাইটগুলি ইনপুট হিসাবে নেয় এবং বাইট আউটপুট নেয়, তাই ডিক্রিপশন (পয়েন্টে ক্ষেত্রে: Cipherঅবজেক্টটি করে)। এখন, একটি নির্দিষ্ট ব্যবহারের ক্ষেত্রে স্ট্রিং থেকে আসা এনক্রিপ্ট করা বাইটগুলি থাকতে পারে, বা স্ট্রিং হিসাবে প্রেরণ করা যেতে পারে (একটি মেইলের জন্য বেস 64 মিমি সংযুক্তি ...), তবে এটি এনকোডিং বাইটের একটি বিষয়, যার জন্য এখানে শত শত উপস্থিত রয়েছে সমাধানগুলি, পুরোপুরি এইএস / এনক্রিপশন সম্পর্কিত নয়।
জিপিআই

3
@ জিপিআই: হ্যাঁ, তবে আমি এটির সাথে আরও দরকারী মনে করি Stringsযেহেতু মূলত আমি 95% সময় নিয়ে কাজ করি এবং আপনি যেভাবেই রূপান্তর করতে পারেন।
বুলিউইআইপ্লাজা

9
না, এটি চাঁদপ্রিয়ঙ্করের কোডের সমতুল্য নয়! আপনার কোডটি ইসিবি ব্যবহার করে যা সাধারণত অনিরাপদ এবং চান না। স্পষ্টভাবে সিবিসি নির্দিষ্ট করা উচিত। সিবিসি সুনির্দিষ্ট করা থাকলে আপনার কোডটি ব্রেক হয়ে যাবে।
ড্যান

পুরোপুরি কার্যকরী, পুরোপুরি অনিরাপদ এবং খুব খারাপ প্রোগ্রামিং অনুশীলন ব্যবহার করে। বর্গ খারাপ নামকরণ করা হয়। মূল আকারটি আগাম চেক করা হয়নি। তবে সবচেয়ে গুরুত্বপূর্ণ বিষয়, কোডটি অনিরাপদ ইসিবি মোড ব্যবহার করে মূল প্রশ্নটিতে সমস্যাটি গোপন করে । অবশেষে, এটি একটি অক্ষর এনকোডিং নির্দিষ্ট করে না, যার অর্থ পাঠ্যের ডিকোডিং অন্য প্ল্যাটফর্মগুলিতে ব্যর্থ হতে পারে।
মার্টেন বোদেউয়েস 21

24

আমার কাছে দেখে মনে হচ্ছে আপনি নিজের ইনিশিয়েশন ভেক্টর (IV) এর সাথে সঠিকভাবে কাজ করছেন না। আমি এইএস, আইভি এবং ব্লক চেইনিংয়ের বিষয়ে সর্বশেষ পড়েছি, তবে আপনার লাইনটি অনেক দিন হয়ে গেছে

IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());

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

অতএব, আপনার এনক্রিপশন শেষে সিফার উদাহরণ থেকে আপনার বাম হিসাবে আইভি পাওয়া উচিত

  cipherOutputStream.close();
  byte[] iv = encryptCipher.getIV();

এবং আপনি আপনার আরম্ভ করা উচিত Cipherমধ্যে DECRYPT_MODEএই বাইট সঙ্গে []:

  IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

তারপরে, আপনার ডিক্রিপশন ঠিক আছে। আশাকরি এটা সাহায্য করবে.


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

উপেক্ষা করুন, আমি উত্তর খুঁজে পেয়েছি! আমার AES / ইসিবি / পিকেসিএস 5 প্যাডিং ব্যবহার করা দরকার।
টেড্রিপ্পিন

20
বেশিরভাগ সময় আপনি ইসিবি ব্যবহার করতে চান না । শুধু গুগল কেন।
জোও ফার্নান্দেস

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

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

17

আপনার ডিক্রিপশনটির জন্য যে আইভি ব্যবহার করছেন তা ভুল। এই কোডটি প্রতিস্থাপন করুন

//Decrypt cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);

এই কোড সহ

//Decrypt cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(encryptCipher.getIV());
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);

এবং এটি আপনার সমস্যার সমাধান করা উচিত।


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

import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
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 java.util.Base64;

public class AES 
{
    public static byte[] encrypt(final byte[] keyBytes, final byte[] ivBytes, final byte[] messageBytes) throws InvalidKeyException, InvalidAlgorithmParameterException
    {       
        return AES.transform(Cipher.ENCRYPT_MODE, keyBytes, ivBytes, messageBytes);
    }

    public static byte[] decrypt(final byte[] keyBytes, final byte[] ivBytes, final byte[] messageBytes) throws InvalidKeyException, InvalidAlgorithmParameterException
    {       
        return AES.transform(Cipher.DECRYPT_MODE, keyBytes, ivBytes, messageBytes);
    }

    private static byte[] transform(final int mode, final byte[] keyBytes, final byte[] ivBytes, final byte[] messageBytes) throws InvalidKeyException, InvalidAlgorithmParameterException
    {
        final SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        final IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        byte[] transformedBytes = null;

        try
        {
            final Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");

            cipher.init(mode, keySpec, ivSpec);

            transformedBytes = cipher.doFinal(messageBytes);
        }        
        catch (NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) 
        {
            e.printStackTrace();
        }
        return transformedBytes;
    }

    public static void main(final String[] args) throws InvalidKeyException, InvalidAlgorithmParameterException
    {
        //Retrieved from a protected local file.
        //Do not hard-code and do not version control.
        final String base64Key = "ABEiM0RVZneImaq7zN3u/w==";

        //Retrieved from a protected database.
        //Do not hard-code and do not version control.
        final String shadowEntry = "AAECAwQFBgcICQoLDA0ODw==:ZtrkahwcMzTu7e/WuJ3AZmF09DE=";

        //Extract the iv and the ciphertext from the shadow entry.
        final String[] shadowData = shadowEntry.split(":");        
        final String base64Iv = shadowData[0];
        final String base64Ciphertext = shadowData[1];

        //Convert to raw bytes.
        final byte[] keyBytes = Base64.getDecoder().decode(base64Key);
        final byte[] ivBytes = Base64.getDecoder().decode(base64Iv);
        final byte[] encryptedBytes = Base64.getDecoder().decode(base64Ciphertext);

        //Decrypt data and do something with it.
        final byte[] decryptedBytes = AES.decrypt(keyBytes, ivBytes, encryptedBytes);

        //Use non-blocking SecureRandom implementation for the new IV.
        final SecureRandom secureRandom = new SecureRandom();

        //Generate a new IV.
        secureRandom.nextBytes(ivBytes);

        //At this point instead of printing to the screen, 
        //one should replace the old shadow entry with the new one.
        System.out.println("Old Shadow Entry      = " + shadowEntry);
        System.out.println("Decrytped Shadow Data = " + new String(decryptedBytes, StandardCharsets.UTF_8));
        System.out.println("New Shadow Entry      = " + Base64.getEncoder().encodeToString(ivBytes) + ":" + Base64.getEncoder().encodeToString(AES.encrypt(keyBytes, ivBytes, decryptedBytes)));
    }
}

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


প্রথমে, আপনি মূল প্রশ্নের উত্তর দেন নি। দ্বিতীয়ত, আপনি কেন ইতিমধ্যে উত্তর, ভালভাবে গৃহীত প্রশ্নের উত্তর দিচ্ছেন? আমি ভেবেছিলাম সুরক্ষাটি এই স্প্যামটি বন্ধ করার কথা।
টেড্রিপ্পিন

14
গৃহীত উত্তরের মতো, আমি উদাহরণের মাধ্যমে আপনার প্রশ্নের উত্তর দিতে বেছে নিয়েছি। আমি কোডের একটি সম্পূর্ণ কার্যকরী টুকরো সরবরাহ করেছি, যা আপনাকে দেখায় যে কীভাবে প্রাথমিকভাবে ভেক্টরকে অন্যান্য জিনিসগুলির সাথে সঠিকভাবে মোকাবেলা করতে হবে। আপনার দ্বিতীয় প্রশ্নের হিসাবে, আমি অনুভব করেছি যে অ্যাপাচি কোডেকের আর প্রয়োজন নেই বলে একটি আপডেট উত্তর দরকার। সুতরাং না এটি স্প্যাম নয়। ট্রিপিন বন্ধ করুন।
k170

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

4
ডাউনভোট: হার্ডকোডড চতুর্থ, আর্টজম বি দেখুন কেন খারাপ তা উপরে মন্তব্য করুন
মার্মেল

1
সিটিআর মোডটি নোপ্যাডিংয়ের সাথে যুক্ত করা উচিত। CTR এর মোড অবশ্যই না সিবিসি পরিবর্তে প্রয়োজন বোধ করা হয় (যদি না প্যাডিং ওরাকেল প্রযোজ্য), কিন্তু যদি CTR এর হয় ব্যবহার করা হয়, তারপর ব্যবহার "/NoPadding"। সিটিআর হ'ল মোড যা একটি স্ট্রিম সাইফারে AES ঘুরিয়ে দেয় এবং একটি স্ট্রিম সাইফার ব্লকের পরিবর্তে বাইটে চালিত হয়।
মার্টেন বোদেউয়েস

16

এই উত্তরে আমি "সিম্পল জাভা এইএস এনক্রিপ্ট / ডিক্রিপ্ট উদাহরণ" মূল থিমের কাছে যেতে বেছে নিয়েছি এবং নির্দিষ্ট ডিবাগিং প্রশ্নটি নয়, কারণ আমি মনে করি এটি বেশিরভাগ পাঠককে উপকৃত করবে।

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

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

AES-GCM এনক্রিপশন / ডিক্রিপশন টিউটোরিয়াল

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

1. কী তৈরি করুন

এটি আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে, তাই আমি সবচেয়ে সহজ কেসটি গ্রহণ করব: একটি এলোমেলো গোপন কী।

SecureRandom secureRandom = new SecureRandom();
byte[] key = new byte[16];
secureRandom.nextBytes(key);
SecretKey secretKey = SecretKeySpec(key, "AES");

গুরুত্বপূর্ণ:

2. সূচনা ভেক্টর তৈরি করুন

একটি সূচনা ভেক্টর (IV) ব্যবহার করা হয় যাতে একই গোপন কীটি বিভিন্ন সাইফার পাঠ্য তৈরি করে ।

byte[] iv = new byte[12]; //NEVER REUSE THIS IV WITH SAME KEY
secureRandom.nextBytes(iv);

গুরুত্বপূর্ণ:

3. IV এবং কী দিয়ে এনক্রিপ্ট করুন

final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); //128 bit auth tag length
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] cipherText = cipher.doFinal(plainText);

গুরুত্বপূর্ণ:

  • 16 বাইট / 128 বিট প্রমাণীকরণ ট্যাগ ব্যবহার করুন (অখণ্ডতা / সত্যতা যাচাই করতে ব্যবহৃত হয়)
  • প্রমাণীকরণ ট্যাগটি স্বয়ংক্রিয়ভাবে সিফার পাঠ্যে সংযুক্ত হবে (জেসিএ প্রয়োগে)
  • যেহেতু জিসিএম স্ট্রিম সাইফারের মতো আচরণ করে, তাই কোনও প্যাডিং প্রয়োজন হয় না
  • CipherInputStreamডেটা বড় অংশগুলি এনক্রিপ্ট করার সময় ব্যবহার করুন
  • অতিরিক্ত (অ গোপনীয়) ডেটা পরিবর্তন করা হয়েছে কিনা তা পরীক্ষা করতে চান? আপনি এখানে আরও সাথে যুক্ত ডেটা ব্যবহার করতে চাইতে পারেন cipher.updateAAD(associatedData);

৩. একক বার্তায় সিরিয়াল করুন

কেবলমাত্র চতুর্থ এবং সিফেরেক্সট যুক্ত করুন। উপরে উল্লিখিত হিসাবে, চতুর্থ গোপনীয় প্রয়োজন হয় না।

ByteBuffer byteBuffer = ByteBuffer.allocate(iv.length + cipherText.length);
byteBuffer.put(iv);
byteBuffer.put(cipherText);
byte[] cipherMessage = byteBuffer.array();

আপনার যদি স্ট্রিং প্রতিনিধিত্বের প্রয়োজন হয় তবে বেস 64 এর সাথে বিকল্পভাবে এনকোড করুন । হয় অ্যান্ড্রয়েড বা জাভা 8 এর অন্তর্নির্মিত বাস্তবায়ন ব্যবহার করুন (অ্যাপাচি কমন্স কোডেক ব্যবহার করবেন না - এটি একটি ভয়াবহ বাস্তবায়ন)। এনকোডিংটি ASCII নিরাপদ করতে বাইট অ্যারেগুলিকে স্ট্রিং উপস্থাপনায় "রূপান্তর" করতে ব্যবহৃত হয় যেমন:

String base64CipherMessage = Base64.getEncoder().encodeToString(cipherMessage);

৪) ডিক্রিপশন প্রস্তুত করুন: ডিসরিওলাইজ করুন

আপনি যদি বার্তাটি এনকোড করেছেন, প্রথমে এটি বাইট অ্যারেতে ডিকোড করুন:

byte[] cipherMessage = Base64.getDecoder().decode(base64CipherMessage)

গুরুত্বপূর্ণ:

5. ডিক্রিপ্ট

সাইফারটি আরম্ভ করুন এবং এনক্রিপশন সহ একই পরামিতিগুলি সেট করুন:

final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
//use first 12 bytes for iv
AlgorithmParameterSpec gcmIv = new GCMParameterSpec(128, cipherMessage, 0, 12);
cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmIv);
//use everything from 12 bytes on as ciphertext
byte[] plainText = cipher.doFinal(cipherMessage, 12, cipherMessage.length - 12);

গুরুত্বপূর্ণ:

একটি কার্যকারী কোড স্নিপেট এই টুকরোটিতে পাওয়া যাবে।


নোট করুন যে সর্বাধিক সাম্প্রতিক Android (SDK 21+) এবং জাভা (7+) বাস্তবায়নগুলিতে AES-GCM থাকা উচিত। পুরানো সংস্করণ এর অভাব হতে পারে। আমি এখনও এই মোডটি বেছে নিই, যেহেতু এনক্রিপ্ট-তত্কালীন ম্যাকের (যেমন এইএস-সিবিসি + এইচএমএসি সহ ) অনুরূপ মোডের তুলনায় আরও দক্ষ হওয়ার সাথে সাথে প্রয়োগ করা আরও সহজ । এইচএমএসি দিয়ে কীভাবে এইএস-সিবিসি বাস্তবায়ন করবেন সে সম্পর্কে এই নিবন্ধটি দেখুন


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

1
যদিও আমি প্রচেষ্টাটির প্রশংসা করি, তাই আমি কেবল একটি ভুল উল্লেখ করব: "আইভিকে অনন্য (যেমন। র্যান্ডম আইভ ব্যবহার করুন) এর সাথে সংমিশ্রণে অনাকাঙ্ক্ষিত হতে হবে" - এটি সিবিসি মোডের ক্ষেত্রে সত্য তবে জিসিএমের পক্ষে নয়।
মার্টেন বোদেউয়েস 21

this is true for CBC mode but not for GCMআপনি কি পুরো অংশটি বোঝাচ্ছেন, বা কেবল এটিই আসলে অবিশ্বাস্য হওয়ার প্রয়োজন নেই?
প্যাট্রিক ফ্যাভরে

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

1
ঠিক আছে, কেবল কারণ আমি উত্তর কব্জি বিষয়বস্তু পছন্দ করি (উদ্দেশ্য পরিবর্তে): আইভি হ্যান্ডলিংটি বিশেষত ডিক্রিপশন চলাকালীন সরল করা যায়: জাভা সব পরে কোনও বিদ্যমান বাইট অ্যারে থেকে সরাসরি আইভি তৈরি করা সহজ করে তোলে। একই ডিক্রিপশন জন্য যায়, যা অফসেট 0 এ শুরু করতে হবে না। এই সমস্ত অনুলিপি কেবল প্রয়োজন হয় না। এছাড়াও যদি আপনাকে IV এর জন্য একটি দৈর্ঘ্য প্রেরণ করতে হয় (আপনি কি?) তবে কেন একটি একক (স্বাক্ষরযুক্ত) বাইট ব্যবহার করবেন না - আপনি চতুর্থের জন্য 255 বাইট পেরিয়ে যাবেন না, তাই না?
মার্টেন বোদেউয়েস

2

অনলাইন সম্পাদক চলমান সংস্করণ: -

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
//import org.apache.commons.codec.binary.Base64;
import java.util.Base64;

public class Encryptor {
    public static String encrypt(String key, String initVector, String value) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));

            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());

            //System.out.println("encrypted string: "
              //      + Base64.encodeBase64String(encrypted));

            //return Base64.encodeBase64String(encrypted);
            String s = new String(Base64.getEncoder().encode(encrypted));
            return s;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static String decrypt(String key, String initVector, String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted));

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) {
        String key = "Bar12345Bar12345"; // 128 bit key
        String initVector = "RandomInitVector"; // 16 bytes IV

        System.out.println(encrypt(key, initVector, "Hello World"));
        System.out.println(decrypt(key, initVector, encrypt(key, initVector, "Hello World")));
    }
}

দুর্দান্ত, খুশি!
ভূপেশ পান্ত

একটি পাসওয়ার্ড হল না একটি কী, একটি চতুর্থ স্ট্যাটিক থাকা উচিত নয়। তবুও কঠোরভাবে কোড টাইপ করা কোড, যা কীটি ধ্বংস করতে অসম্ভব করে তোলে। চতুর্থটি কী করবে সে সম্পর্কে কোনও ইঙ্গিত নেই, বা এটি অনুমানযোগ্যও হওয়া উচিত এমন কোনও ধারণাও নেই।
মার্টেন বোদেউয়েস 21

1

স্ট্যান্ডার্ড লাইব্রেরি প্রদত্ত সমাধানের উপর নির্ভর করা প্রায়শই ভাল ধারণা:

private static void stackOverflow15554296()
    throws
        NoSuchAlgorithmException, NoSuchPaddingException,        
        InvalidKeyException, IllegalBlockSizeException,
        BadPaddingException
{

    // prepare key
    KeyGenerator keygen = KeyGenerator.getInstance("AES");
    SecretKey aesKey = keygen.generateKey();
    String aesKeyForFutureUse = Base64.getEncoder().encodeToString(
            aesKey.getEncoded()
    );

    // cipher engine
    Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

    // cipher input
    aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
    byte[] clearTextBuff = "Text to encode".getBytes();
    byte[] cipherTextBuff = aesCipher.doFinal(clearTextBuff);

    // recreate key
    byte[] aesKeyBuff = Base64.getDecoder().decode(aesKeyForFutureUse);
    SecretKey aesDecryptKey = new SecretKeySpec(aesKeyBuff, "AES");

    // decipher input
    aesCipher.init(Cipher.DECRYPT_MODE, aesDecryptKey);
    byte[] decipheredBuff = aesCipher.doFinal(cipherTextBuff);
    System.out.println(new String(decipheredBuff));
}

এটি "এনকোড থেকে পাঠ্য" মুদ্রণ করে।

সমাধানটি জাভা ক্রিপ্টোগ্রাফি আর্কিটেকচার রেফারেন্স গাইড এবং https://stackoverflow.com/a/20591539/146745 উত্তরের উপর ভিত্তি করে ।


5
ইসিবি মোডটি কখনও ব্যবহার করবেন না। সময়কাল।
কনস্ট্যান্টিনো স্পারাকিস

1
একই কী দিয়ে একাধিক ব্লকের ডেটা এনক্রিপ্ট করা থাকলে ইসিবি ব্যবহার করা উচিত নয়, সুতরাং "পাঠ্য এনকোড করার জন্য" এটি যথেষ্ট ভাল। stackoverflow.com/a/1220869/146745
andrej

@ অ্যান্ড্রয়েডদেভ কী তৈরির জন্য প্রস্তুত করা হয়েছে বিভাগ: aesKey = keygen.generateKey ()
Andrej

1

এটি গৃহীত উত্তরের চেয়ে উন্নতি।

পরিবর্তন করুন:

(1) এলোমেলো IV ব্যবহার করে এবং এটি এনক্রিপ্ট করা পাঠ্যে প্রিপেন্ড করুন

(২) একটি পাসফ্রেজ থেকে কী তৈরি করতে SHA-256 ব্যবহার করা

(3) অ্যাপাচি কমন্সে কোনও নির্ভরতা নেই

public static void main(String[] args) throws GeneralSecurityException {
    String plaintext = "Hello world";
    String passphrase = "My passphrase";
    String encrypted = encrypt(passphrase, plaintext);
    String decrypted = decrypt(passphrase, encrypted);
    System.out.println(encrypted);
    System.out.println(decrypted);
}

private static SecretKeySpec getKeySpec(String passphrase) throws NoSuchAlgorithmException {
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    return new SecretKeySpec(digest.digest(passphrase.getBytes(UTF_8)), "AES");
}

private static Cipher getCipher() throws NoSuchPaddingException, NoSuchAlgorithmException {
    return Cipher.getInstance("AES/CBC/PKCS5PADDING");
}

public static String encrypt(String passphrase, String value) throws GeneralSecurityException {
    byte[] initVector = new byte[16];
    SecureRandom.getInstanceStrong().nextBytes(initVector);
    Cipher cipher = getCipher();
    cipher.init(Cipher.ENCRYPT_MODE, getKeySpec(passphrase), new IvParameterSpec(initVector));
    byte[] encrypted = cipher.doFinal(value.getBytes());
    return DatatypeConverter.printBase64Binary(initVector) +
            DatatypeConverter.printBase64Binary(encrypted);
}

public static String decrypt(String passphrase, String encrypted) throws GeneralSecurityException {
    byte[] initVector = DatatypeConverter.parseBase64Binary(encrypted.substring(0, 24));
    Cipher cipher = getCipher();
    cipher.init(Cipher.DECRYPT_MODE, getKeySpec(passphrase), new IvParameterSpec(initVector));
    byte[] original = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted.substring(24)));
    return new String(original);
}

একটি হ্যাশ এখনও পাসওয়ার্ড ভিত্তিক কী প্রজন্মের ফাংশন / পিবিকেডিএফ নয়। হয় আপনি একটি এলোমেলো কী ব্যবহার করেন বা আপনি PBKDF যেমন PBKDF2 / পাসওয়ার্ড ভিত্তিক এনক্রিপশন ব্যবহার করেন।
মার্টেন বোদেউয়েস

@ মার্টেনবোডওয়েস আপনি কি উন্নতির পরামর্শ দিতে পারেন?
wvdz

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

@ মার্টেনবোডউইজগুলি আমি ভেবেছিলাম এটি একটি সাধারণ সমাধান হতে পারে। কৌতূহলের বাইরে, এই কোডটি যেমন ব্যবহার করছেন তখন নির্দিষ্ট দুর্বলতাগুলি কী হবে?
wvdz

0

স্প্রিং বুট সহ java.util.Base64 ব্যবহার করে আরেকটি সমাধান

এনক্রিপ্টর ক্লাস

package com.jmendoza.springboot.crypto.cipher;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Component
public class Encryptor {

    @Value("${security.encryptor.key}")
    private byte[] key;
    @Value("${security.encryptor.algorithm}")
    private String algorithm;

    public String encrypt(String plainText) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key, algorithm);
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        return new String(Base64.getEncoder().encode(cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8))));
    }

    public String decrypt(String cipherText) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key, algorithm);
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return new String(cipher.doFinal(Base64.getDecoder().decode(cipherText)));
    }
}

এনক্রিপ্টর নিয়ন্ত্রণকারী শ্রেণি

package com.jmendoza.springboot.crypto.controller;

import com.jmendoza.springboot.crypto.cipher.Encryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/cipher")
public class EncryptorController {

    @Autowired
    Encryptor encryptor;

    @GetMapping(value = "encrypt/{value}")
    public String encrypt(@PathVariable("value") final String value) throws Exception {
        return encryptor.encrypt(value);
    }

    @GetMapping(value = "decrypt/{value}")
    public String decrypt(@PathVariable("value") final String value) throws Exception {
        return encryptor.decrypt(value);
    }
}

application.properties

server.port=8082
security.encryptor.algorithm=AES
security.encryptor.key=M8jFt46dfJMaiJA0

উদাহরণ

HTTP: // স্থানীয় হোস্ট: 8082 / সাইফার / এনক্রিপ্ট / jmendoza

2h41HH8Shzc4BRU3hVDOXA ==

HTTP: // স্থানীয় হোস্ট: 8082 / সাইফার / ডিক্রিপ্ট / 2h41HH8Shzc4BRU3hVDOXA ==

jmendoza


-1

গৃহীত উত্তরের অনুকূলিত সংস্করণ।

  • কোন তৃতীয় পক্ষের libs

  • এনক্রিপ্ট করা বার্তার মধ্যে চতুর্থ অন্তর্ভুক্ত (সর্বজনীন হতে পারে)

  • পাসওয়ার্ড যে কোনও দৈর্ঘ্যের হতে পারে

কোড:

import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.util.Base64;

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

public class Encryptor {
    public static byte[] getRandomInitialVector() {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
            byte[] initVector = new byte[cipher.getBlockSize()];
            randomSecureRandom.nextBytes(initVector);
            return initVector;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static byte[] passwordTo16BitKey(String password) {
        try {
            byte[] srcBytes = password.getBytes("UTF-8");
            byte[] dstBytes = new byte[16];

            if (srcBytes.length == 16) {
                return srcBytes;
            }

            if (srcBytes.length < 16) {
                for (int i = 0; i < dstBytes.length; i++) {
                    dstBytes[i] = (byte) ((srcBytes[i % srcBytes.length]) * (srcBytes[(i + 1) % srcBytes.length]));
                }
            } else if (srcBytes.length > 16) {
                for (int i = 0; i < srcBytes.length; i++) {
                    dstBytes[i % dstBytes.length] += srcBytes[i];
                }
            }

            return dstBytes;
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static String encrypt(String key, String value) {
        return encrypt(passwordTo16BitKey(key), value);
    }

    public static String encrypt(byte[] key, String value) {
        try {
            byte[] initVector = Encryptor.getRandomInitialVector();
            IvParameterSpec iv = new IvParameterSpec(initVector);
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());
            return Base64.getEncoder().encodeToString(encrypted) + " " + Base64.getEncoder().encodeToString(initVector);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public static String decrypt(String key, String encrypted) {
        return decrypt(passwordTo16BitKey(key), encrypted);
    }

    public static String decrypt(byte[] key, String encrypted) {
        try {
            String[] encryptedParts = encrypted.split(" ");
            byte[] initVector = Base64.getDecoder().decode(encryptedParts[1]);
            if (initVector.length != 16) {
                return null;
            }

            IvParameterSpec iv = new IvParameterSpec(initVector);
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            byte[] original = cipher.doFinal(Base64.getDecoder().decode(encryptedParts[0]));

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }
}

ব্যবহার:

String key = "Password of any length.";
String encrypted = Encryptor.encrypt(key, "Hello World");
String decrypted = Encryptor.decrypt(key, encrypted);
System.out.println(encrypted);
System.out.println(decrypted);

উদাহরণ আউটপুট:

QngBg+Qc5+F8HQsksgfyXg== yDfYiIHTqOOjc0HRNdr1Ng==
Hello World

আপনার পাসওয়ার্ড ডেরাইভেশন ফাংশনটি নিরাপত্তাহীন। আমি e.printStackTrace()তথাকথিত অনুকূলিত কোডটি আশা করবো না expect
মার্টেন বোদেউয়েস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.