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

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

सिर्फ़ Android Keystore सिस्टम का इस्तेमाल करने वाले प्रोवाइडर की जानकारी दें

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

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

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

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

कक्षा सुझाव
Cipher 256-बिट कुंजियों (जैसे, AES/GCM/NoPadding) के साथ CBC या GCM मोड में AES
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 में क्रिप्टोग्राफ़ी लागू करने के बारे में कुछ जानकारी ऐसी है जो सामान्य नहीं लगती. हालांकि, यह जानकारी काम करने से जुड़ी समस्याओं की वजह से मौजूद है. इस सेक्शन में, उन समस्याओं के बारे में बताया गया है जिनका सामना आपको सबसे ज़्यादा बार करना पड़ सकता है.

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

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

अपने ऐप्लिकेशन में इस्तेमाल किए जाने वाले डाइजेस्ट पर ज़्यादा कंट्रोल पाने के लिए, Cipher.getInstance("RSA/ECB/OAEPPadding") के तौर पर, OAEPPडिंग के साथ साइफ़र का अनुरोध करें. साथ ही, दोनों डाइजेस्ट चुनने के लिए, 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 एल्गोरिदम

बाउंसी कैसल में कई एल्गोरिदम का इस्तेमाल किया जाता है अब काम नहीं करता. इससे सिर्फ़ उन मामलों पर असर पड़ता है जहां आपने खास तौर पर, बाउंसी कैसल प्रोवाइडर से अनुरोध करने के लिए कहा है, जैसा कि इस उदाहरण में दिखाया गया है:

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 से लिया गया हो. अगर आपने ऐसी PBE पासकी दी है जिसमें कोई आईवी नहीं है और आपने साफ़ तौर पर कोई आईवी नहीं दिया है, तो Android पर मौजूद PBE सिफर फ़िलहाल आईवी को शून्य मान लेते हैं.

PBE सिफर का इस्तेमाल करते समय, हमेशा साफ़ तौर पर आईवी पास करें, जैसा कि नीचे दिए गए कोड स्निपेट में दिखाया गया है:

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) प्रोवाइडर को हटा दिया गया है. अगर आपका ऐप्लिकेशन, क्रिप्टो प्रोवाइडर के इंस्टेंस का अनुरोध करता है, तो NoSuchProviderException का इस्तेमाल किया जाता है. उदाहरण के लिए, नीचे दिए गए तरीके का इस्तेमाल करके.

Kotlin

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

Java

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

Jetpack की सुरक्षा क्रिप्टो लाइब्रेरी

Jetpack की सुरक्षा से जुड़ी क्रिप्टो लाइब्रेरी अब काम नहीं करती. इसका असर सिर्फ़ उन मामलों पर पड़ता है जहां आपके ऐप्लिकेशन मॉड्यूल की build.gradle फ़ाइल में ये डिपेंडेंसी मौजूद हों:

Groovy

dependencies {
    implementation "androidx.security:security-crypto:1.0.0"
}

Kotlin

dependencies {
    implementation("androidx.security:security-crypto:1.0.0")
}

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

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