Encrypt File from browser AES-GCM

huangapple go评论62阅读模式
英文:

Encrypt File from browser AES-GCM

问题

我使用AES GCM加密和解密文件时遇到了问题,我使用以下代码进行加密/解密:

我尝试了许多库,但它们没有解决我的问题。

var FileSaver = require("file-saver");

export function formatBytes(bytes) {
  // ...
}

export const encryptFile = async (key, iv, file) => {
  // ...
};

// ...

文件可以加密/解密,但它们可以使用任何密码解密,即使与加密时使用的密码不匹配。我在这里漏掉了什么?

英文:

I have a problem with encrypting and decrypting files with AES GCM, I encrypt/decrypt my files with this code:

I tried many some libraries but they didnt solve my problem.

var FileSaver = require("file-saver");

export function formatBytes(bytes) {
  var marker = 1024; // Change to 1000 if required
  var decimal = 3; // Change as required
  var kiloBytes = marker; // One Kilobyte is 1024 bytes
  var megaBytes = marker * marker; // One MB is 1024 KB
  var gigaBytes = marker * marker * marker; // One GB is 1024 MB

  // return bytes if less than a KB
  if (bytes < kiloBytes) return bytes + " Bytes";
  // return KB if less than a MB
  else if (bytes < megaBytes)
    return (bytes / kiloBytes).toFixed(decimal) + " KB";
  // return MB if less than a GB
  else if (bytes < gigaBytes)
    return (bytes / megaBytes).toFixed(decimal) + " MB";
  // return GB if less than a TB
  else return (bytes / gigaBytes).toFixed(decimal) + " GB";
}

export const encryptFile = async (key, iv, file) => {
  return await window.crypto.subtle.encrypt(
    {
      name: "AES-GCM",
      iv: iv
    },
    key,
    file
  );
};

/*
  Get some key material to use as input to the deriveKey method.
  The key material is a password supplied by the user.
  */
export const getKeyMaterial = async (password) => {
  let enc = new TextEncoder();
  return window.crypto.subtle.importKey(
    "raw",
    enc.encode(password),
    { name: "PBKDF2" },
    false,
    ["deriveBits", "deriveKey"]
  );
};

/*
Given some key material and some random salt
derive an AES-GCM key using PBKDF2.
*/
export const getKey = async (keyMaterial, salt) => {
  return window.crypto.subtle.deriveKey(
    {
      name: "PBKDF2",
      salt: salt,
      iterations: 100000,
      hash: "SHA-256"
    },
    keyMaterial,
    { name: "AES-GCM", length: 256 },
    true,
    ["encrypt", "decrypt"]
  );
};

// get the iv which is similar the salt value used for encryption
export const getiv = () => {
  return window.crypto.getRandomValues(new Uint8Array(12));
};

// load the file in the memory
export const getFile = async (inputFile) => {
  return await inputFile.arrayBuffer();
};

export const decryptFile = (iv, key, cipherText) => {
  return window.crypto.subtle.decrypt(
    {
      name: "AES-GCM",
      iv: iv
    },
    key,
    cipherText
  );
};

export const getDigest = (uid) => {
  let enc = new TextEncoder();

  return crypto.subtle.digest("SHA-256", enc.encode(uid));
};

export const startEncryption = async (file, password) => {
  console.log(file, password);
  let digest = getDigest(password);
  let rawFile = getFile(file);
  let keyMaterial = getKeyMaterial();
  Promise.all([digest, rawFile, keyMaterial]).then((values) => {
    console.log(values);
    let salt = new Uint8Array(
      "12345678".match(/[\da-f]{2}/gi).map(function (h) {
        return parseInt(h, 16);
      })
    );

    let iv = new Uint8Array(
      "4142434445464748494a4b4c4d4e4f50"
        .match(/[\da-f]{2}/gi)
        .map(function (h) {
          return parseInt(h, 16);
        })
    );
    // generate a crypto key
    getKey(values[2], salt).then((resp) => {
      console.log(resp);
      encryptFile(resp, iv, values[1]).then((cipherText) => {
        let fileBlob = new Blob([cipherText], { type: file.type });
        FileSaver.saveAs(fileBlob, file.name);
      });
    });
  });
};

export const startDecryption = (cipherText, password) => {
  let keyMaterial = getKeyMaterial();
  let digest = getDigest(password);
  let rawFile = getFile(cipherText);
  Promise.all([digest, rawFile, keyMaterial]).then((values) => {
    let salt = new Uint8Array(
      "12345678".match(/[\da-f]{2}/gi).map(function (h) {
        return parseInt(h, 16);
      })
    );

    let iv = new Uint8Array(
      "4142434445464748494a4b4c4d4e4f50"
        .match(/[\da-f]{2}/gi)
        .map(function (h) {
          return parseInt(h, 16);
        })
    );

    // generate a crypto key
    getKey(values[2], salt).then((resp) => {
      decryptFile(iv, resp, values[1]).then((file) => {
        let fileBlob = new Blob(, { type: file.type });
        FileSaver.saveAs(fileBlob, file.name);
      });
    });
  });
};

Files can be encrypt/decrypted but they can be decrypted with any password even if it doesnt match the password it encrypted with.
What am i missing here?

答案1

得分: 2

你调用了getKeyMaterial(),但没有提供密码,因此它始终是未定义的。
尝试使用getKeyMaterial(password);

英文:

you call getKeyMaterial() without the password, so its always undefined.
try getKeyMaterial(password);

huangapple
  • 本文由 发表于 2023年2月16日 02:15:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75463909.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定