सुरक्षित प्रोग्रामिंग में पाठ 1: अपने आईवी का पुन: उपयोग न करें
मैंने हाल ही में सैमसंग भेद्यता [ यहाँ ] पर एक लेख लिखा था , और एक टिप्पणी ने कहा ... "यह एक पुरानी बग है, IV (इनिशियलाइज़ेशन वेक्टर्स) का पुन: उपयोग एक बहुत ही बुनियादी समस्या लगती है"। इसके चेहरे पर, टिप्पणी शायद पर्याप्त विवरण में नहीं जाती है, इसलिए मैं कोशिश करूँगा और "बग" की व्याख्या करूँगा और आशा करता हूँ कि यह आश्चर्यजनक रूप से खराब कोडिंग है ... सुरक्षा के मामले में लगभग लापरवाह है, और यहां तक कि देखा भी जा सकता है एक जानबूझकर पिछले दरवाजे के रूप में ।
और एक "बहुत बुनियादी समस्या" के लिए, यह शायद "बेहद खराब कोडिंग" होनी चाहिए, और यह "बग" कभी भी विश्वसनीय वातावरण में कभी नहीं देखा जाना चाहिए। यह नौसिखिया भेद्यता के साथ क्रिप्टोग्राफी कैसे काम करता है, इस बारे में ज्ञान की लगभग पूरी कमी दिखाता है। कागज यहाँ है [1]:
वास्तव में, यह फिर से WEP की तरह है, और जहाँ WEP Wifi पद्धति में एक छोटा IV (इनिशियलाइज़ेशन वेक्टर) था, और जब इसे रोल आउट किया गया, तो केवल XOR सिफर स्ट्रीम करना और प्लेनटेक्स्ट की खोज करना संभव था। स्लीप प्रोग्राम एक दिन से भी कम समय में सिस्को के किसी भी एक्सेस प्वाइंट को क्रैक कर सकता है। सौभाग्य से अब हम WPA-2 का उपयोग करते हैं, और जिसमें IV का पुन: उपयोग नहीं होता है।
मैं यह दिखाने की उम्मीद करता हूं कि अगर इस तरह का कोड किसी उपयोगकर्ता के डिवाइस के पास आता है तो हमें चिंतित होना चाहिए। वास्तव में, यदि किसी मोबाइल फोन में कभी पिछला दरवाजा होता , तो यह यह वाला हो सकता था।
यदि आप "बग" के बारे में पढ़ना चाहते हैं, तो यहां देखें:
सैमसंग गैलेक्सी उपकरणों में क्रिप्टो बग: विश्वसनीय निष्पादन वातावरण (टीईई) को तोड़नाएक बुरा "बग"
अब, मैं समझाता हूँ कि यह "बग" कितना बुरा है। यदि आप साइबर सुरक्षा में हैं, तो आपको उम्मीद है कि एईएस जीसीएम एक स्ट्रीम सिफर है। इसके साथ, हम एक गुप्त कुंजी मान और एक नमक मान (एक IV - इनिशियलाइज़ेशन वेक्टर) लेते हैं और एक छद्म अनंत कीस्ट्रीम उत्पन्न करते हैं। हमारा प्लेनटेक्स्ट हमारे सिफरटेक्स्ट का निर्माण करने के लिए कीस्ट्रीम के साथ केवल XOR-ed है:
तब नमक का मान हमेशा यादृच्छिक होना चाहिए, क्योंकि एक निश्चित नमक मूल्य हमेशा समान प्लेटेक्स्ट के लिए समान कीस्ट्रीम का उत्पादन करेगा, और जहां हम XOR-ing सिफर स्ट्रीम द्वारा कीस्ट्रीम को प्रकट कर सकते हैं, और अंततः प्लेनटेक्स्ट को प्रकट कर सकते हैं। कुंजी रैपिंग के मामले में, प्लेनटेक्स्ट एक एन्क्रिप्शन कुंजी है, और इस प्रकार TEE द्वारा उपयोग की जाने वाली एन्क्रिप्शन कुंजी प्रकट हो जाएगी।
यदि हम IVs का पुन: उपयोग करते हैं, तो ईव XOR सिफर स्ट्रीम को एक साथ करने और कीस्ट्रीम (K) को प्रकट करने में सक्षम होगा। वहां से वह हर सिफर स्ट्रीम को डिक्रिप्ट कर सकती है, लेकिन केवल K के साथ सिफर स्ट्रीम को XOR-ing कर सकती है।
कोडन
एईएस जीसीएम (गैलॉइस काउंटर मोड) एईएस के लिए एक स्ट्रीम सिफर मोड है। यह सीटीआर मोड पर आधारित है लेकिन स्ट्रीम सिफर में परिवर्तित हो जाता है। यह एन्क्रिप्शन/डिक्रिप्शन प्रक्रिया में कम विलंबता प्रदान करता है और प्रक्रिया में तेज़ है। इसके साथ ही यह ऑथेंटिकेशन के लिए AEAD मोड को इंटीग्रेट करता है। लेकिन जैसा कि GCM एक स्ट्रीम सिफर मोड है, यह पुन: उपयोग IV हमले के लिए खुला है। इसके साथ, सिफर का IV (इनिशियलाइज़ेशन वेक्टर) दो सिफर संदेशों के लिए समान है। इसके बाद हम सिफर स्ट्रीम कुंजी ( K ) प्रकट करने के लिए एक साथ दो सिफर स्ट्रीम को XOR कर सकते हैं। फिर हम K के साथ किसी भी सिफर स्ट्रीम को XOR-ing करके प्लेन टेक्स्ट को प्रकट कर सकते हैं ।
तो, चलिए ऐसा करने के लिए कुछ कोड आजमाते हैं। इस मामले में, मैं विधि के मूल सिद्धांतों को दिखाने के लिए गोलंग का उपयोग करूंगा। मैं इस मामले में "0123456789ABCDEF" (16 बाइट्स - 128-बिट कुंजी), और "0123456789AB" (12 बाइट्स - 96 बिट्स) [ यहाँ ]:
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
"os"
)
func xor(a, b []byte, length int) []byte {
c := make([]byte, len(a))
for i := 0; i < length; i++ {
c[i] = a[i] ^ b[i]
}
return (c)
}
func main() {
nonce := []byte("0123456789AB")
key := []byte("0123456789ABCDEF")
block, err := aes.NewCipher(key)
if err != nil {
panic(err.Error())
}
msg1 := "hello"
msg2 := "Hello"
argCount := len(os.Args[1:])
if argCount > 0 {
msg1 = (os.Args[1])
}
if argCount > 1 {
msg2 = (os.Args[2])
}
plaintext1 := []byte(msg1)
plaintext2 := []byte(msg2)
aesgcm, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
ciphertext1 := aesgcm.Seal(nil, nonce, plaintext1, nil)
ciphertext2 := aesgcm.Seal(nil, nonce, plaintext2, nil)
xor_length := len(ciphertext1)
if len(ciphertext1) > len(ciphertext2) {
xor_length = len(ciphertext2)
}
ciphertext_res := xor(ciphertext1, ciphertext2, xor_length)
fmt.Printf("Message 1:\t%s\n", msg1)
fmt.Printf("Message 2:\t%s\n", msg2)
fmt.Printf("Cipher 1:\t%x\n", ciphertext1)
fmt.Printf("Cipher 2:\t%x\n", ciphertext2)
fmt.Printf("Key:\t\t%x\n", key)
fmt.Printf("Nonce:\t\t%x\n", nonce)
fmt.Printf("XOR:\t\t%x\n", ciphertext_res)
plain1, _ := aesgcm.Open(nil, nonce, ciphertext1, nil)
plain2, _ := aesgcm.Open(nil, nonce, ciphertext2, nil)
fmt.Printf("Decrypted:\t%s\n", plain1)
fmt.Printf("Decrypted:\t%s\n", plain2)
}
Message 1: hello
Message 2: Hello
Cipher 1: 7fcbe7378c2b87a5dfb2803d4fcaca8d5cde86dbfa
Cipher 2: 5fcbe7378cf8c68b82a2b8d705354e8d6c0502cef2
Key: 30313233343536373839414243444546
Nonce: 303132333435363738394142
XOR: 2000000000d3412e5d1038ea4aff840030db841508
Decrypted: hello
Decrypted: Hello
Message 1: hello
Message 2: Cello
Cipher 1: 7fcbe7378c2b87a5dfb2803d4fcaca8d5cde86dbfa
Cipher 2: 54cbe7378c5638db82df34a46172abed62b887aa48
Key: 30313233343536373839414243444546
Nonce: 303132333435363738394142
XOR: 2b000000007dbf7e5d6db4992eb861603e660171b2
Decrypted: hello
Decrypted: Cello
निष्कर्ष
यह बेहद खराब कोडिंग है , और मैं एक नए स्नातक से इस स्तर के कार्यान्वयन की अपेक्षा नहीं करता। यदि टीईई के भीतर कोड बनाने वाली एक विकास टीम एक पुन: उपयोग IV हमले को नहीं समझती है, तो इससे पहले कि वे किसी और विश्वसनीय कोड को स्पर्श करें, उन्हें एक सुरक्षित कोडिंग प्रशिक्षण पाठ्यक्रम पर जाने की आवश्यकता है। अगर यह जानबूझकर पिछले दरवाजे थे, तो यह एक पूरी कहानी है। मुझे उम्मीद है, यह सिर्फ एक बग था, लेकिन हमें वास्तव में टीईई के निर्माण में अपने ज्ञान में सुधार करने की जरूरत है, क्योंकि ये भी क्लाउड-आधारित सिस्टम के भीतर चलते हैं।
संदर्भ
[1] शकेव्स्की, ए., रोनेन, ई., और वूल, ए. (2022)। अंधेरे में विश्वास मर जाता है: सैमसंग के ट्रस्टज़ोन कीमास्टर डिज़ाइन पर प्रकाश डालता है। क्रिप्टोलॉजी ईप्रिंट आर्काइव ।