2016-01-28 16 views
6

एन्क्रिप्ट करें मैं एईएस -256 एन्क्रिप्शन करने के लिए रुबी के Open SSL bindings का उपयोग कर रहा हूं। मैं एक गैर खाली स्ट्रिंग एन्क्रिप्ट कर सकते हैं। हालांकि, एक खाली स्ट्रिंग को एन्क्रिप्ट करने का प्रयास करते समय, रूबी ने अपवाद उठाया कि डेटा खाली नहीं होना चाहिए। रुबी के ओपनएसएसएल बाइंडिंग का उपयोग करके मैं एक खाली स्ट्रिंग को कैसे एन्क्रिप्ट कर सकता हूं?खाली स्ट्रिंग

कोड समस्या

require "openssl" 

KEY = OpenSSL::Cipher::Cipher.new("aes-256-cbc").random_key 

def encrypt(plaintext) 
    cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc") 
    cipher.encrypt 
    iv = cipher.random_iv 
    cipher.iv = iv 
    cipher.key = KEY 
    ciphertext = cipher.update(plaintext) # <- ArgumentError here 
    ciphertext << cipher.final 
    [iv, ciphertext] 
end 

def decrypt(iv, ciphertext) 
    cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc") 
    cipher.decrypt 
    cipher.iv = iv 
    cipher.key = KEY 
    plaintext = cipher.update(ciphertext) 
    plaintext << cipher.final 
    plaintext 
end 

p decrypt(*encrypt("foo")) # "foo" 

p decrypt(*encrypt("")) 
# /tmp/foo.rb:11:in `update': data must not be empty (ArgumentError) 
#   from /tmp/foo.rb:11:in `encrypt' 
#   from /tmp/foo.rb:27:in `<main>' 

संस्करण

  • माणिक 2.2.2p95
  • OpenSSL पुन: पेश करने :: संस्करण है "1.1.0"
  • Microsoft SQL सर्वर 2014 (12.0.2000.8)

मैं खाली तारों को एन्क्रिप्ट क्यों करना चाहता हूं?

मैं एक डेटाबेस से SQL सर्वर सर्वर पर डेटा माइग्रेट करने के लिए ETL प्रोग्राम लिख रहा हूं। स्रोत डेटाबेस से कुछ कॉलम गंतव्य डेटाबेस पर लिखने से पहले एन्क्रिप्ट किया जाना चाहिए। स्रोत कॉलम में खाली स्ट्रिंग सहित कोई भी डेटा हो सकता है। गंतव्य कॉलम आमतौर पर गैर-शून्य होते हैं। गंतव्य कॉलम को .NET कोड द्वारा डिक्रिप्ट किया जाएगा।

लक्ष्य # 1: एन्क्रिप्टेड फ़ील्ड के बारे में कोई जानकारी नहीं, जिसमें यह भी मौजूद है या नहीं, इसे ठीक से डिक्रिप्ट किए बिना पुनर्प्राप्त करने योग्य होना चाहिए। एक एन्क्रिप्टेड रिक्त स्ट्रिंग किसी अन्य एन्क्रिप्टेड डेटा से अलग नहीं होनी चाहिए।

लक्ष्य # 2: .NET कोड जो इन मानों को डिक्रिप्ट करेगा, विशेष रूप से खाली तारों को संभालने की आवश्यकता नहीं है।

यदि मैं खाली तारों को एन्क्रिप्ट करने के लिए openssl प्राप्त कर सकता हूं, तो मैं इन दोनों लक्ष्यों को प्राप्त करूंगा।

वर्कअराउंड - रिक्त स्ट्रिंग

मैं सिर्फ रिक्त स्ट्रिंग एन्क्रिप्ट नहीं कर सकता एन्क्रिप्ट मत करो, के माध्यम से उन्हें गुजर।

def encrypt(plaintext) 
    return plaintext if plaintext.empty? 
    ... 
end 

def decrypt(iv, ciphertext) 
    return ciphertext if ciphertext.empty? 
    ... 
end 

यह उजागर जानकारी का नुकसान है, और सहयोग कोड की आवश्यकता होती है की भी .net पक्ष पर लिखा होना चाहिए।

वर्कअराउंड - डिक्रिप्शन के बाद प्लेन

मैं एन्क्रिप्शन से पहले प्लेन टेक्स्ट के लिए कुछ निरंतर स्ट्रिंग जोड़ सकते हैं करने के लिए कुछ निरंतर जोड़ें, और हटाने यह:

PLAINTEXT_SUFFIX = " " 

def encrypt(plaintext) 
    plaintext += PLAINTEXT_SUFFIX 
    ... 
