使用python3和node js进行加密和解密

问题描述

我正在尝试创建一种多平台的加密-解密机制,到目前为止,我已经能够使用python进行加密并使用C进行解密,反之亦然,现在我正在尝试使用python脚本和一个节点来进行相同的操作js脚本。我能够在节点js中加密字符串并在python中解密,但是使用Python的加密消息在Node中解密却没有发生 这是python代码:

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto import Random
from base64 import b64decode
from base64 import b64encode
import json
import random

#iv= get_random_bytes(16)
key=b"aaaaaaaaaaaaaaaa"
iv= b"aaaaaaaaaaaaaaaa"
value = "Hello World"
strValue= str.encode(value)
data =strValue

#Encryption
data = b64encode(data)
pad =data + b"\0" * (AES.block_size - len(data) % AES.block_size)
cipher = AES.new(key,AES.MODE_CBC,iv)
ciphertext= cipher.encrypt(pad)
print (type(ciphertext))

print(b64encode(ciphertext).decode("utf-8"))

# Decryption
cipher = AES.new(key,iv)
data = cipher.decrypt(ciphertext)
print(b64decode(data))

这是Nodejs代码:

const crypto = require('crypto'); 

var iv = Buffer.from('aaaaaaaaaaaaaaaa')
var key =  Buffer.from('aaaaaaaaaaaaaaaa')
var cipher = crypto.createCipheriv('aes-128-cbc',key,iv);

let enc= cipher.update( "Hello World");
console.log(typeof (enc))
enc += cipher.final('base64');

console.log("enc is :",enc)



var decipher = crypto.createDecipheriv('aes-128-cbc',iv);
let decrypted = decipher.update(enc,'base64');
decrypted += decipher.final('utf8'); 
console.log("plain text is :",decrypted)

我从中取出了节点部分: AES - Encryption with Crypto (node-js) / decryption with Pycrypto (python) 我收到错误消息:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt 任何帮助将不胜感激,谢谢! 如果有更好的Node js实现方法,请告诉我们。

解决方法

在Python代码中,明文在加密之前是经过Base64编码的,而在NodeJS代码中则不是。此外,Python代码使用自定义的零填充,NodeJS代码使用默认的PKCS7填充。

要使NodeJS代码提供与Python代码相同的密文,必须在加密之前对明文进行Base64编码。此外,必须禁用默认的PKCS7填充,并且必须应用Python代码的“零填充”变体。由于PyCryptodome不支持零填充,因此需要自定义实现。

可能的NodeJS实现可能是:

const crypto = require('crypto') 
const buffertrim = require('buffertrim') 

function toB64padded(plaintext,blocksize){
    var bufPlaintext = Buffer.from(plaintext,'utf8')
    var bufPlaintextB64 = Buffer.from(bufPlaintext.toString('base64'),'utf8')      // Base64 encoding
    var bufPadding = Buffer.alloc(blocksize - bufPlaintextB64.length % blocksize)
    return Buffer.concat([bufPlaintextB64,bufPadding])                             // Zero padding
}

var iv = Buffer.from('aaaaaaaaaaaaaaaa')                                            // Static IV only for testing purposes
var key =  Buffer.from('aaaaaaaaaaaaaaaa')

// Encryption
var plaintext = "The quick brown fox jumps over the lazy dog"
var bufPlaintextB64padded = toB64padded(plaintext,16)                              // Base64 encoding and Zero padding
var cipher = crypto.createCipheriv('aes-128-cbc',key,iv)
cipher.setAutoPadding(false)                                                        // Disable PKCS7 padding

var ciphertextB64 = cipher.update(bufPlaintextB64padded,'','base64')              // Encryption,Base64 encoding of ciphertext 
ciphertextB64 += cipher.final('base64')
console.log("ciphertext is:",ciphertextB64)  

// Decryption
var decipher = crypto.createDecipheriv('aes-128-cbc',iv)
decipher.setAutoPadding(false)                                                      // Disable PKCS7 (un-) padding

var bufPlaintextB64padded = Buffer.concat([                                         // Base64 decoding of ciphertext,decryption
    decipher.update(ciphertextB64,'base64'),decipher.final()
]);                                                                                 
var bufPlaintextB64 = buffertrim.trimEnd(bufPlaintextB64padded)                     // Unpadding (unreliable)
var bufPlaintext = Buffer.from(bufPlaintextB64.toString('utf8'),'base64')          // Base64 decoding
console.log("plaintext is:",bufPlaintext.toString('utf8'))

作为示例,纯文本快速的棕狐跳过懒狗已使用上面的Python代码和NodeJS代码进行了加密。两种代码都使用发布的密钥和IV产生相同的密文,即:

IETFUbiTGsKFZWLgjjP5RrKPX+GeVon1Kuy38bPdKXwqUJWUGWMJ9MOL9gEAsF+1U/N0Juwzu24Dju4UMwdZaA== 

这意味着可以使用一种代码进行加密,而使用另一种代码进行解密。


请注意,在加密之前,无需对Base64编码明文 。同样,零填充是一种不可靠填充,最好用PKCS7填充代替。 PyCryptodome通过Crypto.Util.Padding模块支持PKCS7填充,因此填充不需要自定义实现。并且如上所述,NodeJS的加密模块默认使用PKCS7填充。

出于安全原因,每次加密都必须使用 random IV。 IV(不是秘密的)通常与密文连接在一起。在Python代码中,实现了IV的随机生成(但已注释掉,可能出于测试目的)。但是,缺少串联部分。为了与Python代码兼容,在NodeJS代码中都省略了这两个代码。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...