2010-10-14 5 views
7

मेरे पास एक वेब आधारित एप्लिकेशन है जिसके लिए सर्वर पर भेजे जाने से पहले छवियों को एन्क्रिप्ट किया जाना आवश्यक है, और सर्वर से ब्राउज़र में लोड होने के बाद डिक्रिप्ट किया गया है, जब उपयोगकर्ता द्वारा सही कुंजी दी गई थी।ब्राउज़र के भीतर जावास्क्रिप्ट का उपयोग कर छवियों को डिक्रिप्ट करना

[संपादित करें:। लक्ष्य है कि मूल छवि और चाबी उपयोगकर्ता के कंप्यूटर ताकि वह/वह सर्वर पर भरोसा करने की आवश्यकता नहीं है कभी नहीं छोड़ देता है]

मेरा पहला दृष्टिकोण का उपयोग कर छवि पिक्सल एन्क्रिप्ट करने के लिए था एईएस और छवि शीर्षलेख छूटे छोड़ दें। मुझे एन्क्रिप्टेड छवि को पीएनजी जैसे लापरवाही प्रारूप में सहेजना पड़ा। जेपीजी जैसे हानिकारक प्रारूप एईएस एन्क्रिप्टेड बिट्स को बदल देगा और उन्हें डिक्रिप्ट करने के लिए असंभव बना देगा।

अब एन्क्रिप्टेड छवियों को ब्राउज़र में लोड किया जा सकता है, एक पूरी तरह से स्कैम्बल दिखने के साथ। यहां मेरे पास Image.canvas.getContext("2d").getImageData() का उपयोग कर आरजीबी पिक्सल के रूप में छवि डेटा में पढ़ने के लिए जावास्क्रिप्ट कोड है, उपयोगकर्ता को मुख्य रूप प्राप्त करें, एईएस का उपयोग करके पिक्सेल डिक्रिप्ट करें, कैनवास को दोबारा हटाएं और उपयोगकर्ता को डिक्रिप्ट की गई छवि दिखाएं।

यह दृष्टिकोण काम करता है लेकिन दो प्रमुख समस्याओं का सामना करता है।

पहली समस्या यह है कि पूरी तरह से स्कैम्बल छवि को लापरवाही प्रारूप में सहेजना बहुत बाइट लेता है, 3 बाइट प्रति पिक्सेल के करीब।

दूसरी समस्या यह है कि ब्राउज़र में बड़ी छवियों को डिक्रिप्ट करने में काफी समय लगता है।

यह दूसरे दृष्टिकोण को आमंत्रित करता है, जो वास्तविक पिक्सल की बजाय छवि शीर्षलेखों को एन्क्रिप्ट करना है। लेकिन मुझे उन्हें डिक्रिप्ट करने के लिए जावास्क्रिप्ट में छवि शीर्षलेखों में पढ़ने का कोई तरीका नहीं मिला है। कैनवास केवल पहले ही डिकंप्रेस्ड पिक्सेल डेटा देता है। वास्तव में, ब्राउज़र छवि को बदले गए हेडर के साथ अमान्य के रूप में दिखाता है।

पहला दृष्टिकोण सुधारने या दूसरे दृष्टिकोण को संभव बनाने या अन्य दृष्टिकोण प्रदान करने के लिए कोई सुझाव बहुत सराहना की जाती है।

लंबे पद के लिए खेद है।

+0

"सर्वर पर भेजे जाने से पहले छवियों को एन्क्रिप्ट करने की आवश्यकता है" सोच रहा है ... सर्वर पर भेजने से पहले आपको छवि डेटा कैसे प्राप्त होता है? – oberhamsi

+2

"होस्ट सबूत होस्टिंग" वह शब्द है जिसे आप ढूंढ रहे हैं। – Acorn

+0

बिल्कुल, धन्यवाद। – timeon

उत्तर

3

एन्क्रिप्ट और बेस 64 छवि सहेजे जाने पर छवि के कच्चे डेटा को एन्कोड करता है। (आप केवल उस वेब ब्राउज़र पर ऐसा कर सकते हैं जो HTML5 फ़ाइल एपीआई का समर्थन करता है जब तक आप जावा एप्लेट का उपयोग नहीं करते)। जब छवि डाउनलोड की जाती है, इसे अनएकोड करें, इसे डिक्रिप्ट करें, और ब्राउज़र के उपयोग के लिए डेटा यूआरआई बनाएं (या फिर, छवि को प्रदर्शित करने के लिए जावा एप्लेट का उपयोग करें)।

