【问题标题】:Convert a binary string (SecureRandom.random_bytes) into a hexadecimal string?将二进制字符串 (SecureRandom.random_bytes) 转换为十六进制字符串?
【发布时间】:2016-10-16 09:37:24
【问题描述】:

我的 AES-256 CBC Ruby encryption implementationgenerating 32 字节密钥和 16 字节 iv:

key         = SecureRandom.random_bytes(32)      # => "m\xD4\x90\x85\xF9\xCD\x13\x98\xAB\v\xBB\xCD\x0E\x17\xFAA\xF9\x99\xAF\e\x8A\xB5\x8Ate\x93[m\x9As\xC7\xCB"
iv          = SecureRandom.random_bytes(16)      # => "\xDF\x95[\xD5\xDD(\x0F\xB8SE\xFCZr\xF1\xB1W"
ruby_cipher = SymmetricEncryption::Cipher.new(
  key: key,
  iv: iv,
  cipher_name: 'aes-256-cbc'
)
ruby_cipher.encrypt("Hello!")                    # => 'qAnTLy7jyiLRkUqBnME8sw=='

问题:

如何将密钥和 iv 转换为十六进制字符串,以便将它们传输到其他应用程序?

上下文:

在另一个使用 Javascript via CryptoJS 的应用程序中,我需要接收密钥和 iv 并将它们转换回这样的字节:

CryptoJS.AES.encrypt(
    "Hello!",
    CryptoJS.enc.Utf8.parse(key),
    { iv: CryptoJS.enc.Utf8.parse(iv) }
).toString()                                     // 'qAnTLy7jyiLRkUqBnME8sw=='

在第三个 PHP 应用程序中,我将像这样直接使用十六进制字符串:

<?php
openssl_encrypt(
  'Hello!', 'aes-256-cbc',
  key,
  0,
  iv
);                                               // => 'qAnTLy7jyiLRkUqBnME8sw=='

【问题讨论】:

    标签: ruby encryption binary hex


    【解决方案1】:

    我认为这应该可以完成工作:

    key = SecureRandom.random_bytes(32)
    key_as_str = key.each_byte.map{ |byte| '%02x' % byte }.join
    

    我确实使用以下脚本验证了此解决方案:

    test.rb

    require 'securerandom'
    require 'symmetric-encryption'
    
    key         = SecureRandom.random_bytes(32) 
    iv          = SecureRandom.random_bytes(16)
    ruby_cipher = SymmetricEncryption::Cipher.new(
      key: key,
      iv: iv,
      cipher_name: 'aes-256-cbc'
    )
    hex_key = key.each_byte.map{ |byte| '%02x' % byte }.join 
    hex_iv =  iv.each_byte.map{ |byte| '%02x' % byte }.join 
    encoded = ruby_cipher.encrypt("Hello!") 
    
    puts "Ruby encoded: #{encoded}"
    
    system("php test.php #{hex_key} #{hex_iv}")
    

    test.php

    <?php
    $encoded = openssl_encrypt(
      'Hello!', 'aes-256-cbc',
      hex2bin($argv[1]), 
      0,
      hex2bin($argv[2]) 
    ); 
    
    print "php  encoded: $encoded\n";
    

    在我的机器上看起来一样。

    【讨论】:

    • 您确定这会生成正确的十六进制字符串吗?当尝试将十六进制转换的字符串插入到我的 Javascript 实现中时,我得到了不同的加密结果。我也尝试过在 Ruby 中加密一个字符串,然后尝试在 Javascript 中解密它,但没有成功。
    • 你说得对。我的第一个代码没有为小数字添加 0。例如 10 被简单地转换为 a 而不是 0a。我确实增强了我的示例。
    • 嗯,奇怪,我的 Ruby 和 JS 实现仍然得到不同的结果。但是你确定转换本身是正确的吗?那么也许我的问题出在其他地方。
    • 在 js 中你使用了CryptoJS.enc.Hex.parse 吗?您的示例使用CryptoJS.enc.Utf8.parse。我认为对于 php 你必须使用key = hex2bin('....')
    • 你是对的,这就是问题所在。感谢您的帮助!
    【解决方案2】:

    您可以像 SecureRandom 为他们的 #hex 方法所做的那样做:

    key = SecureRandom.random_bytes(32)
    key_as_hex = key.unpack('H*')[0]
    

    (对于这个非插值字符串,在这里使用单引号字符串可以正常工作,并且对 rubocop 友好。)

    【讨论】:

      猜你喜欢
      • 2019-08-23
      • 1970-01-01
      • 2017-02-23
      • 2014-08-03
      • 2015-06-21
      • 2014-10-24
      • 2012-03-04
      • 2015-06-27
      相关资源
      最近更新 更多