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

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

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

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

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

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

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

कक्षा सुझाव
Cipher 256-बिट कुंजियों (जैसे, AES/GCM/NoPadding) के साथ CBC या GCM मोड में AES
MessageDigest SHA-2 फ़ैमिली (जैसे, SHA-256)
Mac SHA-2 फ़ैमिली एचएमएसी (जैसे, HMACSHA256)
हस्ताक्षर ईसीडीएसए के साथ SHA-2 फ़ैमिली (जैसे, SHA256withECDSA)

क्रिप्टोग्राफ़िक ऑपरेशन करना

यहां दिए गए सेक्शन में ऐसे स्निपेट शामिल हैं जिनसे पता चलता है कि अपने ऐप्लिकेशन में, क्रिप्टोग्राफ़िक से जुड़े सामान्य काम कैसे पूरे किए जा सकते हैं.

मैसेज को एन्क्रिप्ट करना

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

मैसेज का डाइजेस्ट जनरेट करना

KotlinJava
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 ऑब्जेक्ट होना चाहिए जिसमें साइनिंग पासकोड हो. इसे रनटाइम पर जनरेट किया जा सकता है, ऐप्लिकेशन के साथ बंडल की गई फ़ाइल से पढ़ा जा सकता है या अपनी ज़रूरतों के हिसाब से किसी दूसरे सोर्स से लिया जा सकता है.

KotlinJava
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 ऑब्जेक्ट होना चाहिए जिसमें हस्ताक्षर करने वाले व्यक्ति की सार्वजनिक कुंजी हो. इसे ऐप्लिकेशन के साथ बंडल की गई फ़ाइल से पढ़ा जा सकता है, सर्टिफ़िकेट से निकाला जा सकता है या अपनी ज़रूरत के हिसाब से किसी अन्य सोर्स से लिया जा सकता है.

KotlinJava
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 के पासवर्ड सेव करने की सुविधा के लिए, MGF1 डाइजेस्ट के लिए SHA-1 का इस्तेमाल किया जाता है. वहीं, Android के अन्य क्रिप्टोग्राफ़िक प्रोवाइडर के लिए, दोनों डाइजेस्ट एक जैसे होते हैं.

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

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

KotlinJava
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 सिस्टम की मदद से, सेवा देने वाली किसी कंपनी के बारे में बताने वाले सेक्शन में बताया गया है कि किसी खास कंपनी से अनुरोध करने का सुझाव नहीं दिया जाता. अगर आपने उस दिशा-निर्देश का पालन किया है, तो इस सुविधा को बंद किए जाने का आप पर कोई असर नहीं पड़ेगा.

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

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

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

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

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

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

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

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

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

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