Javascript CryptoJS-解密加密文件
我正在尝试编写一个应用程序,在浏览器中使用JS对文件进行端到端加密。但是,我似乎无法正确解密所有文件 TL;DR由于加密整个大于1MB的文件是不切实际的,所以我尝试逐块加密它们。这样做之后,我尝试将加密字(由Javascript CryptoJS-解密加密文件,javascript,file,encryption,cryptojs,Javascript,File,Encryption,Cryptojs,我正在尝试编写一个应用程序,在浏览器中使用JS对文件进行端到端加密。但是,我似乎无法正确解密所有文件 TL;DR由于加密整个大于1MB的文件是不切实际的,所以我尝试逐块加密它们。这样做之后,我尝试将加密字(由CryptoJS的字数组生成)写入一个blob。至于解密,我读取文件并根据加密区块时生成的映射将其拆分为区块,然后尝试解密。问题是解密结果是0位 我猜我没有在正确解密时读取块。请查看下面关于函数getBlob(将数据写入blob)的代码,以及用于读取块的decryptFile的最后一部分 更
CryptoJS
的字数组生成)写入一个blob。至于解密,我读取文件并根据加密区块时生成的映射将其拆分为区块,然后尝试解密。问题是解密结果是0位
我猜我没有在正确解密时读取块。请查看下面关于函数getBlob
(将数据写入blob)的代码,以及用于读取块的decryptFile
的最后一部分
更多解释
我正在使用默认设置的CryptoJS AES
现在,我的代码如下所示:
function encryptFile (file, options, resolve, reject) {
if (!options.encrypt) {
return resolve(file)
}
if (!options.processor || !options.context) {
return reject('No encryption method.')
}
function encryptBlob (file, optStart, optEnd) {
const start = optStart || 0
let stop = optEnd || CHUNK_SIZE
if (stop > file.size - 1) {
stop = file.size
}
const blob = file.slice(start, stop)
const fileReader = new FileReader()
fileReader.onloadend = function () {
if (this.readyState !== FileReader.DONE) return
const index = Math.ceil(optStart / CHUNK_SIZE)
const result = CryptoJS.lib.WordArray.create(this.result)
encryptedFile[index] = encrypt(result)
chunksResolved++
if (chunksResolved === count) {
const {sigBytes, sigBytesMap, words} = getCipherInfo(encryptedFile)
const blob = getBlob(sigBytes, words)
resolve(blob, Object.keys(sigBytesMap))
}
}
fileReader.readAsArrayBuffer(blob)
}
let chunksResolved = 0
const encryptedFile = []
const CHUNK_SIZE = 1024*1024
const count = Math.ceil(file.size / CHUNK_SIZE)
const encrypt = value => options.processor.call(
options.context, value, 'file',
(v, k) => CryptoJS.AES.encrypt(v, k))
for (let start = 0; (start + CHUNK_SIZE) / CHUNK_SIZE <= count; start+= CHUNK_SIZE) {
encryptBlob(file, start, start + CHUNK_SIZE - 1)
}
}
解密与加密完全相同,但不起作用。虽然块不再是1MB,但它们仅限于图中提到的sigBytes。解密没有结果<代码>字节:0
以下是生成blob和获取sigbytesMap的代码:
function getCipherInfo (ciphers) {
const sigBytesMap = []
const sigBytes = ciphers.reduce((tmp, cipher) => {
tmp += cipher.sigBytes || cipher.ciphertext.sigBytes
sigBytesMap.push(tmp)
return tmp
}, 0)
const words = ciphers.reduce((tmp, cipher) => {
return tmp.concat(cipher.words || cipher.ciphertext.words)
}, [])
return {sigBytes, sigBytesMap, words}
}
function getBlob (sigBytes, words) {
const bytes = new Uint8Array(sigBytes)
for (var i = 0; i < sigBytes; i++) {
const byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
bytes[i] = byte
}
return new Blob([ new Uint8Array(bytes) ])
}
函数getCipherInfo(密码){
常量sigBytesMap=[]
const sigBytes=密码。reduce((tmp,cipher)=>{
tmp+=cipher.sigBytes | | cipher.ciphertext.sigBytes
sigBytesMap.push(tmp)
返回tmp
}, 0)
const words=密码。reduce((tmp,密码)=>{
返回tmp.concat(cipher.words | | cipher.ciphertext.words)
}, [])
返回{sigBytes,sigBytesMap,words}
}
函数getBlob(sigBytes,words){
常量字节=新的Uint8Array(sigBytes)
对于(变量i=0;i我还应该提到,以前我做了一些不同的加密。我使用默认编码(我相信是
CryptoJS.enc.Hex
)的toString
方法对作为CryptoJS.AES.encrypt
结果得到的每个字数组进行了字符串化,但有些文件没有正确解密。它与原始文件的大小无关,而与它们的类型无关。再说一遍,我猜 原来问题在于CryptoJS.AES返回的WordArray
。decrypt(value,key)
有4个额外的单词作为填充,不应包含在最终结果中。CryptoJS尝试添加结果,但只会相应地更改sigBytes
,而不会更改单词。因此,在解密时,在将块写入文件之前,请弹出这些额外的单词。4个单词代表完整的块,3个单词代表较小的块(最后一块)。1)你为什么这样做?2) 你知道那是不安全的吗?使用这种加密技术,您到底实现了什么?由于它是浏览器到浏览器-密钥将是可见的,那么重点是什么?是k
硬编码还是通过非对称加密检索?@Mjh实现零知识加密,因此我们将无法访问用户的数据。如果你有密钥,你就有了关于数据的知识。既然你有钥匙,这个零知识原则就被打破了。SSL/TLS有什么问题?对,你用什么加密数据?用户的公钥?公钥加密对可以加密的数据量有限制。你的系统的整个前提听起来完全不正确——你有一个可以看到其内容的文件。如果看不到内容,就不需要加密。您只需将损坏的blob传递给另一个人,他将通过向所有者询问密钥来解密它。你在这里有太多的错误决定,如果我知道你提供的是哪种服务,我永远不会注册。没有怨恨,这里有太多的“错误”。
function getCipherInfo (ciphers) {
const sigBytesMap = []
const sigBytes = ciphers.reduce((tmp, cipher) => {
tmp += cipher.sigBytes || cipher.ciphertext.sigBytes
sigBytesMap.push(tmp)
return tmp
}, 0)
const words = ciphers.reduce((tmp, cipher) => {
return tmp.concat(cipher.words || cipher.ciphertext.words)
}, [])
return {sigBytes, sigBytesMap, words}
}
function getBlob (sigBytes, words) {
const bytes = new Uint8Array(sigBytes)
for (var i = 0; i < sigBytes; i++) {
const byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
bytes[i] = byte
}
return new Blob([ new Uint8Array(bytes) ])
}