如何在发布以表达路由后保存到磁盘之前对上传的文件进行加密,然后安全地将其读回?

问题描述 投票:0回答:1

如问题所述。我现在有一个过程,用户可以在其中“发布”并将文件上传到我的快速Web服务器,然后将其保存到磁盘上。我的问题是,任何能够访问服务器的人都可以使用该文件并查看其内容。我可以在Express Post处理程序中以任何方式加密/保护文件,以便尽管server.js文件可以打开文件并安全地对其进行“解密”,但用户无法读取/访问保存到磁盘上的内容。执行返回给用户的处理?最好的方法是什么?

node.js express security encryption
1个回答
0
投票

您可以使用multer程序包和内置的加密模块上传文件并对其进行加密,然后再存储到磁盘。然后可以将它们解密并通过get路由读取。

文件将以_encrypted.ext的名称保存到./uploads。

可以通过对/ file /:fileName的GET请求检索上载的文件。

我正在使用AES-256-CBC加密文件,但是您可以选择所需的任何算法。显然,您必须更改密钥和/或iv长度。

例如:

const express = require("express");
const port = 8080;
const app = express();
const bodyParser = require("body-parser");
const multer = require("multer");
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const stream = require("stream");

const CryptoAlgorithm = "aes-256-cbc";

// Obviously keys should not be kept in code, these should be populated with environmental variables or key store
const secret = {
    iv: Buffer.from('efb2da92cff888c9c295dc4ee682789c', 'hex'),
    key: Buffer.from('6245cb9b8dab1c1630bb3283063f963574d612ca6ec60bc8a5d1e07ddd3f7c53', 'hex')
}

app.use(express.static("./public"));
app.use(bodyParser.json());

const storage = multer.memoryStorage()
const upload = multer({ storage });

function encrypt(algorithm, buffer, key, iv) {
    const cipher = crypto.createCipheriv(algorithm, key, iv);
    const encrypted = Buffer.concat([cipher.update(buffer),cipher.final()]);
    return encrypted;
};

function decrypt(algorithm, buffer, key, iv) {
    const decipher = crypto.createDecipheriv(algorithm, key, iv);
    const decrypted = Buffer.concat([decipher.update(buffer), decipher.final()]);
    return decrypted;
}

function saveEncryptedFile(buffer, filePath, key, iv) {
    const encrypted = encrypt(CryptoAlgorithm, buffer, key, iv);
    if (!fs.existsSync(path.dirname(filePath))) {
        fs.mkdirSync(path.dirname(filePath))
    }
    filePath = path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath)) + "_encrypted" + path.extname(filePath));
    fs.writeFileSync(filePath, encrypted);
}

function getEncryptedFile(filePath, key, iv) {
    filePath = path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath)) + "_encrypted" + path.extname(filePath));
    const encrypted = fs.readFileSync(filePath);
    const buffer = decrypt(CryptoAlgorithm, encrypted, key, iv);
    return buffer;
}

app.post("/upload", upload.single("file"),  (req, res, next) => {
    console.log("file upload: ", req.file.originalname);
    saveEncryptedFile(req.file.buffer, path.join("/uploads", req.file.originalname), secret.key, secret.iv);
    // Should set a location header here...
    res.status(201).json( { status: "ok" });
});

app.get("/file/:fileName", (req, res, next) => {
    console.log("Getting file:", req.params.fileName);
    const buffer = getEncryptedFile(path.join("/uploads", req.params.fileName), secret.key, secret.iv);
    const readStream = new stream.PassThrough();
    readStream.end(buffer);
    res.writeHead(200, {
        "Content-disposition": "attachment; filename=" + req.params.fileName,
        "Content-Type": "application/octet-stream",
        "Content-Length": buffer.length
    });
    res.end(buffer);
});

app.listen(port);
console.log(`Serving at http://localhost:${port}`);
© www.soinside.com 2019 - 2024. All rights reserved.