সংকেতলিপি রচনার বিদ্যা

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

শুধুমাত্র Android Keystore সিস্টেমের সাথে কোনও পরিষেবা প্রদানকারীকে নির্দিষ্ট করুন

আপনি Android Keystore সিস্টেম ব্যবহার করলে, আপনাকে অবশ্যই কোনও পরিষেবা প্রদানকারী নির্দিষ্ট করতে হবে।

তবে, অন্যান্য পরিস্থিতিতে, Android কোনও নির্দিষ্ট অ্যালগরিদমের জন্য কোনও নির্দিষ্ট প্রদানকারীর গ্যারান্টি দেয় না। Android Keystore সিস্টেম ব্যবহার না করে কোনও পরিষেবা প্রদানকারীকে নির্দিষ্ট করলে ভবিষ্যতে রিলিজের ক্ষেত্রে মানানসই সংক্রান্ত সমস্যা হতে পারে।

সাজেস্ট করা অ্যালগরিদম বেছে নিন

কোন অ্যালগরিদম ব্যবহার করবেন তা বেছে নেওয়ার স্বাধীনতা আপনার থাকলে (যেমন, থার্ড-পার্টি সিস্টেমের সাথে মানানসই হওয়ার প্রয়োজন না থাকলে), আমরা নিম্নলিখিত অ্যালগরিদম ব্যবহার করার সাজেশন দিই:

শ্রেণী সাজেশন
সাইফার ২৫৬-বিট কী (যেমন AES/GCM/NoPadding) সহ CBC বা GCM মোডে AES
MessageDigest SHA-2 ফ্যামিলি (যেমন SHA-256)
Mac SHA-2 ফ্যামিলি HMAC (যেমন HMACSHA256)
স্বাক্ষর ECDSA সহ SHA-2 ফ্যামিলি (যেমন SHA256withECDSA)

সাধারণ ক্রিপ্টোগ্রাফিক অপারেশন পারফর্ম করা

নিম্নলিখিত বিভাগে স্নিপেট অন্তর্ভুক্ত আছে যা দেখায় যে কীভাবে আপনি অ্যাপে সাধারণ ক্রিপ্টোগ্রাফিক অপারেশন সম্পূর্ণ করতে পারবেন।

মেসেজ এনক্রিপ্ট করা

Kotlin

val plaintext: ByteArray = ...
val keygen = KeyGenerator.getInstance("AES")
keygen.init(256)
val key: SecretKey = keygen.generateKey()
val cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING")
cipher.init(Cipher.ENCRYPT_MODE, key)
val ciphertext: ByteArray = cipher.doFinal(plaintext)
val iv: ByteArray = cipher.iv

জাভা

byte[] plaintext = ...;
KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init(256);
SecretKey key = keygen.generateKey();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] ciphertext = cipher.doFinal(plaintext);
byte[] iv = cipher.getIV();

মেসেজের সারাংশ তৈরি করুন

Kotlin

val message: ByteArray = ...
val md = MessageDigest.getInstance("SHA-256")
val digest: ByteArray = md.digest(message)

জাভা

byte[] message = ...;
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(message);

ডিজিটাল স্বাক্ষর জেনারেট করুন

আপনার কাছে একটি PrivateKey অবজেক্ট থাকতে হবে যার মধ্যে সাইনিং কী থাকবে, যা আপনি রানটাইমে তৈরি করতে পারেন, আপনার অ্যাপের সাথে বান্ডেল করা ফাইল থেকে পড়তে পারেন অথবা আপনার প্রয়োজন অনুযায়ী অন্য কোনও সোর্স থেকে পেতে পারেন।

Kotlin

val message: ByteArray = ...
val key: PrivateKey = ...
val s = Signature.getInstance("SHA256withECDSA")
        .apply {
            initSign(key)
            update(message)
        }
val signature: ByteArray = s.sign()

জাভা

byte[] message = ...;
PrivateKey key = ...;
Signature s = Signature.getInstance("SHA256withECDSA");
s.initSign(key);
s.update(message);
byte[] signature = s.sign();

ডিজিটাল স্বাক্ষর যাচাই করা

আপনার কাছে একটি PublicKey অবজেক্ট থাকতে হবে যাতে স্বাক্ষরকারীর সর্বজনীন কী থাকে, যা আপনি আপনার অ্যাপের সাথে বান্ডিল করা ফাইল থেকে পড়তে পারেন, সার্টিফিকেট থেকে এক্সট্র্যাক্ট করতে পারেন, অথবা আপনার প্রয়োজন অনুযায়ী অন্য কোনো সোর্স থেকে পেতে পারেন।

Kotlin

val message: ByteArray = ...
val signature: ByteArray = ...
val key: PublicKey = ...
val s = Signature.getInstance("SHA256withECDSA")
        .apply {
            initVerify(key)
            update(message)
        }
val valid: Boolean = s.verify(signature)

জাভা

byte[] message = ...;
byte[] signature = ...;
PublicKey key = ...;
Signature s = Signature.getInstance("SHA256withECDSA");
s.initVerify(key);
s.update(message);
boolean valid = s.verify(signature);

প্রয়োগ সংক্রান্ত জটিলতা

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

