将加密的消息从python客户端发送到Node.js服务器

时间:2018-09-28 04:48:49

标签: python node.js cryptography

我这里有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

如何使服务器正确解密客户端发送的邮件?需要您的专家指导。谢谢!

2 个答案:

答案 0 :(得分:2)

首先,您需要分解问题:消息发送和加密/解密应分别进行测试。

如果您使用createCiphercreateDecipher,则必须提供密码而不是密钥。密码已经过预处理以创建密钥,但是密钥显然不同于客户端密钥,在尝试解密时会给您带来垃圾。您需要使用createCipherivcreateDecipheriv来使用密钥。但是,我上次检查时,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");

希望以上示例可以帮助其他面临相同问题的人。