OpenSSL encryption error AES-256-CBC, Ruby "wrong end block length"

Using Ruby 1.8.6.

I am writing a basic server that echo the encrypted version sends a message from the client to inquire about the symmetric encryption implementation in Ruby. The program is designed to accept a socket connection, exchange a secret key, then encrypt the data it receives before sending it back to the client program. The client then decrypts the message using the shared secret, showing the echo'd message.

The problem I am facing is a return message that throws "wrong final block length (OpenSSL :: CipherError)". After looking at the issue, deleting decrypted << chiper.final

allows my client program to decrypt the message, but adds extra characters or bank spaces at the end. I know this is because the keyword final

removes the extra padding to allow 16-bit encryption / decryption of the CBC mode block, but I can't figure out how to get the job done correctly.

Here's a simplified server code (I know it's not secure, it isn't, this is just a tutorial application)

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

      

And my client ...

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

      

The client takes the information from the keyboard and sends it to the server before waiting for an encrypted message in response. As said, I can't think of waiting for it to decrypted << cipher.final

work correctly or successfully removing the extra addition from the echo'd message.

Any help would be greatly appreciated. Thank you.

+3


source to share


1 answer


puts

and gets

work with strings, and the ciphertext is binary. So you're in trouble if you're just expecting a string and then a newline in time gets

(especially if you try to decode the final newline as well, this is probably causing the error).

Instead, you could base 64 encode the ciphertext and IV (separately) first. Then gets.chomp

, decode and then decode the message.

If you're just a chomp

newline, then your encryption / decryption will probably work too ... as long as you don't accidentally enter a newline in the middle of the binary ciphertext.




So never forget that despite the name, the ciphertext is not actually text (for modern ciphers), it is a random binary string of bytes.

+3


source







All Articles