| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- import fs from 'node:fs';
- import path from 'node:path';
- import crypto from 'node:crypto';
- export const COMPANY='FKieRbIoGt', APP='FKieRbIoGt_main';
- export const AGENT='agent-node-kangshifu', HOST='6f03725e5dc8';
- export const SKILL='/opt/data/skills/ksf-workshop-runtime';
- export const PURPOSE='KSF-credential-receive-20261031';
- export const WRAPPER_SHA='10abc8fcb4c0dd459ff15c086668608b404cc0d61efaf559213a90d0a573ce75';
- export const DECRYPTOR_SHA='43e462c21053c2829402e218b05aaa4438aed9552f561d54582675e687a63f79';
- export const DELIVERY_FILES=['RELEASE.json','credential-binding.json','credential-envelope.json','decrypt-envelope.mjs'];
- export const SCOPES=['data:read','source:write','ingest:write'];
- export const sha=raw=>crypto.createHash('sha256').update(raw).digest('hex');
- export const encode=value=>Buffer.from(JSON.stringify(value,null,2)+'\n');
- export const fail=code=>{throw Object.assign(Error(code),{code});};
- export const need=(value,code)=>{if(!value)fail(code);};
- export function plain(file){
- need(path.isAbsolute(file),'ABSOLUTE_PATH_REQUIRED');
- for(let p=path.resolve(file);;p=path.dirname(p)){
- if(fs.existsSync(p))need(!fs.lstatSync(p).isSymbolicLink(),'SYMLINK_PATH');
- if(path.dirname(p)===p)break;
- }
- return path.resolve(file);
- }
- export function writeNew(file,bytes){
- plain(file);fs.mkdirSync(path.dirname(file),{recursive:true,mode:0o700});
- const fd=fs.openSync(file,'wx',0o600);
- try{fs.writeFileSync(fd,bytes);fs.fsyncSync(fd);}finally{fs.closeSync(fd);}
- }
- export function readPrivate(file){
- plain(file);const stat=fs.lstatSync(file);
- need(stat.isFile(),'NOT_PLAIN_FILE');
- if(process.platform==='linux')need(stat.uid===process.geteuid()&&(stat.mode&0o777)===0o600,'PRIVATE_FILE_PERMISSIONS');
- return fs.readFileSync(file);
- }
- export function privateDirectory(file){
- plain(file);const s=fs.lstatSync(file);need(s.isDirectory(),'NOT_DIRECTORY');
- if(process.platform==='linux')need(s.uid===process.geteuid()&&(s.mode&0o777)===0o700,'PRIVATE_DIRECTORY_PERMISSIONS');
- }
- export function readDelivery(directory,expectedSha){
- plain(directory);need(/^[a-f0-9]{64}$/.test(expectedSha||''),'BUNDLE_MANIFEST_SHA_REQUIRED');
- need(JSON.stringify(fs.readdirSync(directory).sort())===JSON.stringify([...DELIVERY_FILES,'FILES.sha256'].sort()),'UNEXPECTED_DELIVERY_FILES');
- const manifest=readPrivate(path.join(directory,'FILES.sha256'));
- need(sha(manifest)===expectedSha,'DELIVERY_MANIFEST_MISMATCH');
- const entries=manifest.toString('utf8').trim().split('\n').map(line=>line.match(/^([a-f0-9]{64}) ([A-Za-z.-]+)$/));
- need(entries.every(Boolean)&&JSON.stringify(entries.map(m=>m[2]).sort())===JSON.stringify(DELIVERY_FILES),'INVALID_DELIVERY_MANIFEST');
- const files={};for(const[,digest,name]of entries){files[name]=readPrivate(path.join(directory,name));need(sha(files[name])===digest,'DELIVERY_FILE_MISMATCH');}
- return{files,manifest};
- }
- export function recipientInfo(value){
- need(value?.schema==='ksf.enterprise-workshop-recipient.v1'&&value.publicOnly===true,'INVALID_RECIPIENT');
- need(value.companyObjectId===COMPANY&&value.appId===APP&&value.agentId===AGENT
- &&value.host===HOST,'RECIPIENT_IDENTITY_MISMATCH');
- need(/^\/opt\/data\/ksf-key-receive-20261031-[A-Za-z0-9]+$/.test(value.keyDirectory),'BAD_KEY_DIRECTORY');
- need(typeof value.publicKeyPem==='string'&&value.publicKeyPem.startsWith('-----BEGIN PUBLIC KEY-----'),'INVALID_PUBLIC_KEY');
- const key=crypto.createPublicKey(value.publicKeyPem);
- need(key.asymmetricKeyType==='rsa'&&key.asymmetricKeyDetails.modulusLength>=3072,'WEAK_PUBLIC_KEY');
- need(sha(key.export({type:'spki',format:'der'}))===value.publicKeySha256,'PUBLIC_KEY_FINGERPRINT_MISMATCH');
- need(value.privateKeyExported===false&&value.tokenExported===false,'PRIVATE_RECIPIENT_EXPORT_REJECTED');
- return value;
- }
- export function argsOf(argv,allowed){
- const values={};for(let i=0;i<argv.length;i+=2){const[k,v]=argv.slice(i,i+2);
- need(allowed.includes(k)&&v&&!values[k]&&!v.startsWith('--'),'USAGE');values[k]=v;}
- return values;
- }
- export function errorReceipt(error){return{ok:false,error:{code:/^[A-Z][A-Z0-9_]+$/.test(error.code||'')?error.code:'AUTHORIZATION_STOPPED'},businessRecordWrites:0};}
|