【问题标题】:How to encrypt an uploaded file before saving to disk after posting to express route, then read it back securely?如何在发布到快速路线后在保存到磁盘之前加密上传的文件,然后安全地读取它?
【发布时间】:2020-03-21 10:50:49
【问题描述】:

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

【问题讨论】:

  • 如果这能解决您的问题,请告诉我,medium.com/@brandonstilson/…
  • 您有密钥管理吗?或者您打算将加密密钥存储在哪里?如果你把它存储在服务器上,你又回到了第一格。

标签: node.js express security encryption


【解决方案1】:

您可以使用 multer 软件包和内置的加密模块来上传文件并在存储到磁盘之前对其进行加密。然后可以通过 get 路由对其进行解密和读回。

文件将保存到 ./uploads,名称为 [originalfile]_encrypted.[ext]。

可以通过对 /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 getEncryptedFilePath(filePath) {
    return path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath)) + "_encrypted" + path.extname(filePath))
}

function saveEncryptedFile(buffer, filePath, key, iv) {
    const encrypted = encrypt(CryptoAlgorithm, buffer, key, iv);

    filePath = getEncryptedFilePath(filePath);
    if (!fs.existsSync(path.dirname(filePath))) {
        fs.mkdirSync(path.dirname(filePath))
    }

    fs.writeFileSync(filePath, encrypted);
}

function getEncryptedFile(filePath, key, iv) {
    filePath = getEncryptedFilePath(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);
    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}`);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-13
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    • 2010-10-26
    • 2012-03-04
    • 1970-01-01
    相关资源
    最近更新 更多