OpenSSL AES-256-CBC加密错误,"错误的最终块长度"红宝石

时间:2015-07-27 16:33:07

标签: ruby encryption openssl cryptography padding

使用Ruby 1.8.6。

我正在编写一个基本服务器,它是一个加密版本,是客户端发送的消息,用于了解Ruby中对称加密的实现。该程序旨在接受套接字连接,共享它的密钥,然后加密它接收的数据,然后再将其发送回客户端程序。然后,客户端使用共享密钥解密消息,显示回声消息。

我遇到的问题是返回消息导致&#34;错误的最终块长度(OpenSSL :: CipherError)&#34;。进一步检查问题,删除decrypted << chiper.final允许我的客户端程序解密消息,但最后添加其他字符或库空间。我知道这是因为final关键字删除了额外的填充以允许16位块加密/解密CBC模式,但我无法弄清楚如何使工作正常。

这里有简化的服务器代码(我知道这不安全,不是重点,这只是一个学习应用程序)

require 'socket'
require 'thread'
require 'openssl'
require 'digest/sha1'

class Server 
@@static_id = 1
@connection_no 

@port
@server

@aes_cipher
@key

def initialize(p)
    #setting up server connections
    puts "Starting server"      
    @port = p
    puts "connections on port #{@port} will be accepted"
    @server = TCPServer.open(@port)

    #generate a secret key
    puts "creating secret key..."
    @aes_cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
    @aes_cipher.encrypt
    @key = @aes_cipher.random_key
    @aes_cipher.key = @key
    puts "key: #{@key}"

    #start server       
    start_server
end

def start_server    
    loop{
        Thread.new(@server.accept) do |client|

            #connection and request
            sock_domain, remote_port, remote_hostname, remote_ip = client.peeraddr
            client_ip = remote_ip.to_s  
            @@static_id += 1
            @connection_no = @@static_id                
            puts "\nConnection ##{@connection_no} client #{client_ip} accepted" 

            #send client secret key 
            client.puts @key                        

            #receive data from client
            data = client.gets
            puts "received: #{data}"

            # you will need to store these for later, in order to decrypt your data
            iv = @aes_cipher.random_iv  
            @aes_cipher.iv = iv
            puts "generated IV: #{iv}"
            encrypted = @aes_cipher.update(data)
            encrypted << @aes_cipher.final  
            puts "Encrypted Msg: #{encrypted}"              

            #send back IV and data
            client.puts encrypted
            client.puts iv              

            #close connections
            client.close        

        end
    }
end 
end

我的客户......

require 'socket'
require 'thread'
require 'openssl'
require 'digest/sha1'

class aes_client
@port
@hostname

def initialize(p)
    @hostname = 'localhost'
    @port = p
    connect
end

def connect
    #establis connections
    s = TCPSocket.new(@hostname, @port) 

    #get key on connection
    key = s.gets
    puts "Key to decrypt: #{key}"

    #send data  
    data = $stdin.gets.chomp
    s.puts data     

    #receive message and IV
    message = s.gets
    puts "Encrypted Message: #{message}"        
    iv = s.gets
    puts "IV to decypt: #{iv}"  

    # now we create a sipher for decrypting
    cipher = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
    cipher.decrypt
    cipher.key = key
    cipher.iv = iv

    # and decrypt it
    decrypted = cipher.update(message) 
    #decrypted << cipher.final

    puts "decrypted: #{decrypted}\n"

    s.close
end
end

客户端从键盘获取信息并将其发送到服务器,然后再等待加密消息。如前所述,我想不出等待decrypted << cipher.final正常工作,或者成功从echo消息中删除额外的填充。

任何帮助将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:3)

studentFirstputs处理字符串,而密文是二进制的。因此,如果您只是期望在gets期间使用字符串然后换行,则会遇到问题(特别是如果您尝试解密最终换行符,这可能是导致错误的原因)。

相反,您可以先base 64 encode密文 IV(单独)。然后gets,解码并然后解密消息。

如果您只是gets.chomp换行符,那么您的加密/解密可能也会起作用......直到您不小心在二进制密文的中间引入换行符。

所以永远不要忘记,尽管名称密文实际上不是文本(对于现代密码),但它是一个随机的二进制字节字符串。