credentials.mjs 1.5 KB

1234567891011121314151617181920212223
  1. import {createHash} from 'node:crypto'
  2. import {execFile} from 'node:child_process'
  3. const prefix=Buffer.from('YAOYAO-RUNNER-KEYCHAIN-1\n')
  4. export class DesktopCredentials {
  5. constructor({home,helper,legacyDecrypt}){this.account=createHash('sha256').update(home).digest('hex');this.helper=helper;this.legacyDecrypt=legacyDecrypt}
  6. async invoke(operation,input){
  7. if(input.length>1048576)throw new Error('执行节点配置超过加密大小上限')
  8. return new Promise((resolve,reject)=>{
  9. const child=execFile(this.helper,[operation,this.account],{encoding:'buffer',timeout:30000,killSignal:'SIGKILL',maxBuffer:1048576},(error,stdout)=>{
  10. if(error)reject(new Error('无法访问当前数据目录的系统加密密钥,请完成钥匙串授权后重试'))
  11. else resolve(stdout)
  12. })
  13. child.stdin.on('error',()=>{});child.stdin.end(input)
  14. })
  15. }
  16. async encrypt(value){return Buffer.concat([prefix,await this.invoke('encrypt',Buffer.from(value))])}
  17. async decrypt(value){
  18. if(value.subarray(0,prefix.length).equals(prefix))return (await this.invoke('decrypt',value.subarray(prefix.length))).toString('utf8')
  19. // Existing safeStorage files remain readable after the user grants normal OS access.
  20. let timer
  21. try{return await Promise.race([this.legacyDecrypt(value),new Promise((_,reject)=>{timer=setTimeout(()=>reject(new Error('旧配置等待钥匙串授权,请完成系统授权后重试')),30000)})])}finally{clearTimeout(timer)}
  22. }
  23. }