【问题标题】:"key must be 16 bytes" AES-128 CBC, with MD5 Key+IV“密钥必须是 16 字节”AES-128 CBC,带有 MD5 密钥+IV
【发布时间】:2019-09-30 23:29:24
【问题描述】:

我正在与一个 API 交互,该 API 要求我在 CBC 模式下使用 AES-128 加密某些内容。

他们说对于密钥和 IV,我需要使用他们给我的字符串的 16 字节 MD5 哈希。

我用谷歌搜索了一段时间,看起来所有 MD5 都是 16 字节,为什么这不起作用?

  key = Digest::MD5.hexdigest(temp_token)
  cipher = OpenSSL::Cipher::AES.new(128, :CBC)
  cipher.encrypt
  cipher.key = key # ArgumentError: key must be 16 bytes
  cipher.iv = key # ArgumentError: iv must be 16 bytes

  encrypted = cipher.update(joined_params) + cipher.final
  Base64.urlsafe_encode64(encrypted)

【问题讨论】:

  • 如果他们的外部服务实现如此糟糕,想象一下他们的内部系统实现有多糟糕...... 颤抖......

标签: ruby-on-rails ruby encryption openssl ruby-on-rails-5


【解决方案1】:

我认为根本原因是OpenSSL::Cipher::AES#key 必须以一个 16 字节的字符串作为其键。

[27] pry(main)> cipher = OpenSSL::Cipher::AES.new(128, :CBC)
=> #<OpenSSL::Cipher::AES:0x00007f7f876f1608>
[28] pry(main)> cipher.encrypt
=> #<OpenSSL::Cipher::AES:0x00007f7f876f1608>
[30] pry(main)> cipher.random_key.length
=> 16

Digest::MD5.hexdigest无关

[26] pry(main)> key = Digest::MD5.hexdigest('abc').first(16)
=> "900150983cd24fb0"
[27] pry(main)> cipher = OpenSSL::Cipher::AES.new(128, :CBC)
=> #<OpenSSL::Cipher::AES:0x00007f7f876f1608>
[28] pry(main)> cipher.encrypt
=> #<OpenSSL::Cipher::AES:0x00007f7f876f1608>
[29] pry(main)> cipher.key = key
=> "900150983cd24fb0"

参考:OpenSSL::Cipher

【讨论】:

    【解决方案2】:

    问题是我需要改用Digest::MD5.digest

    【讨论】:

    • 我很高兴你只花了 10 分钟就学会了二进制和十六进制之间的区别,但我想人们必须自己找出答案,我觉得这个 Q/A 没什么意义。跨度>
    • 好吧,我们都不能在堆栈溢出时成为 Maarten Bodewes。你得从某个地方开始。
    • 没错,我很幸运,因为我确实没有多少选择可以在值得信赖的 MSX 家用计算机上了解它。但是,恐怕找不到问题。请注意,MD5 不再被认为是一种好的散列算法。如果重用密钥,IV 应该不同,因此您不应重用 temp_token
    • 这是一个我无法控制的支付处理 API。我被他们所有过时或糟糕的安全方法所困扰。我已经在他们的 gem 中发现了一个缺陷,他们使用的是 hexidigest 方法,但他们没有意识到它会被截断(在较新的版本中已修复以引发错误)。
    猜你喜欢
    • 1970-01-01
    • 2020-04-28
    • 2021-09-23
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    • 2012-11-14
    相关资源
    最近更新 更多