Ruby Ruby 解密 AES

liujinxia · 2015年11月30日 · 最后由 uestc_bird 回复于 2016年11月30日 · 9977 次阅读
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex

class AESCrypto():
    def __init__(self,key):
        self.key = key
        self.mode = AES.MODE_CBC

    #加密函数,如果text不足16位就用空格补足为16位,
    #如果大于16当时不是16的倍数,那就补足为16的倍数。
    def encrypt(self,text):
        cryptor = AES.new(self.key,self.mode,b'0000000000000000')   
        #这里密钥key 长度必须为16(AES-128),
        #24(AES-192),或者32 (AES-256)Bytes 长度
        #目前AES-128 足够目前使用
        length = 16
        count = len(text)
        if count < length:
            add = (length-count)
            text = text + ('\0' * add)
        elif count > length:
            add = (length-(count % length))
            text = text + ('\0' * add)
        self.ciphertext = cryptor.encrypt(text)
        #因为AES加密时候得到的字符串不一定是ascii字符集的,输出到终端或者保存时候可能存在问题
        #所以这里统一把加密后的字符串转化为16进制字符串
        return b2a_hex(self.ciphertext)

    #解密后,去掉补足的空格用strip() 去掉
    def decrypt(self,text):
        cryptor = AES.new(self.key,self.mode,b'0000000000000000')
        plain_text  = cryptor.decrypt(a2b_hex(text))
        return plain_text.rstrip('\0')

if __name__ == '__main__':
    pc = AESCrypto('123456789') #初始化密钥
    e = pc.encrypt('MhpPUwqNAsLehj1VRQmo8eLiQumNPAif7YZAuSW6')
    print "e=",e    
    d = pc.decrypt(e) #解密
    print "加密:",e
    print "解密:",d

这是一个用 Python 实现的AES加密解密方法,我现在需要使用Ruby来实现其中的解密方法,但是那个 b'0000000000000000'不知道是什么东西,写了一部分如下:

require 'openssl'
require 'base64'
class Test

    token_encry = "c8fd20f158163fcfe2b41ef546ec7b4af0caeb65fbfd1128090335f6640effa819aae009a036acf020162613f08fcb01"    
    decipher = OpenSSL::Cipher.new("AES-256-CBC")
    decipher.decrypt
    decipher.key = "123456789"

    decipher.padding = 0
    re = [token_encry].pack('H*')
    puts "re====#{re}"
    result = decipher.update([token_encry].pack('H*')) << decipher.final          
    puts result
    return result
end

查了很多资料,也找不到怎么能得出一样的结论。?_?

你要找的那个东西是 IV,前两天刚回答了一个类似问题。 加上 decipher.iv = '0000000000000000' 就行

aes 加密算法有"CBC", "ECB","CFB","OFB",加密不一定非得用到 iv,比如 ECB 算法就不用 iv 参数。 推荐个 gem https://github.com/Gurpartap/aescrypt。 解密的时候要与加密用的算法模式相同,之前写的一个例子http://www.cnblogs.com/wangyuyu/p/4950397.html

你给的 key 似乎短了点,最好写满 16 位

我觉得是编码出了问题,因为关于 AES 的所有能配的都配了,key 我没有写真实的,实际用的 key 长度是没问题的。 python 那个解密只调用 cryptor.decrypt(a2b_hex(text)),这个方法先把十六进制的 text 转化成了二进制,然后解码。 这个方法和 ruby 用的 [token_encry].pack('H*') 得到的二进制码一样,但是解出的码不一样,ruby 解出了乱码

class AES256
  class << self
    def encrypt(data)
      cipher = OpenSSL::Cipher::AES.new(256, :CBC)
      cipher.encrypt
      cipher.key = ENV['AES256_KEY']
      cipher.iv  = ENV['AES256_IV']
      cipher.update(data) << cipher.final
    end

    def decrypt(data)
      cipher = OpenSSL::Cipher::AES.new(256, :CBC)
      cipher.decrypt
      cipher.key = ENV['AES256_KEY']
      cipher.iv  = ENV['AES256_IV']
      cipher.update(data) << cipher.final
    end
  end
end
2.2.3 :001 > AES256.encrypt('tumayun').unpack('H*').first
 => "c199ee70fe440c24409945bc57c3ec86"
2.2.3 :002 > AES256.decrypt(['c199ee70fe440c24409945bc57c3ec86'].pack('H*'))
 => "tumayun"
2.2.3 :003 >

写过一些,参加:qy_wechat

@tumayun 我也用了这个方法,但是跟 python 加密的结果不一样,那个 update 方法能详细讲讲码? ^^^

嗯,解决啦,用了一楼的方法,借鉴了三楼和六楼的代码。😄大家给力👍🏼👍🏼👏🏻

上面的加密方法有个 bug,如果明文的最后一位是 '\0' 的话,,解密之后的结果会不等于明文。 一般来说,除非是要兼容已有的实现,使用广泛使用的库(比如 rbnacl)是一个更好的选择。

require 'openssl'
class Test3

  def aes_encrypt(key, encrypted_string)
    aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
    aes.encrypt
    aes.key = key
    aes.iv = '0000000000000000'
    aes.padding =0 


    length = 16
    count = encrypted_string.length
    if count < length
        add = (length-count)
        encrypted_string = encrypted_string + ("\0" * add)
    else if count > length
        add = (length-(count % length))
        encrypted_string = encrypted_string + ("\0" * add)
         end
    end
    puts "encrypted_string=#{encrypted_string}" 
    txt = aes.update(encrypted_string)+aes.final
    puts "txt=:#{txt}"
    txt.unpack('H*')[0]
  end


  def aes_dicrypt(key, dicrypted_string)
    aes = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
    aes.decrypt
    aes.key = key
    aes.iv = '0000000000000000'
    aes.padding = 0
    aes.update([dicrypted_string].pack('H*')) << aes.final
  end

  test = Test3.new
  key = "双方的秘钥"
  sec = test.aes_encrypt(key,'1111111111111111')
  puts sec

  txt = test.aes_dicrypt(key, sec)
  puts txt

end

huacnlee [该话题已被删除] 提及了此话题。 11月25日 10:09

上述所有的回复都太肤浅,没有一个人解释了这种问题的本质,都是皮毛

需要 登录 后方可回复, 如果你还没有账号请 注册新账号