क्रिप्टोग्राफी

इस दस्तावेज़ में, Android की क्रिप्टोग्राफ़िक सुविधाओं का सही तरीके से इस्तेमाल करने के बारे में बताया गया है. साथ ही, उनके इस्तेमाल के कुछ उदाहरण भी दिए गए हैं. अगर आपके ऐप्लिकेशन को बेहतर कुंजी सुरक्षा की ज़रूरत है, तो Android Keystore सिस्टम का इस्तेमाल करें.

Android Keystore सिस्टम की मदद से ही, सेवा देने वाली कंपनी या संस्था के बारे में जानकारी दें

अगर Android Keystore सिस्टम का इस्तेमाल किया जा रहा है, तो आपको प्रोवाइडर की जानकारी ज़रूर देनी होगी.

हालांकि, अन्य स्थितियों में Android, किसी एल्गोरिदम के लिए किसी खास सेवा देने वाली कंपनी की गारंटी नहीं देता. Android Keystore सिस्टम का इस्तेमाल किए बिना किसी प्रोवाइडर को तय करने से, आने वाले समय में रिलीज़ होने वाले वर्शन में समस्याएं आ सकती हैं.

सुझाया गया एल्गोरिदम चुनना

जब आपके पास यह चुनने का विकल्प हो कि किस एल्गोरिदम का इस्तेमाल करना है (जैसे, जब आपको तीसरे पक्ष के सिस्टम के साथ काम करने वाले एल्गोरिदम की ज़रूरत न हो), तो हमारा सुझाव है कि आप इन एल्गोरिदम का इस्तेमाल करें:

कक्षा सुझाव
साइफ़र 256 बिट की कुंजियों के साथ, सीबीसी या जीसीएम मोड में AES (जैसे, AES/GCM/NoPadding)
MessageDigest SHA-2 फ़ैमिली (जैसे कि SHA-256)
Mac SHA-2 फ़ैमिली का एचएमएसी (जैसे, HMACSHA256)
सिग्नेचर ईसीडीएसए के साथ 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

Java

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)

Java

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()

Java

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)

Java

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

लागू करने से जुड़ी समस्याएं

Android क्रिप्टोग्राफ़ी को लागू करने से जुड़ी कुछ ऐसी जानकारी है जो सामान्य नहीं है. हालांकि, यह जानकारी इसलिए मौजूद है, ताकि यह पक्का किया जा सके कि क्रिप्टोग्राफ़ी की सुविधा, Android के साथ काम करती है. इस सेक्शन में, उन गड़बड़ियों के बारे में बताया गया है जो आपको सबसे ज़्यादा दिख सकती हैं.

OAEP MGF1 मैसेज डाइजेस्ट

RSA OAEP सिफ़र को दो अलग-अलग मैसेज डाइजेस्ट के हिसाब से पैरामीटर में बांटा जाता है: “मुख्य” डाइजेस्ट और MGF1 डाइजेस्ट. ऐसे Cipher आइडेंटिफ़ायर हैं जिनमें डाइजेस्ट के नाम शामिल हैं. जैसे, Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding"). यह मुख्य डाइजेस्ट के बारे में बताता है और MGF1 डाइजेस्ट के बारे में कोई जानकारी नहीं देता. Android Keystore के लिए, MGF1 डाइजेस्ट के लिए SHA-1 का इस्तेमाल किया जाता है. वहीं, Android के अन्य क्रिप्टोग्राफ़िक प्रोवाइडर के लिए, दोनों डाइजेस्ट एक जैसे होते हैं.

आपके ऐप्लिकेशन में इस्तेमाल किए जाने वाले डाइजेस्ट पर ज़्यादा कंट्रोल पाने के लिए, OAEPPadding के साथ सिफ़र का अनुरोध करें. जैसे, Cipher.getInstance("RSA/ECB/OAEPPadding") में किया गया है. साथ ही, दोनों डाइजेस्ट को साफ़ तौर पर चुनने के लिए, init() को OAEPParameterSpec दें. यह जानकारी यहां दिए गए कोड में दिखाई गई है:

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))
        }

Java

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 provider से साफ़ तौर पर अनुरोध किया है. जैसे, यहां दिए गए उदाहरण में दिखाया गया है:

Kotlin

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

Java

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

सिर्फ़ Android Keystore सिस्टम की मदद से किसी सेवा देने वाली कंपनी को चुनने के बारे में जानकारी देने वाले सेक्शन में बताया गया है कि किसी सेवा देने वाली कंपनी को चुनने का अनुरोध करने से बचना चाहिए. अगर आपने उस दिशा-निर्देश का पालन किया है, तो इस सुविधा को बंद करने से आप पर कोई असर नहीं पड़ेगा.

इनिशलाइज़ेशन वेक्टर के बिना, पासवर्ड पर आधारित एन्क्रिप्शन सिफ़र

पासवर्ड पर आधारित एन्क्रिप्शन (पीबीई) सिफ़र, जिन्हें इनिशियलाइज़ेशन वेक्टर (आईवी) की ज़रूरत होती है, वे इसे कुंजी से पा सकते हैं. हालांकि, इसके लिए कुंजी को सही तरीके से बनाया जाना चाहिए. इसके अलावा, वे इसे साफ़ तौर पर पास किए गए आईवी से भी पा सकते हैं. अगर आपने ऐसी PBE कुंजी पास की है जिसमें IV शामिल नहीं है और आपने साफ़ तौर पर कोई IV पास नहीं किया है, तो Android पर मौजूद PBE सिफ़र फ़िलहाल IV को शून्य मान लेते हैं.

पीबीई सिफ़र का इस्तेमाल करते समय, हमेशा एक साफ़ तौर पर बताया गया 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))

Java

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 (एपीआई लेवल 28) से, Crypto Java Cryptography Architecture (JCA) provider को हटा दिया गया है. अगर आपका ऐप्लिकेशन, क्रिप्टो प्रोवाइडर के इंस्टेंस का अनुरोध करता है, तो NoSuchProviderException गड़बड़ी होती है. जैसे, नीचे दिए गए तरीके को कॉल करके अनुरोध करना.

Kotlin

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

Java

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

Jetpack security-crypto लाइब्रेरी

वर्शन 1.1.0 की स्टेबल रिलीज़ में, security-crypto Jetpack लाइब्रेरी के सभी एपीआई बंद कर दिए गए थे. इस लाइब्रेरी का कोई नया वर्शन रिलीज़ नहीं किया जाएगा.

अगर आपके ऐप्लिकेशन मॉड्यूल की 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")
}

साथ काम करने वाले एल्गोरिदम

Android पर काम करने वाले JCA एल्गोरिदम आइडेंटिफ़ायर ये हैं: