Я разработал веб-приложение с Express и React для проведения онлайн-экзаменов с использованием асимметричной c криптографии для обеспечения безопасности. он должен зашифровать объект вопроса, отправляемый клиентской стороне, а затем расшифровать его с помощью privateKey пользователя. ответы пользователя также должны быть зашифрованы, а затем отправлены на сервер. Я использовал модуль криптоузла на стороне клиента, и он работает только для симметрии c enc / de c, а не асимметрии c и говорит Unable to decrypt data
. Я нашел модуль npm для клиентской стороны, но он не работал, и те не могут расшифровать данные (privateDecrypt). Кроме того, я попытался использовать WebCryptoApi, но это заканчивается просто ошибка DOMException.
, если вы можете, пожалуйста, помогите мне найти способ сделать это.
ОБНОВЛЕНИЕ (КОД)
examController. js
static examStarted(req, res) {
let userInfo = this._userToken(req, res);
console.log(userInfo);
let examID = 1;
exam
.findAll({
attributes: ["id", "idCourse", "totalQuestion"],
where: {
id: examID,
},
include: [
{
model: userRegisterToExam,
attributes: ["id"],
required: true,
where: {
idUser: userInfo.id,
},
},
{
model: course,
attributes: ["id"],
required: true,
include: [
{
model: question,
required: true,
},
],
},
],
})
.then((responses) => {
const array = [];
const MyQuestion = [];
const questionInfo = [];
const lenghtofQuestion = Object.keys(responses[0].course.questions)
.length;
console.log(lenghtofQuestion);
const info = responses[0].course.questions;
//this.generateQuestion(req, res, queryResult1[0].idCourse)
for (let total = 0; total <= responses[0].totalQuestion - 1; total++) {
const count = this.RandomInt(lenghtofQuestion, array);
console.log(count);
MyQuestion[total] = info[count];
questionInfo.push({
idExamStart: 0,
idQuestion: info[count].id,
response: 5,
status: 0,
});
array.push(count);
}
//console.log(responses[0].userRegisterToExam)
this.startTest(
req,
res,
MyQuestion,
questionInfo,
examID,
responses[0].userRegisterToExams[0].id
);
})
.catch((error) => this.SetErrorInfo(req, res, error));
}
static startTest(
req,
res,
MyQuestion,
questionInfo,
examID,
idUserRegisterToExam
) {
let userInfo = this._userToken(req, res);
let password = "milad"; //userInfo.id + "-" + this.generateRandomString();
console.log("pass1", password);
let key = this.generateKeys(password);
let publicKey = key.publicKey;
let privateKey = key.privateKey;
let data = {
idUser: userInfo.id,
idExam: examID,
idUserRegisterToExam,
dateStart: this.getDate("jYYYY/jMM/jDD h:m:s"),
dateUpload: "",
teacherConfirmation: "0",
supervisorConfirmation: "0",
score: "0",
document: "0",
status: "0",
public: publicKey,
private: privateKey,
password,
};
examStart
.create(data)
.then((responses) => {
let tokenString = {
userID: userInfo.id,
start: responses.id,
password,
privateKey,
};
let d = this.encryption(
JSON.stringify(MyQuestion),
publicKey,
privateKey,
password
);
let data = {
token: this.encrypt(JSON.stringify(tokenString)),
data: d.data,
k: d.key,
};
res.send(data);
})
.catch((error) => this.SetErrorInfo(req, res, error));
}
static encryption(toEncrypt, publicKey, privateKey, password) {
var mykey = crypto.createCipher("aes-128-cbc", password);
var mystr = mykey.update(toEncrypt, "utf8", "base64");
mystr += mykey.final("base64");
// key encryption (asymmetric)
var buffer = new Buffer(password);
var encrypted = crypto.publicEncrypt(publicKey, buffer);
var enc = encrypted.toString("base64");
return { key: encrypted.toString("base64"), data: mystr };
}
static decryption(req, res) {
// decryption
// key decryption (asymmetric)
let dec = this.decrypt(req, res, req.body.token);
console.log("dec", dec);
let tokenObject = JSON.parse(dec);
let privateKey = tokenObject.privateKey;
let password = tokenObject.password; //this.decrypt(req, res, tokenObject.password);
let pass = password.toString("utf8");
let buffer = new Buffer(req.body.key, "base64");
const decryptedKey = crypto.privateDecrypt(
{
key: privateKey.toString(),
passphrase: pass,
},
buffer
);
var symmetricKey = decryptedKey.toString("utf8");
// symmetric decryption
var mykey = crypto.createDecipher("aes-128-cbc", symmetricKey);
var mystr = mykey.update(req.body.data, "base64", "utf8");
mystr += mykey.final("utf8");
res.send({ requests: req.body, result: mystr });
}
static generateKeys(myPassword) {
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
modulusLength: 4096,
namedCurve: "secp256k1",
publicKeyEncoding: {
type: "spki",
format: "pem",
},
privateKeyEncoding: {
type: "pkcs8",
format: "pem",
cipher: "aes-256-cbc",
passphrase: myPassword,
},
});
return {
privateKey,
publicKey,
};
}
React Component (получение зашифрованных вопросов с сервера)
_getData() {
const data = {
exam: this.state.id,
idCourse: this.state.idCourse,
factor: this.state.idFactor,
};
axios
.post(`${this._ServerUrl()}examStarted`, data, {
headers: this._Header(),
})
.then((response) => {
let a = this.decrypt(response.data.token); // it's for symmetric decryption and works good.
console.log(a);
this.setState({
privateKey: a.privateKey,
password: a.password,
getDateStatus: true,
});
try {
let data = this.decryption(
a.password,
a.privateKey,
response.data.data,
response.data.k
);
console.log(data);
} catch (error) {
console.log(error);
}
})
.catch((error) => {
this.errorLog(error);
});
}
decryption(password, privateKey, text, key) {
let buffer = new Buffer(key, "base64");
const decryptedKey = cryptoBrowserify.privateDecrypt(
{
key: privateKey.toString(),
passphrase: password.toString(),
},
buffer
);
var symmetricKey = decryptedKey.toString("utf8");
// symmetric decryption
var mykey = crypto.createDecipher("aes-128-cbc", symmetricKey);
var mystr = mykey.update(text, "base64", "utf8");
mystr += mykey.final("utf8");
return mystr;
}