加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 加密空字符串

发布时间:2020-12-16 23:03:20 所属栏目:百科 来源:网络整理
导读:我使用 Ruby的 Open SSL bindings进行AES-256加密.我可以加密非空字符串.但是,在尝试加密空字符串时,Ruby会引发异常,抱怨数据不能为空.如何使用Ruby的OpenSSL绑定加密空字符串? 代码重现问题 require "openssl"KEY = OpenSSL::Cipher::Cipher.new("aes-256-
我使用 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>'

版本

> ruby??-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代码.

解决方法

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读