OpenSSL AES-256-CBC 加密错误,"wrong final block length" Ruby

OpenSSL AES-256-CBC Encryption Error, "wrong final block length" Ruby

使用 Ruby 1.8.6.

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

我 运行 遇到的问题是 return 消息导致 "wrong final block length (OpenSSL::CipherError)"。进一步检查问题,删除 decrypted << chiper.final 允许我的客户端程序解密消息,但在末尾添加额外的字符或银行空格。我知道这是因为 final 关键字删除了额外的填充以允许 CBC 模式的 16 位块 encryption/decryption,但我不知道如何正确地工作。

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

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

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

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

putsgets 对字符串起作用,而密文是二进制的。因此,如果您只希望在 gets 期间收到一个字符串然后是换行符,您 运行 就会遇到问题(特别是如果您还尝试解密最后的换行符,这可能是导致错误的原因)。

相反,您可以首先 base 64 encode 密文 IV(分别)。然后 gets.chomp、解码和 然后 解密消息。

如果你只是 chomp 换行符,那么你的加密/解密也可能有效......直到你不小心在二进制密文中间引入了换行符。


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