OAEP MGF1 মেসেজ ডাইজেস্ট

RSA OAEP সাইফার দুটি ভিন্ন মেসেজ ডাইজেস্ট দ্বারা প্যারামিটারাইজ করা হয়: "প্রধান" ডাইজেস্ট এবং MGF1 ডাইজেস্ট। Cipherটি আইডেন্টিফায়ার আছে যার মধ্যে ডাইজেস্টের নাম অন্তর্ভুক্ত আছে, যেমন Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding"), যা মূল ডাইজেস্ট নির্দিষ্ট করে এবং MGF1 ডাইজেস্ট নির্দিষ্ট করে না। Android-এর জন্য Keystore, SHA-1, MGF1 ডাইজেস্টের জন্য ব্যবহার করা হয়, যেখানে অন্যান্য Android ক্রিপ্টোগ্রাফিক প্রদানকারীর জন্য, দুটি ডাইজেস্ট একই।

আপনার অ্যাপ ব্যবহার করে এমন ডাইজেস্টের উপর আরও নিয়ন্ত্রণ পেতে, OAEPPadding সহ একটি সাইফারের জন্য অনুরোধ করুন, যেমন Cipher.getInstance("RSA/ECB/OAEPPadding")-এ, এবং স্পষ্টভাবে উভয় ডাইজেস্ট বেছে নিতে OAEPParameterSpec থেকে init() প্রদান করুন। এটি নিম্নলিখিত কোডে দেখানো হয়েছে:

Kotlin

val key: Key = ...
val cipher = Cipher.getInstance("RSA/ECB/OAEPPadding")
        .apply {
            // To use SHA-256 the main digest and SHA-1 as the MGF1 digest
            init(Cipher.ENCRYPT_MODE, key, OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT))
            // To use SHA-256 for both digests
            init(Cipher.ENCRYPT_MODE, key, OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT))
        }

জাভা

Key key = ...;
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding");
// To use SHA-256 the main digest and SHA-1 as the MGF1 digest
cipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT));
// To use SHA-256 for both digests
cipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));

বন্ধ করা হয়েছে এমন কার্যকারিতা

নিম্নলিখিত বিভাগে বন্ধ হয়ে যাওয়া কার্যকারিতা সম্পর্কে বর্ণনা করা হয়েছে। আপনার অ্যাপে এটি ব্যবহার করবেন না।

Bouncy Castle অ্যালগরিদম

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

Kotlin

Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC")
// OR
Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"))

জাভা

Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC");
// OR
Cipher.getInstance("AES/CBC/PKCS7PADDING", Security.getProvider("BC"));

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

ইনিশিয়ালাইজেশন ভেক্টর ছাড়া পাসওয়ার্ড-ভিত্তিক এনক্রিপশন সাইফার

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

PBE সাইফার ব্যবহার করার সময়, নিম্নলিখিত কোড স্নিপেটে যেমন দেখানো হয়েছে, সবসময় একটি এক্সপ্লিসিট IV পাস করুন:

Kotlin

val key: SecretKey = ...
val cipher = Cipher.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC")
val iv = ByteArray(16)
SecureRandom().nextBytes(iv)
cipher.init(Cipher.ENCRYPT_MODE, key, IvParameterSpec(iv))

জাভা

SecretKey key = ...;
Cipher cipher = Cipher.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC");
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));

ক্রিপ্টো পরিষেবা প্রদানকারী

Android 9 (API লেভেল ২৮) থেকে, ক্রিপ্টো জাভা ক্রিপ্টোগ্রাফি আর্কিটেকচার (JCA) প্রদানকারীকে সরিয়ে দেওয়া হয়েছে। আপনার অ্যাপ যদি Crypto প্রোভাইডারের ইনস্ট্যান্সের জন্য অনুরোধ করে, যেমন নিম্নলিখিত পদ্ধতি কল করার মাধ্যমে, তাহলে একটি NoSuchProviderException ঘটে।

Kotlin

SecureRandom.getInstance("SHA1PRNG", "Crypto")

জাভা

SecureRandom.getInstance("SHA1PRNG", "Crypto");

Jetpack security-crypto লাইব্রেরি

security-crypto Jetpack লাইব্রেরির সব API ভার্সন 1.1.0-এর স্টেবল রিলিজে বন্ধ করা হয়েছে। এই লাইব্রেরির আর কোনও ভার্সন রিলিজ করা হবে না।

আপনার অ্যাপ মডিউলের build.gradle ফাইলে নিম্নলিখিত ডিপেন্ডেন্সিগুলির মধ্যে কোনও একটি থাকলে, অবচিতি সংক্রান্ত অ্যানোটেশন দেখা যাবে:

গ্ৰুভি

dependencies {
    implementation "androidx.security:security-crypto:1.1.0"
    // or
    implementation "androidx.security:security-crypto-ktx:1.1.0"
}

Kotlin

dependencies {
    implementation("androidx.security:security-crypto:1.1.0")
    // or
    implementation("androidx.security:security-crypto-ktx:1.1.0")
}

কাজ করে এমন অ্যালগরিদম

এগুলি হল JCA অ্যালগরিদম শনাক্তকারী যা Android-এ কাজ করে: