我这里有2个程序。
客户端是一个python程序。它需要通过套接字将加密的消息发送到服务器。它使用pycryptodome软件包对消息进行加密。模式是DES。
from Crypto.Cipher import DES
from Crypto.Util import Padding
import socket
message=b"abc"
key = b"secret_k"
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host ='127.0.0.1'
port =8007
serversocket.connect((host,port))
#need to do the padding manually
des = DES.new(key, DES.MODE_ECB)
# ciphered = des.encrypt(message)
ciphered = des.encrypt(Padding.pad(message,8))
plain_msg_withpadding = des.decrypt(ciphered)
# plain_msg = Padding.unpad(plain_withpadding,8)
print ("Deciphered including padding: ", plain_withpadding)
# print ("Decipered without padding: ", plain_msg)
print('msg_to_send', ciphered)
serversocket.send(ciphered)
serversocket.close()
服务器端是一个nodejs程序。它需要解释收到的消息。它为nodejs使用加密包。模式也设置为DES
var net = require('net');
const crypto = require('crypto');
const decipher = crypto.createDecipher('DES-ECB','secret_k');
const local_decipher = crypto.createDecipher('DES-ECB','secret_k');
const cipher = crypto.createCipher('DES-ECB','secret_k')
function encrypt (buf){
let crypted = Buffer.concat([cipher.update(buf),cipher.final()]);
return crypted
}
local_message = 'abc'
local_cyphered = encrypt(Buffer.from(local_message));
console.log('cyphered in buffer', local_cyphered);
console.log('local_message decyphered: ',
local_decipher.update(local_cyphered)+local_decipher.final());
net.createServer(function(socket){
socket.on('data', function(data){
decipher.setAutoPadding(false);// have to disable auto padding, otherwise final() will raise and error.
var totalBuffer = Buffer.concat([decipher.update(data),decipher.final()]);
console.log('decrypted remote message: ',totalBuffer);
console.log('decrypted remote message in utf-8: ',totalBuffer.toString('utf-8'));
})
}).listen(8007);
console.log("server started at 8007 \n");
当我运行客户端程序时,它会打印结果:
Deciphered including padding: b'abc\x05\x05\x05\x05\x05'
msg_to_send b'\t\xc3JkP\xca\xd0\xf7'
但是在服务器端,结果如下:
cyphered in buffer <Buffer 4f c1 e4 2c fc dd eb 67>
local_message decyphered: abc
server started at 8007
decrypted remote message: <Buffer 74 d2 47 08 cd 45 bb 6a>
decrypted remote message in utf-8: t��E�j
如何使服务器正确解密客户端发送的邮件?需要您的专家指导。谢谢!
答案 0 :(得分:2)
首先,您需要分解问题:消息发送和加密/解密应分别进行测试。
如果您使用createCipher
和createDecipher
,则必须提供密码而不是密钥。密码已经过预处理以创建密钥,但是密钥显然不同于客户端密钥,在尝试解密时会给您带来垃圾。您需要使用createCipheriv
或createDecipheriv
来使用密钥。但是,我上次检查时,ECB不适用于这些方法。使用仍然需要IV的密码模式可能是一个好主意。诸如AES-GCM之类的身份验证模式将是最有益的。
不需要setAutoPadding(false)
调用。如果将其禁用,则可能是因为解密失败,然后解密结果就没有意义了。
请注意,在Node.js包中重用密码是危险的。您应该为每个要加密/解密的消息重新创建密文对象。
答案 1 :(得分:1)
谢谢Maarten,我已经根据您的提示重写了两个程序。现在他们可以进行我想要的通信了。我知道可能存在一些安全问题,但我稍后会对此进行改进
from Crypto.Cipher import DES
from Crypto.Util import Padding
import socket
host ='127.0.0.1'
port =8007
greeting=bytes("hello!",encoding="utf-8")
message=bytes("abc这个",encoding="utf-8")
key = b"secret_k"
def ba(byte_data):
return list(map(hex,bytearray(byte_data)))
def post_message(msg):
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.connect((host,port))
serversocket.send(msg)
serversocket.close()
#1 test normal connection server should print hello!
post_message(greeting)
print ('plain text', ba(greeting))
#2 test encrypt
padded_msg = Padding.pad(message,8) #need to do the padding manually
des = DES.new(key, DES.MODE_CBC) #using CBC instead of ECB
ciphered = des.encrypt(des.iv+padded_msg)
post_message(ciphered)
print("ciphered : ",ba(ciphered))
在服务器上
var net = require('net');
const crypto = require('crypto');
const key = 'secret_k';
//prepare the cipher with shared key 'secret_k'
const decipher = crypto.createDecipheriv('DES-CBC',key,'iv123456');
var notFirstMessage = false;//just a flag
net.createServer(function(socket){
socket.on('data', function(data){
if(notFirstMessage){
console.log("I will do decipher work\n");
console.log("encrypted data is: ", data);
//do the decipher here
var remote_message = Buffer.concat([decipher.update(data),decipher.final()]);
console.log("After decipher: ",remote_message.slice(8).toString());//remove the iv
}else {
//
console.log('connection is ok, I got data: ',data.toString());
notFirstMessage = true;
console.log("============[Plain Text Connection OK]==============\n")
}
});
}).listen(8007);
console.log("server started at 8007 \n");
希望以上示例可以帮助其他面临相同问题的人。