आप नहीं है, तथापि, जरूरत उपयोगकर्ता के लिए सर्वर पर विश्वास करने के लिए सर्वर को भेज सकते हैं क्योंकि जो जावा स्क्रिप्ट कोड यह ग्राहक है, जो किसी को भी करने के लिए छवि की एक प्रतिलिपि भेज सकते हैं जब यह decrypted है करने के लिए करना चाहता है हटा सकते हैं। यह एन्क्रिप्टेड ई-मेल सेवा हैशमेल – के साथ कुछ चिंता है कि सरकार कंपनी को दुर्भावनापूर्ण जावा एप्लेट देने के लिए मजबूर कर सकती है। यह एक असंभव परिदृश्य नहीं है; दूरसंचार कंपनी एटिसलाट ने डिवाइस पर स्पाइवेयर इंस्टॉल करके ब्लैकबेरी संचार को दूर करने का प्रयास किया (http://news.bbc.co.uk/2/hi/technology/8161190.stm)।

यदि आपकी वेबसाइट सार्वजनिक रूप से उपयोग की जाती है, तो आपके उपयोगकर्ताओं के सॉफ़्टवेयर कॉन्फ़िगरेशन पर आपका कोई नियंत्रण नहीं है, इसलिए उनके कंप्यूटर पहले से ही स्पाइवेयर से संक्रमित हो सकते हैं।

+0

धन्यवाद। यह एक दिलचस्प दृष्टिकोण है। जावास्क्रिप्ट एपीआई क्या हैं जो मुझे सर्वर से फाइल डाउनलोड करने, पूरी फाइल को पढ़ने, इसे कुशल बनाने और छवि के रूप में प्रदर्शित होने के लिए डेटा यूआरआई बनाने की अनुमति देगी? अगर मैं ऐसा कर सकता हूं, तो मैं छवि डेटा के बजाय छवि शीर्षलेख एन्क्रिप्ट कर सकता हूं और यह बड़ी एन्क्रिप्टेड फ़ाइलों और धीमी डिक्रिप्शन के लिए समस्याओं को हल करेगा। अब तक मुझे डिस्क पर या स्मृति में अस्थायी रूप से डाउनलोड की गई फ़ाइलों को सहेजने का कोई तरीका नहीं मिला है। – timeon

+0

ट्रस्ट के बारे में आपकी टिप्पणियों के साथ सहमत हैं। यह शायद सर्वर पर छवियों को सुरक्षित रूप से संभालने की सर्वर व्यवस्थापक की तकनीकी क्षमता पर भरोसा करने की आवश्यकता को कम करेगा। लेकिन उसका इरादा नहीं। मैं यहां किसी भी इनपुट का उपयोग कर सकता था। यह छवियों को एन्क्रिप्ट करने का मुख्य प्रेरणा है। क्या कोई प्रमाणन सेवाएं हैं जिनका हम उपयोग कर सकते हैं? हमारा नाम छोटा और अज्ञात है, लेकिन हो सकता है कि हम अपनी प्रक्रिया और कोड प्रमाणित करने के लिए कुछ बड़ा नाम दे सकें? – timeon

+0

नीचे दिए गए लिंक में फ़ाइल फ़ाइल को डाउनलोड करने का तरीका है और इसे डेटा यूआरएल http://ajaxref.com/ch4/datauri.html के माध्यम से एक छवि के रूप में दिखाएं – timeon

0

मैं आपके लक्ष्य पर कुछ हद तक अस्पष्ट हूं।

क्या छवियों को सर्वर पर एन्क्रिप्ट करने की आवश्यकता है? सर्वर पर वास्तविक एन्क्रिप्शन/डिक्रिप्शन करने के बारे में, उपयोगकर्ता को HTTPS कनेक्शन के माध्यम से कुंजी प्रदान करने के साथ कैसे? फिर आप सर्वर पर छवि को एन्क्रिप्ट/डिक्रिप्ट करेंगे और क्लाइंट को नियमित छवि फ़ाइल प्रदान करेंगे।

यदि मैं लक्ष्य को समझ रहा हूं, तो मुझे लगता है कि यह दृष्टिकोण अधिक समझ में आता है, और ब्राउज़र में एन्क्रिप्शन और डिक्रिप्शन करने की कोशिश करने की गड़बड़ी से बचाता है।

+0

उत्तर के लिए धन्यवाद। क्षमा करें मुझे स्पष्ट रूप से कहा जाना चाहिए था। लक्ष्य यह है कि मूल छवि और कुंजी उपयोगकर्ता के कंप्यूटर को कभी नहीं छोड़ती है ताकि उसे सर्वर पर भरोसा करने की आवश्यकता न हो। – timeon

4

आपने मुझे यह प्रयास करने के लिए प्रेरित किया। मैं इसके बारे में blogged और आप a demo here पा सकते हैं।

मैं Crypto-JS इस्तेमाल किया एन्क्रिप्ट और एईएस और खरगोश के साथ डिक्रिप्ट करने के लिए।

सबसे पहले मैं ImageData वस्तु से CanvasPixelArray मिलता है। RGBA लेकिन क्रिप्टो-जे एस एक स्ट्रिंग, नहीं एक सरणी को एन्क्रिप्ट रूप

var ctx = document.getElementById('leif') 
        .getContext('2d'); 
var imgd = ctx.getImageData(0,0,width,height); 
var pixelArray = imgd.data; 

पिक्सेल सारणी प्रत्येक पिक्सेल के लिए चार बाइट्स है। पहले मैंने सरणी से स्ट्रिंग और बैक तक पहुंचने के लिए .join() और .split (",") का उपयोग किया था। यह धीमा था और स्ट्रिंग की तुलना में काफी लंबा हो गया था। असल में चार गुना लंबा। और भी जगह बचाने के लिए मैंने अल्फा चैनल को त्यागने का फैसला किया।

function canvasArrToString(a) { 
    var s=""; 
    // Removes alpha to save space. 
    for (var i=0; i<pix.length; i+=4) { 
    s+=(String.fromCharCode(pix[i]) 
     + String.fromCharCode(pix[i+1]) 
     + String.fromCharCode(pix[i+2])); 
    } 
    return s; 
} 

कि स्ट्रिंग मैं तो क्या एन्क्रिप्ट है। मैंने String Performance an Analysis पढ़ने के बाद + = पर चिपकाया।

var encrypted = Crypto.Rabbit.encrypt(imageString, password); 

मैं एक छोटे से 160x120 पिक्सेल छवि का इस्तेमाल किया। प्रत्येक पिक्सल के लिए चार बाइट्स के साथ जो 76800 बाइट देता है। भले ही मैंने अल्फा चैनल को तोड़ दिया, एन्क्रिप्टेड छवि अभी भी 124680 बाइट्स लेती है, 1.62 गुना बड़ा है। .join का उपयोग करना() यह 384736 बाइट था, 5 गुना बड़ा। मूल छवि की तुलना में यह अभी भी बड़ा कारण यह है कि क्रिप्टो-जेएस बेस 64 एन्कोडेड स्ट्रिंग देता है और इसमें 37% की तरह कुछ जोड़ता है।

इससे पहले कि मैं यह कैनवास मैं इसे एक सरणी के लिए फिर से कन्वर्ट करने के लिए किया था के लिए वापस लिख सकते हैं।

function canvasStringToArr(s) { 
    var arr=[]; 
    for (var i=0; i<s.length; i+=3) { 
    for (var j=0; j<3; j++) { 
     arr.push(s.substring(i+j,i+j+1).charCodeAt()); 
    } 
    arr.push(255); // Hardcodes alpha to 255. 
    } 
    return arr; 
} 

डिक्रिप्शन सरल है।

var arr=canvasStringToArr(
      Crypto.Rabbit.decrypt(encryptedString, password)); 
imgd.data=arr; 
ctx.putImageData(imgd,0,0); 

फ़ायरफ़ॉक्स, गूगल क्रोम, WebKit3.1 (Android 2.2), आईओएस 4.1 में परीक्षण किया गया, और ओपेरा का एक बहुत ही हाल ही में रिलीज।

alt text

0

मैं इसी तरह कुछ करना चाहता था: सर्वर पर एक एन्क्रिप्टेड gif है और मैं, डाउनलोड डिक्रिप्ट, और जावास्क्रिप्ट में यह प्रदर्शित करना चाहते हैं। मैं इसे काम करने में सक्षम था और सर्वर पर संग्रहीत फ़ाइल मूल प्लस कुछ बाइट्स (शायद 32 बाइट्स तक) के समान आकार है। यह वह कोड है जो फ़ाइल calendar.gif फ़ाइल के एईएस एन्क्रिप्शन करता है और VB.Net में लिखा गया calendar.gif.enc बनाता है।

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     Dim AES As New System.Security.Cryptography.RijndaelManaged 
     Dim encryption_key As String = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4" 
     AES.Key = HexStringToBytes(encryption_key) 
     Dim iv_string As String = "000102030405060708090A0B0C0D0E0F" 
     'System.IO.File.ReadAllBytes("calendar.gif") 
     'Dim test_string As String = "6bc1bee22e409f96e93d7e117393172a" 
     AES.Mode = Security.Cryptography.CipherMode.CBC 
     AES.IV = HexStringToBytes(iv_string) 
     Dim Encrypter As System.Security.Cryptography.ICryptoTransform = AES.CreateEncryptor 
     Dim b() As Byte = System.IO.File.ReadAllBytes("calendar.gif") 
     System.IO.File.WriteAllBytes("calendar.gif.enc", (Encrypter.TransformFinalBlock(System.IO.File.ReadAllBytes("calendar.gif"), 0, b.Length))) 
    End Sub 

यह जावास्क्रिप्ट कोड है कि बाइनरी के रूप में calendar.gif.enc डाउनलोड करता है, decrypts है, और एक छवि बनाता है:

function wordArrayToBase64(wordArray) { 
     var words = wordArray.words; 
     var sigBytes = wordArray.sigBytes; 

     // Convert 
     var output = ""; 
     var chr = []; 
     for(var i = 0; i < sigBytes; i++) { 
     chr.push((words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff); 
     if(chr.length == 3) { 
      var enc = [ 
      (chr[0] & 0xff) >> 2, 
      ((chr[0] & 3) << 4) | ((chr[1] & 0xff) >> 4), 
      ((chr[1] & 15) << 2) | ((chr[2] & 0xff) >> 6), 
      chr[2] & 63 
      ]; 
      for(var j = 0; j < 4; j++) { 
      output += Base64._keyStr.charAt(enc[j]); 
      } 
      chr = []; 
     } 
     } 
     if(chr.length == 1) { 
     chr.push(0,0); 
     var enc = [ 
      (chr[0] & 0xff) >> 2, 
      ((chr[0] & 3) << 4) | ((chr[1] & 0xff) >> 4), 
      ((chr[1] & 15) << 2) | ((chr[2] & 0xff) >> 6), 
      chr[2] & 63 
     ]; 
     enc[2] = enc[3] = 64; 
     for(var j = 0; j < 4; j++) { 
      output += Base64._keyStr.charAt(enc[j]); 
     } 
     } else if(chr.length == 2) { 
     chr.push(0); 
     var enc = [ 
      (chr[0] & 0xff) >> 2, 
      ((chr[0] & 3) << 4) | ((chr[1] & 0xff) >> 4), 
      ((chr[1] & 15) << 2) | ((chr[2] & 0xff) >> 6), 
      chr[2] & 63 
     ]; 
     enc[3] = 64; 
     for(var j = 0; j < 4; j++) { 
      output += Base64._keyStr.charAt(enc[j]); 
     } 
     } 
    return(output); 
    } 
    var xhr = new XMLHttpRequest(); 
    xhr.overrideMimeType('image/gif; charset=x-user-defined'); 
    xhr.onreadystatechange = function() { 
    if(xhr.readyState == 4) { 
     var key = CryptoJS.enc.Hex.parse('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'); 
     var iv = CryptoJS.enc.Hex.parse('000102030405060708090A0B0C0D0E0F'); 
     var aesEncryptor = CryptoJS.algo.AES.createDecryptor(key, { iv: iv }); 
     var words = []; 
     for(var i=0; i < (xhr.response.length+3)/4; i++) { 
     var newWord = (xhr.response.charCodeAt(i*4+0)&0xff) << 24; 
     newWord += (xhr.response.charCodeAt(i*4+1)&0xff) << 16; 
     newWord += (xhr.response.charCodeAt(i*4+2)&0xff) << 8; 
     newWord += (xhr.response.charCodeAt(i*4+3)&0xff) << 0; 
     words.push(newWord); 
     }    
     var inputWordArray = CryptoJS.lib.WordArray.create(words, xhr.response.length); 
     var ciphertext0 = aesEncryptor.process(inputWordArray); 
     var ciphertext1 = aesEncryptor.finalize(); 

     $('body').append('<img src="data:image/gif;base64,' + wordArrayToBase64(ciphertext0.concat(ciphertext1)) + '">'); 
     $('body').append('<p>' + wordArrayToBase64(ciphertext0.concat(ciphertext1)) + '</p>'); 
    } 
    }; 

चेतावनियां:

  • मैं एक निश्चित चतुर्थ और फिक्स्ड पासवर्ड का इस्तेमाल किया। आपको एन्क्रिप्शन के दौरान एक यादृच्छिक चतुर्थ उत्पन्न करने के लिए कोड को संशोधित करना चाहिए और आउटपुट फ़ाइल के पहले बाइट्स के रूप में उन्हें प्रीपेड करना चाहिए। इन बाइट्स को निकालने के लिए जावास्क्रिप्ट को भी संशोधित करने की आवश्यकता है।
  • पासवर्ड की लंबाई तय की जानी चाहिए: एईएस -256 के लिए 256-बिट्स। यदि पासवर्ड 256 बाइट्स नहीं है, तो एक संभावना है कि एईएस हैशिंग को एन्क्रिप्शन और डिक्रिप्शन दोनों में लंबाई में 256 बिट्स के लिए पासवर्ड हैश करना है।
  • आपको crypto-js की आवश्यकता होगी।
  • ओवरराइड माइमटाइप पुराने ब्राउज़र पर काम नहीं कर सकता है। आपको इसकी आवश्यकता है ताकि बाइनरी डेटा ठीक से डाउनलोड हो जाए।
संबंधित मुद्दे

 संबंधित मुद्दे