我使用Ruby的Open SSL bindings进行AES-256加密。我可以加密非空字符串。但是,在尝试加密空字符串时,Ruby会引发异常,抱怨数据不能为空。 如何使用Ruby的OpenSSL绑定加密空字符串?
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>'
我正在编写一个ETL程序,用于将数据从一个数据库迁移到SqlServer数据库。必须先对源数据库中的某些列进行加密,然后再将其写入目标数据库。源列可以包含任何数据,包括空字符串。目标列通常是不可为空的。目标列将由.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代码。
答案 0 :(得分:7)
As suggested by @ArtjomB,就像不使用空字符串调用Cipher#update
一样简单。 Cipher#final
返回的值然后正确加密空字符串。
public long InvoiceID { get; set; }
答案 1 :(得分:2)
如果你可以使用DBMS提供的加密功能,那么MySQL AES_ENCRYPT
似乎能够加密空字符串。
例如:
UPDATE some_table
SET some_column = AES_ENCRYPT('',UNHEX('F3229A0B371ED2D9441B830D21A390C3'));
默认情况下它是AES-128,我猜这将是一个问题,因为你需要AES-256。此外,不确定您使用的是哪个DBMS以及该DBMS是否具有加密功能。