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
正常工作,或者成功地从回显消息中删除额外的填充。
任何帮助将不胜感激。谢谢。
puts
和 gets
对字符串起作用,而密文是二进制的。因此,如果您只希望在 gets
期间收到一个字符串然后是换行符,您 运行 就会遇到问题(特别是如果您还尝试解密最后的换行符,这可能是导致错误的原因)。
相反,您可以首先 base 64 encode 密文 和 IV(分别)。然后 gets.chomp
、解码和 然后 解密消息。
如果你只是 chomp
换行符,那么你的加密/解密也可能有效......直到你不小心在二进制密文中间引入了换行符。
所以永远不要忘记,尽管密文这个名字实际上并不是文本(对于现代密码),它是一个随机的二进制字节串。
使用 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
正常工作,或者成功地从回显消息中删除额外的填充。
任何帮助将不胜感激。谢谢。
puts
和 gets
对字符串起作用,而密文是二进制的。因此,如果您只希望在 gets
期间收到一个字符串然后是换行符,您 运行 就会遇到问题(特别是如果您还尝试解密最后的换行符,这可能是导致错误的原因)。
相反,您可以首先 base 64 encode 密文 和 IV(分别)。然后 gets.chomp
、解码和 然后 解密消息。
如果你只是 chomp
换行符,那么你的加密/解密也可能有效......直到你不小心在二进制密文中间引入了换行符。
所以永远不要忘记,尽管密文这个名字实际上并不是文本(对于现代密码),它是一个随机的二进制字节串。