2016-01-28 14 views
6

Ich verwende Open SSL bindings von Ruby, um AES-256-Verschlüsselung zu tun. Ich kann eine nicht leere Zeichenfolge verschlüsseln. Beim Versuch, eine leere Zeichenfolge zu verschlüsseln, löst Ruby eine Ausnahme aus, in der es heißt, dass die Daten nicht leer sein dürfen. Wie kann ich eine leere Zeichenfolge mit den OpenSSL-Bindungen von Ruby verschlüsseln?Verschlüsseln leerer String

Code, um das Problem

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>' 

Versionen

  • rubin 2.2.2p95
  • OpenSSL :: VERSION ist "1.1.0"
  • Microsoft SQL Server 2014 zu reproduzieren (12.0.2000.8)

Warum möchte ich leere Zeichenfolgen verschlüsseln?

Ich schreibe ein ETL Programm, um Daten von einer Datenbank in eine SqlServer-Datenbank zu migrieren. Bestimmte Spalten aus der Quelldatenbank müssen verschlüsselt werden, bevor sie in die Zieldatenbank geschrieben werden. Die Quellenspalten können beliebige Daten einschließlich leerer Zeichenfolgen enthalten. Die Zielspalten sind normalerweise nicht nullfähig. Die Zielspalten werden mit dem .net-Code entschlüsselt.

Ziel # 1: Keine Informationen über das verschlüsselte Feld, einschließlich, ob es überhaupt existiert oder nicht, sollten wiederhergestellt werden können, ohne es richtig zu entschlüsseln. Eine verschlüsselte leere Zeichenfolge sollte von anderen verschlüsselten Daten nicht zu unterscheiden sein.

Ziel # 2: Der .NET-Code, der diese Werte entschlüsseln wird, sollte nicht speziell mit leeren Zeichenfolgen umgehen.

Wenn ich openssl bekommen kann, um leere Zeichenfolgen zu verschlüsseln, werde ich diese beiden Ziele erreichen.

Umgehung - Verschlüsseln Sie keine leeren Zeichenfolge

Ich konnte einfach nicht leere Zeichenfolge verschlüsseln, so dass sie die Durchreise.

Dies hat die Nachteile der Offenlegung von Informationen und auch der Anforderung, dass kooperierender Code auf der .net-Seite geschrieben werden muss.

Umgehung - eine Konstante zu dem unverschlüsselten Text hinzufügen

ich zu dem unverschlüsselten Text vor der Verschlüsselung einen konstanten String hinzufügen könnte, und entfernen Sie es nach der Entschlüsselung:

PLAINTEXT_SUFFIX = " " 

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

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

Dies verbirgt, ob die Daten oder nicht vorhanden ist, erfordert aber immer noch die Zusammenarbeit mit .net-Code.

+1

OpenSSL unterstützt PKCS # 7 Padding, so sollte dies funktionieren. Dies ist wahrscheinlich besser als Fehlerbericht geeignet. Übrigens, hast du schon versucht, 'cipher.update' zu ​​überspringen, wenn der Klartext leer ist? 'cipher.final' könnte in diesem Fall ausreichend sein. –

+0

@ ArtjomB. Ich hatte versucht, den Anruf zu Cipher # Update wegzulassen. Es hat nicht funktioniert, als ich es vorher aufgrund eines ID10T-Fehlers versuchte, als ich es zu der Zeit nicht bemerkte. Das ist die Lösung. Könnten Sie das bitte als Antwort hinzufügen? –

+0

Sie können es selbst hinzufügen. Ich habe keine Ahnung von Rubin und möchte nicht zu diesem bestimmten Zeitpunkt anfangen zu lernen. :) –

Antwort

2

Wenn Sie die von DBMS bereitgestellten Verschlüsselungsfunktionen verwenden können, scheint MySQL AES_ENCRYPT in der Lage zu sein, leere Zeichenfolgen zu verschlüsseln.

Zum Beispiel:

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

Es ist AES-128 standardmäßig Ich vermute, dass ein Problem sein wird, wie Sie AES-256 benötigen. Außerdem nicht sicher, welches DBMS Sie verwenden und ob dieses DBMS Verschlüsselungsfunktionen hat.

+0

Ich hatte nicht gedacht, die Datenbank für die Verschlüsselung zu verwenden. Die Ziel-DB ist SqlServer 2014. –

+1

@WayneConrad Ich weiß nicht viel über diesen Server, aber es scheint AES-256-Verschlüsselung zu unterstützen. Möglicherweise müssen Sie es für die Verschlüsselung leerer Zeichenfolgen testen. –

+0

@WayneConrad Nebenbei bemerkt, wegen Ihrer SO-Profilseite - ich entdeckte, dass es etwas namens [Ruby Extensions] (http://extensions.rubyforge.org/rdoc/index.html) gab, das erste Versionen von 'Symbol hatte # to_proc', das wurde in Rails und dann in Ruby Core assimiliert. Ich habe einige Nachforschungen darüber angestellt, ob Sie wirklich '[Tag, Dollar] .eines (&: ein anderes)' 2003 benutzt haben.: D –

Verwandte Themen