/* * Jubal's encrypting tool * call_out version. (doesn't work) * * This program reads in a file and: * decrypts the file if it ends in EXTENSION * encrypts the file otherwise * The encryption is done by rotating with a key that the user selects * The first lines of the file are the header * Then, the next line is the key encrypted with crypt() (for checking keys) * After that is the data. * * Enjoy, Jubal (Dave Ljung, ljung@cae.wisc.edu) */ /* consideration: make the write_file a diff. function * and then do a call_out to help take care of too long eval error (big files) */ /* call_out block size */ #define BLOCK 100 /* last character of header MUST be '\n' */ #define HEADER "\ This file was created by Jubal's 'crypt' program\n\ Please do not alter it in ANY way as this will destroy the contents\n\ -------------------------------------------------------------------\n" /* filename extension */ #define EXTENSION ".x" /* don't touch this! :) */ #define CHARS ({"`","1","2","3","4","5","6","7","8","9","0","-","="," ", \ "q","w","e","r","t","y","u","i","o","p","[","]","\\","a","s","d","f","g","h", \ "j","k","l",";","'","z","x","c","v","b","n","m",",",".","/"," ","~","!","@", \ "#","$","%","^","&","*","(",")","_","+","Q","W","E","R","T","Y","U","I","O", \ "P","{","}","|","A","S","D","F","G","H","J","K","L",":","\"","Z","X","C","V", \ "B","N","M","<",">","?"}) /* global variables! Don't let two players use this command at once! */ string name,newname; int crypt,overwrite; string tmpkey; main(what) { int totlines,l; if(!what) return !notify_fail("Usage: crypt \n"); name=mk_path(what); l=file_size(name); if(l==-1) { if(file_size(name+EXTENSION)==-1) return write(name+" does not exist\n"), 1; name=name+EXTENSION; l=file_size(name); } if(l==-2) return write(name+" is a directory\n"), 1; if(l==0) return write(name+" is empty\n"), 1; l=strlen(name); if(name[l-strlen(EXTENSION)..l-1]==EXTENSION) { newname=name[0..l-strlen(EXTENSION)-1]; crypt=0; } else { newname=name+EXTENSION; crypt=1; } overwrite=0; write((crypt?"En":"De")+"crypting: " +name+" ("+(l/1000)+"."+(l-(l/1000*1000))+"k) to "+newname+"\n"); write("Key: "); if(!crypt) input_to("get_key2",1); else input_to("get_key1",1); return 1; } get_key1(key) { tmpkey=key; write("\nKey (again): "); input_to("get_key2",1); } get_key2(key) { int i,l; write("\n"); if(crypt && key!=tmpkey) { write("You changed!\n"); tmpkey=0; key=0; return 1; } tmpkey=0; file_crypt(key,!crypt,name,newname); return 1; } /* the encryption routine */ file_crypt(key,decrypt,name,newname) { int lines,len,i,j,s1,s2,c,k; string in,out,*chars,seed,hdr; chars=CHARS; s1=sizeof(chars); s2=strlen(key)-1; k=0; i=1; if(file_size(newname)!=-1) if(!overwrite) return write(newname+" already exists\n"), 0; else if(!rm(newname)) return write("Could not remove "+newname+"\n"), 0; if(decrypt) { hdr=explode(HEADER,"\n"); while(i<=sizeof(hdr)) { if(read_file(name,i)!=hdr[i-1]+"\n") return write("Corrupt header\n"), 0; i++; } in=read_file(name,i); if(crypt(key,in)!=in[0..strlen(in)-2]) return write("Wrong key\n"), 0; i++; } else { j=random(s1); if(chars[j]=="\n") j=5; seed=chars[j]; j=random(s1); if(chars[j]=="\n") j=6; seed+=chars[j]; if(!write_file(newname,HEADER+crypt(key,seed)+"\n")) return write("ERROR: writing header\n"), 0; } write("call_out"); call_out("do_lines",1,({key,name,newname,i,k,decrypt,this_player()})); } do_lines(args) { string key,name,newname; int i,k,decrypt; object tp; string *chars,in,out; int j,len,s1,s2,c; key=args[0]; name=args[1]; newname=args[2]; i=args[3]; k=args[4]; decrypt=args[5]; tp=args[6]; chars=CHARS; s1=sizeof(chars); s2=strlen(key)-1; tell_object(tp,"here\n"+name+i+read_file(name,i)); while(in=read_file(name,i)) { i++; len=strlen(in); out=""; for(j=0;j=s1) c-=s1; k=k+1>s2?0:k+1; out+=chars[c]; } } tell_object(tp,"here\n"); if(!write_file(newname,out)) return tell_object(tp,"ERROR: writing line: "+i+" to: "+newname+"\n"), 0; } tell_object(tp,"HEY\n"); done(tp); return 1; } done(tp) { if(!rm(name)) tell_object(tp,"Couldn't remove file: "+name+"\n"); else tell_object(tp,"Done.\n"); } /* this can be altered in many ways -- use valid_write, mk_path, whatever */ /* make sure it returns the prepending "/" */ mk_path(name) { /* resolve_path and prepending '/' for use on Virtual Realities */ return "/"+resolve_path(this_player()->query_path(),name); return this_player()->mk_path(name); }