mirror of
https://github.com/fzxx/XiangYue.git
synced 2025-11-25 11:29:25 +08:00
3 lines
4.7 KiB
JavaScript
3 lines
4.7 KiB
JavaScript
const encryptionMethod1={async deriveKey(password,salt){try{const passwordBuffer=utils.stringToArrayBuffer(password);const pbkdf2Key=await crypto.subtle.importKey('raw',passwordBuffer,{name:'PBKDF2'},false,['deriveBits']);const pbkdf2Bits=await crypto.subtle.deriveBits({name:'PBKDF2',salt,iterations:500000,hash:'SHA-256'},pbkdf2Key,512);const hkdfKey=await crypto.subtle.importKey('raw',pbkdf2Bits,{name:'HKDF'},false,['deriveBits']);const aesBits=await crypto.subtle.deriveBits({name:'HKDF',hash:'SHA-256',salt:new Uint8Array(0),info:utils.stringToArrayBuffer('AES-CTR')},hkdfKey,256);const chachaBits=await crypto.subtle.deriveBits({name:'HKDF',hash:'SHA-256',salt:new Uint8Array(0),info:utils.stringToArrayBuffer('ChaCha20')},hkdfKey,256);const aesCtrKey=await crypto.subtle.importKey('raw',aesBits,{name:'AES-CTR'},false,['encrypt','decrypt']);return{aesCtrKey,chachaKey:new Uint8Array(chachaBits)};}catch(error){console.error('密钥派生失败:',error);throw new Error('密钥派生过程发生错误,请检查输入参数');}},async encryptAESCTR(plaintext,key){try{const counter=utils.generateRandomBytes(16);const encrypted=await crypto.subtle.encrypt({name:'AES-CTR',counter,length:128},key,plaintext);return new Uint8Array([...counter,...new Uint8Array(encrypted)]).buffer;}catch(error){console.error('AES-CTR加密失败:',error);throw new Error('AES-CTR加密过程发生错误');}},async decryptAESCTR(ciphertext,key){try{const counter=ciphertext.slice(0,16);const encrypted=ciphertext.slice(16);return crypto.subtle.decrypt({name:'AES-CTR',counter,length:128},key,encrypted);}catch(error){console.error('AES-CTR解密失败:',error);throw new Error('AES-CTR解密过程发生错误,可能密钥不正确');}},async encryptChaCha20Poly1305(plaintext,key){try{const nonce=sodium.randombytes_buf(12);const encrypted=sodium.crypto_aead_chacha20poly1305_ietf_encrypt(new Uint8Array(plaintext),null,null,nonce,key);return new Uint8Array([...nonce,...encrypted]).buffer;}catch(error){console.error('ChaCha20加密失败:',error);throw new Error('ChaCha20加密过程发生错误');}},async decryptChaCha20Poly1305(ciphertext,key){try{const nonce=ciphertext.slice(0,12);const encrypted=ciphertext.slice(12);return sodium.crypto_aead_chacha20poly1305_ietf_decrypt(null,new Uint8Array(encrypted),null,new Uint8Array(nonce),key);}catch(error){console.error('ChaCha20解密失败:',error);throw new Error('ChaCha20解密过程发生错误,可能密钥或数据已损坏');}},isBase64(str){return/^[A-Za-z0-9+/=]+$/.test(str);},async encrypt(plaintext,password,outputMode='base64'){try{const salt=utils.generateRandomBytes(16);const{aesCtrKey,chachaKey}=await this.deriveKey(password,salt);const compressed=await utils.compressData(utils.stringToArrayBuffer(plaintext));const aesCtrEncrypted=await this.encryptAESCTR(compressed,aesCtrKey);const chachaEncrypted=await this.encryptChaCha20Poly1305(aesCtrEncrypted,chachaKey);const combined=new Uint8Array([...salt,...new Uint8Array(chachaEncrypted)]);let result=utils.arrayBufferToBase64(combined.buffer);switch(outputMode){case'chinese':result=mappingMode1.base64ToChinese(result);break;case'emoji':result=mappingMode2.base64ToEmoji(result);break;case'zero-width':result=mappingMode3.base64ToZeroWidth(result);break;}
|
||
return result;}catch(error){console.error('数据加密失败:',error);throw new Error(`加密过程发生错误: ${error.message}`);}},async decrypt(ciphertext,password){try{const detectedMode=utils.detectCiphertextType(ciphertext);let processedCiphertext=ciphertext;if(detectedMode==='emoji'){processedCiphertext=mappingMode2.emojiToBase64(ciphertext);}else if(detectedMode==='chinese'){processedCiphertext=mappingMode1.chineseToBase64(ciphertext);}else if(detectedMode==='zero-width'){processedCiphertext=mappingMode3.zeroWidthToBase64(ciphertext);}else if(detectedMode==='base64'||detectedMode==='weibase64'){processedCiphertext=ciphertext.replace(/[^A-Za-z0-9+/=]/g,'');}
|
||
const ciphertextBuffer=utils.base64ToArrayBuffer(processedCiphertext);const salt=ciphertextBuffer.slice(0,16);const encryptedData=ciphertextBuffer.slice(16);const{aesCtrKey,chachaKey}=await this.deriveKey(password,salt);const chachaDecrypted=await this.decryptChaCha20Poly1305(encryptedData,chachaKey);const aesCtrDecrypted=await this.decryptAESCTR(chachaDecrypted,aesCtrKey);return utils.arrayBufferToString(await utils.decompressData(aesCtrDecrypted));}catch(error){console.error('数据解密失败:',error);if(error.message.includes('decryption failed')){throw new Error('解密失败:可能密码错误或数据已损坏');}else if(error.message.includes('key derivation')){throw new Error('密钥派生失败:请检查密码长度和复杂度');}else{throw new Error(`解密过程发生错误: ${error.message}`);}}}}; |