加密空字符串

韦恩·康拉德(Wayne Conrad)

我正在使用Ruby的Open SSL绑定来进行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>'

版本号

  • 红宝石-2.2.2p95
  • OpenSSL :: VERSION是“ 1.1.0”
  • Microsoft SQL Server 2014(12.0.2000.8)

为什么要加密空字符串?

我正在编写一个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代码。

韦恩·康拉德(Wayne Conrad)

正如@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(""))       # ""

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章