代码之家  ›  专栏  ›  技术社区  ›  Rob Cameron

加密很难:aes加密到hex

  •  2
  • Rob Cameron  · 技术社区  · 15 年前

    所以,我有一个应用程序正在使用coldfusion加密字符串。Coldfusion的Bulit in Encryption帮助程序使其非常简单:

    encrypt('string_to_encrypt','key','AES','HEX')
    

    我要做的是使用ruby创建与coldfusion脚本创建的相同的加密字符串。不幸的是,加密是人类所知的最令人困惑的计算机科学课题。

    我找到了几个使用openssl库的助手方法,为您提供了一个非常简单的加密/解密方法。下面是结果字符串:

    "\370\354D\020\357A\227\377\261G\333\314\204\361\277\250"
    

    在我看来是Unicode的。我试过几个库将其转换为十六进制,但它们都说它包含无效字符。尝试将其解压缩会导致:

    string = "\370\354D\020\357A\227\377\261G\333\314\204\361\277\250"
    string.unpack('U')
    ArgumentError: malformed UTF-8 character
      from (irb):19:in `unpack'
      from (irb):19
    

    在一天结束时,它应该是这样的(coldfusion encrypt方法的输出):

    F8E91A689565ED24541D2A0109F201EF
    

    当然,这是假设所有的填充、初始化向量、盐类、cypher类型和一百万个其他可能的差异都排成一行。

    下面是我用来加密/解密的简单脚本:

    def aes(m,k,t)
      (aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc').send(m)).key = Digest::SHA256.digest(k)
      aes.update(t) << aes.final
    end
    
    def encrypt(key, text)
      aes(:encrypt, key, text)
    end
    
    def decrypt(key, text)
      aes(:decrypt, key, text)
    end
    

    有什么帮助吗?也许只是一个简单的选项,我可以传递给openssl::cipher::cipher,它会告诉它对最后的字符串进行十六进制编码?

    2 回复  |  直到 13 年前
        1
  •  2
  •   Oleh Khomey    13 年前

    我今天也遇到了类似的问题。我的有点棘手,B/C我没有访问CF代码只有文本加密,密钥和SHA256加密结果。

    Official documentation for Encrypt function 说:

    钥匙 字符串。用于加密字符串的密钥或种子。

    • 对于cfmx_compat算法,任意字符数的任意组合;用作生成32位加密密钥的种子。

    • 对于所有其他算法,使用算法所用格式的密钥。对于这些算法,使用 GenerateSecretKey 功能 生成密钥。

    在我的例子中,我得到了一个32个字符长的md5字符串,这是一个我必须使用的键。

    因为我们不能直接使用 拥有 AES ancryption的密钥-我必须将其转换为相同的格式 生成密钥 有。

    经过一番挖掘,似乎 生成密钥 创建16字节长的随机二进制字符串并将其编码为base64。但是 这很重要 在加密过程中对其进行内部解码。

    所以这是有效的解决方案:

    cf代码:

    plain_key = "REPLACE_ME_WITH_32_HEX_UPPERCASED_CHARS"; // this can be MD5 of some secret string
    encoded_key = ToBase64(BinaryDecode(plain_key, "Hex"));
    base64EncodedResult = Encrypt("PLAIN TEXT", key, "AES", "Base64");
    

    红宝石代码:

    plain_key = "REPLACE_ME_WITH_32_HEX_UPPERCASED_CHARS"
    encoded_key = plain_key.unpack('a2' * 16).map(&:hex).pack('c' * 16) # same as in CF except encoding to Base64
    aes_encrypted = Aes.encrypt('PLAIN TEXT', encoded_key)
    base64_encoded_result = ActiveSupport::Base64.encode64s(aes_encrypted)
    

    AES模块代码:

    # Two changes comparing to author's code:
    # 1) AES-128-ECB instead of AES-256-CBC
    # 2) No key conversion to SHA256
    
    module Aes
      def self.aes(m,k,t)
        (aes = OpenSSL::Cipher::Cipher.new('aes-128-ecb').send(m)).key = k
        aes.update(t) << aes.final
      end
    
      def self.encrypt(text, key)
        aes(:encrypt, key, text)
      end
    
      def self.decrypt(text, key)
        aes(:decrypt, key, text)
      end
    end 
    
        2
  •  1
  •   rud    15 年前

    要将生成的字符串转换为与ColdFusion输出类似的格式,只需使用:

    raw = "\370\354D\020\357A\227\377\261G\333\314\204\361\277\250" 
    raw.unpack('H*').to_s.upcase
    => "F8EC4410EF4197FFB147DBCC84F1BFA8"