Jay*_*Jay 4 ruby encryption openssl cryptography padding
使用 Ruby 1.8.6。
我正在编写一个基本服务器,该服务器回显从客户端发送的消息的加密版本,以了解 Ruby 中对称加密的实现。该程序旨在接受套接字连接,共享其密钥,然后对其接收的数据进行加密,然后将其发送回客户端程序。然后,客户端使用共享密钥解密该消息,从而显示回显的消息。
我遇到的问题是返回消息导致“错误的最终块长度(OpenSSL::CipherError)”。进一步检查问题,删除decrypted << chiper.final
允许我的客户端程序解密消息,但在末尾添加额外的字符或银行空格。我知道这是因为final
关键字删除了额外的填充以允许 CBC 模式的 16 位块加密/解密,但我不知道如何正确工作。
这是简化的服务器代码(我知道这不安全,那不是重点,这只是一个学习应用程序)
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
Run Code Online (Sandbox Code Playgroud)
还有我的客户...
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
Run Code Online (Sandbox Code Playgroud)
客户端从键盘获取信息并将其发送到服务器,然后等待加密消息返回。如前所述,我无法想象要等待才能decrypted << cipher.final
正常工作,或者成功地从回显消息中删除额外的填充。
任何帮助将不胜感激。谢谢。
puts
并gets
处理字符串,而密文是二进制的。因此,如果您只期望一个字符串,然后是一个换行符gets
(特别是如果您也尝试解密最终的换行符,这可能是导致错误的原因),那么您会遇到问题。
相反,您可以首先对密文和IV(分别)进行 Base 64 编码。然后,解码并解密该消息。gets.chomp
如果您只是chomp
换行符,那么您的加密/解密也可能会起作用......直到您不小心在二进制密文中间引入了换行符。
所以永远不要忘记,尽管名称密文实际上不是文本(对于现代密码),它是一个随机的二进制字节字符串。