Encrypt File from browser AES-GCM

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

Encrypt File from browser AES-GCM

问题

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

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

  1. var FileSaver = require("file-saver");
  2. export function formatBytes(bytes) {
  3. // ...
  4. }
  5. export const encryptFile = async (key, iv, file) => {
  6. // ...
  7. };
  8. // ...

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

英文:

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.

  1. var FileSaver = require("file-saver");
  2. export function formatBytes(bytes) {
  3. var marker = 1024; // Change to 1000 if required
  4. var decimal = 3; // Change as required
  5. var kiloBytes = marker; // One Kilobyte is 1024 bytes
  6. var megaBytes = marker * marker; // One MB is 1024 KB
  7. var gigaBytes = marker * marker * marker; // One GB is 1024 MB
  8. // return bytes if less than a KB
  9. if (bytes < kiloBytes) return bytes + " Bytes";
  10. // return KB if less than a MB
  11. else if (bytes < megaBytes)
  12. return (bytes / kiloBytes).toFixed(decimal) + " KB";
  13. // return MB if less than a GB
  14. else if (bytes < gigaBytes)
  15. return (bytes / megaBytes).toFixed(decimal) + " MB";
  16. // return GB if less than a TB
  17. else return (bytes / gigaBytes).toFixed(decimal) + " GB";
  18. }
  19. export const encryptFile = async (key, iv, file) => {
  20. return await window.crypto.subtle.encrypt(
  21. {
  22. name: "AES-GCM",
  23. iv: iv
  24. },
  25. key,
  26. file
  27. );
  28. };
  29. /*
  30. Get some key material to use as input to the deriveKey method.
  31. The key material is a password supplied by the user.
  32. */
  33. export const getKeyMaterial = async (password) => {
  34. let enc = new TextEncoder();
  35. return window.crypto.subtle.importKey(
  36. "raw",
  37. enc.encode(password),
  38. { name: "PBKDF2" },
  39. false,
  40. ["deriveBits", "deriveKey"]
  41. );
  42. };
  43. /*
  44. Given some key material and some random salt
  45. derive an AES-GCM key using PBKDF2.
  46. */
  47. export const getKey = async (keyMaterial, salt) => {
  48. return window.crypto.subtle.deriveKey(
  49. {
  50. name: "PBKDF2",
  51. salt: salt,
  52. iterations: 100000,
  53. hash: "SHA-256"
  54. },
  55. keyMaterial,
  56. { name: "AES-GCM", length: 256 },
  57. true,
  58. ["encrypt", "decrypt"]
  59. );
  60. };
  61. // get the iv which is similar the salt value used for encryption
  62. export const getiv = () => {
  63. return window.crypto.getRandomValues(new Uint8Array(12));
  64. };
  65. // load the file in the memory
  66. export const getFile = async (inputFile) => {
  67. return await inputFile.arrayBuffer();
  68. };
  69. export const decryptFile = (iv, key, cipherText) => {
  70. return window.crypto.subtle.decrypt(
  71. {
  72. name: "AES-GCM",
  73. iv: iv
  74. },
  75. key,
  76. cipherText
  77. );
  78. };
  79. export const getDigest = (uid) => {
  80. let enc = new TextEncoder();
  81. return crypto.subtle.digest("SHA-256", enc.encode(uid));
  82. };
  83. export const startEncryption = async (file, password) => {
  84. console.log(file, password);
  85. let digest = getDigest(password);
  86. let rawFile = getFile(file);
  87. let keyMaterial = getKeyMaterial();
  88. Promise.all([digest, rawFile, keyMaterial]).then((values) => {
  89. console.log(values);
  90. let salt = new Uint8Array(
  91. "12345678".match(/[\da-f]{2}/gi).map(function (h) {
  92. return parseInt(h, 16);
  93. })
  94. );
  95. let iv = new Uint8Array(
  96. "4142434445464748494a4b4c4d4e4f50"
  97. .match(/[\da-f]{2}/gi)
  98. .map(function (h) {
  99. return parseInt(h, 16);
  100. })
  101. );
  102. // generate a crypto key
  103. getKey(values[2], salt).then((resp) => {
  104. console.log(resp);
  105. encryptFile(resp, iv, values[1]).then((cipherText) => {
  106. let fileBlob = new Blob([cipherText], { type: file.type });
  107. FileSaver.saveAs(fileBlob, file.name);
  108. });
  109. });
  110. });
  111. };
  112. export const startDecryption = (cipherText, password) => {
  113. let keyMaterial = getKeyMaterial();
  114. let digest = getDigest(password);
  115. let rawFile = getFile(cipherText);
  116. Promise.all([digest, rawFile, keyMaterial]).then((values) => {
  117. let salt = new Uint8Array(
  118. "12345678".match(/[\da-f]{2}/gi).map(function (h) {
  119. return parseInt(h, 16);
  120. })
  121. );
  122. let iv = new Uint8Array(
  123. "4142434445464748494a4b4c4d4e4f50"
  124. .match(/[\da-f]{2}/gi)
  125. .map(function (h) {
  126. return parseInt(h, 16);
  127. })
  128. );
  129. // generate a crypto key
  130. getKey(values[2], salt).then((resp) => {
  131. decryptFile(iv, resp, values[1]).then((file) => {
  132. let fileBlob = new Blob(, { type: file.type });
  133. FileSaver.saveAs(fileBlob, file.name);
  134. });
  135. });
  136. });
  137. };

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:

确定