end 

def decrypt(iv, ciphertext) 
    ... 
    plaintext.chomp(PLAINTEXT_SUFFIX) 
end 

यह खाल डेटा मौजूद है या नहीं, लेकिन अभी भी सहयोगी .NET कोड की आवश्यकता है।

+1

ओपनएसएसएल पीकेसीएस # 7 पैडिंग का समर्थन करता है, इसलिए यह काम करना चाहिए। यह शायद एक बग रिपोर्ट के रूप में बेहतर अनुकूल है। बीटीडब्ल्यू, क्या आपने सादे टेक्स्ट खाली होने पर बस 'cipher.update' को छोड़ने की कोशिश की है? उस मामले में 'cipher.final' पर्याप्त हो सकता है। –

+0

@ArtjomB। मैंने सिफर # अपडेट को कॉल छोड़ने का प्रयास किया था। जब मैंने उस समय नोटिस नहीं किया था, तो आईडी 10 टी त्रुटि के कारण मैंने इसे पहले कोशिश की थी। यह बदल जाता है कि समाधान है। क्या आप इसे एक उत्तर के रूप में जोड़ना चाहते हैं? –

+0

आप इसे स्वयं जोड़ सकते हैं। मुझे रूबी के बारे में कोई जानकारी नहीं है और मैं इस विशेष समय पर सीखना शुरू नहीं करना चाहता हूं। :) –

उत्तर

7

As suggested by @ArtjomB, यह खाली स्ट्रिंग के साथ Cipher#update पर कॉल नहीं करना उतना आसान है। Cipher#final द्वारा लौटाया गया मान ठीक से एक खाली स्ट्रिंग को एन्क्रिप्ट करता है।

require "openssl" 

KEY = OpenSSL::Cipher::Cipher.new("aes-256-cbc").random_key 

def encrypt(plaintext) 
    cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc") 
    cipher.encrypt 
    iv = cipher.random_iv 
    cipher.iv = iv 
    cipher.key = KEY 
    ciphertext = "" 
    ciphertext << cipher.update(plaintext) unless plaintext.empty? 
    ciphertext << cipher.final 
    [iv, ciphertext] 
end 

def decrypt(iv, ciphertext) 
    cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc") 
    cipher.decrypt 
    cipher.iv = iv 
    cipher.key = KEY 
    plaintext = cipher.update(ciphertext) 
    plaintext << cipher.final 
end 

p decrypt(*encrypt("foo")) # "foo" 
p decrypt(*encrypt(""))  # "" 
2

यदि आप डीबीएमएस प्रदान किए गए एन्क्रिप्शन फ़ंक्शंस का उपयोग कर सकते हैं, तो MySQL AES_ENCRYPT, रिक्त स्ट्रिंग को एन्क्रिप्ट करने में सक्षम प्रतीत होता है।

उदाहरण के लिए:

UPDATE some_table 
    SET some_column = AES_ENCRYPT('',UNHEX('F3229A0B371ED2D9441B830D21A390C3')); 

यह एईएस 128 डिफ़ॉल्ट रूप से, मैं अनुमान लगा रहा हूँ के रूप में आप एईएस 256 की जरूरत है कि एक समस्या हो जाएगा। साथ ही, यह सुनिश्चित न करें कि आप कौन से डीबीएमएस का उपयोग कर रहे हैं और क्या डीबीएमएस में एन्क्रिप्शन फ़ंक्शन हैं।

+0

मैंने एन्क्रिप्शन करने के लिए डेटाबेस का उपयोग करने के बारे में सोचा नहीं था। गंतव्य डीबी एसक्लसेवर 2014 है। –

+1

@WayneConrad उस सर्वर के बारे में बहुत कुछ नहीं पता, लेकिन ऐसा लगता है कि एईएस -256 एन्क्रिप्शन समर्थन है। आपको रिक्त स्ट्रिंग एन्क्रिप्शन के लिए इसका परीक्षण करना पड़ सकता है। –

+0

@WayneConrad एक साइड नोट पर, आपके एसओ प्रोफाइल पेज की वजह से - मैंने पाया कि कुछ [रूबी एक्सटेंशन] (http://extensions.rubyforge.org/rdoc/index.html) कहा गया था जिसमें 'प्रतीक' के पहले संस्करण थे # to_proc', जो रेल में और फिर रूबी कोर में समेकित हो गया। मैं 2003 में '[दिन, डॉलर]। प्रत्येक (और: दूसरा)' का उपयोग करने के बारे में कुछ जांच कर रहा था।: डी –

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