(function(root){'use strict';const enc=new TextEncoder(),dec=new TextDecoder('utf-8',{fatal:true}),iterations=600000;
function password(v){if(typeof v!=='string'||v.length<12||v.length>1024)throw Error('Use a password of 12–1,024 characters. It is not stored and cannot be recovered here.');return v;}
const b64=v=>{let s='';for(let i=0;i<v.length;i+=8192)s+=String.fromCharCode(...v.slice(i,i+8192));return btoa(s);},bytes=s=>{if(typeof s!=='string'||s.length>3000000||!/^[A-Za-z0-9+/]*={0,2}$/.test(s))throw Error('Invalid encrypted backup encoding.');return Uint8Array.from(atob(s),c=>c.charCodeAt(0));};
async function key(p,salt){if(!root.crypto?.subtle)throw Error('Encrypted backups require Web Crypto in a secure browser.');const source=await root.crypto.subtle.importKey('raw',enc.encode(password(p)),'PBKDF2',false,['deriveKey']);return root.crypto.subtle.deriveKey({name:'PBKDF2',hash:'SHA-256',salt,iterations},source,{name:'AES-GCM',length:256},false,['encrypt','decrypt']);}
async function encrypt(text,p){if(typeof text!=='string'||enc.encode(text).length>2000000)throw Error('Maximum plaintext backup is 2 MB.');const salt=root.crypto.getRandomValues(new Uint8Array(16)),iv=root.crypto.getRandomValues(new Uint8Array(12)),k=await key(p,salt),data=new Uint8Array(await root.crypto.subtle.encrypt({name:'AES-GCM',iv,additionalData:enc.encode('litecoin.watch.portfolio.encrypted/v1')},k,enc.encode(text)));return JSON.stringify({format:'litecoin.watch.portfolio.encrypted',version:1,kdf:'PBKDF2-SHA256',iterations,cipher:'AES-256-GCM',salt:b64(salt),iv:b64(iv),data:b64(data)},null,2);}
async function decrypt(text,p){if(text.length>3000000)throw Error('Maximum encrypted backup is 3 MB.');const v=JSON.parse(text);if(v.format!=='litecoin.watch.portfolio.encrypted'||v.version!==1||v.iterations!==iterations||v.kdf!=='PBKDF2-SHA256'||v.cipher!=='AES-256-GCM')throw Error('Unsupported encrypted backup version.');const salt=bytes(v.salt),iv=bytes(v.iv),data=bytes(v.data);if(salt.length!==16||iv.length!==12||data.length<17||data.length>2000016)throw Error('Invalid encrypted backup lengths.');const k=await key(p,salt);try{return dec.decode(await root.crypto.subtle.decrypt({name:'AES-GCM',iv,additionalData:enc.encode('litecoin.watch.portfolio.encrypted/v1')},k,data));}catch{throw Error('Cannot decrypt: wrong password or a damaged backup. Nothing was imported.');}}
const api={encrypt,decrypt};if(typeof module==='object'&&module.exports)module.exports=api;else root.LwPortfolioCrypto=api;
})(typeof globalThis!=='undefined'?globalThis:this);
