program rsa; {$mode objfpc}{$H+} {$DEFINE UseCThreads} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes, SysUtils, CustApp, { you can add units after this } gmp, math, rsaunit, crt; type { TRSAApplication } TRSAApplication = class(TCustomApplication) protected procedure DoRun; override; public constructor Create(TheOwner: TComponent); override; destructor Destroy; override; procedure WriteHelp; virtual; end; { TRSAApplication } procedure TRSAApplication.DoRun; var ErrorMsg,s,version: String; pass: tLockedString; n1,n2,n3,modul, e_exponent,d_exponent: mpz_t; state: randstate_t; i,j,bits,maxThreads: longint; gelesen,zulesen: int64; binf: file; textf: textfile; buff: array of byte; privOut,pubOut: textfile; act: tRSAAction; begin // parse parameters maxThreads:=1; pass:=nil; if HasOption('g','generate') then begin act:=raGen; ErrorMsg:=CheckOptions('g:b:rt:','generate: bits: randomize threads:'); if HasOption('b','bits') then bits:=strtoint(GetOptionValue('b','bits')) div 2 + 1 else bits:=64; if HasOption('t','threads') then maxThreads:=strtoint(GetOptionValue('t','threads')); end else if HasOption('e','encrypt') then begin act:=raEnc; ErrorMsg:=CheckOptions('e:i:o:','encrypt: input: output:'); if (ErrorMsg='') and not (HasOption('i','input') and HasOption('o','output')) then ErrorMsg:='Ich benötige zum Verschlüsseln Dateien!'; end else if HasOption('d','decrypt') then begin act:=raDec; ErrorMsg:=CheckOptions('d:i:o:','decrypt: input: output:'); if (ErrorMsg='') and not (HasOption('i','input') and HasOption('o','output')) then ErrorMsg:='Ich benötige zum Entschlüsseln Dateien!'; end else if HasOption('c','check') then begin act:=raChk; ErrorMsg:=CheckOptions('c:','check:'); end else if HasOption('u','update') then begin act:=raUpd; ErrorMsg:=CheckOptions('u:','update:'); end else begin act:=raUnk; WriteHelp; Terminate; Exit; end; if ErrorMsg<>'' then begin ShowException(Exception.Create(ErrorMsg)); Terminate; Exit; end; { add your program here } case act of raGen: begin readNewPassword(pass,ceil(sqrt(bits/8))); mpz_init(n1); mpz_init(n2); mpz_init(n3); mpz_init(modul); mpz_init(e_exponent); mpz_init(d_exponent); assignfile(privOut,GetOptionValue('g','generate')); rewrite(privOut); assignfile(pubOut,GetOptionValue('g','generate')+'.pub'); rewrite(pubOut); if HasOption('r','randomize') then begin s:=acquireRandomness(bits div 4 + 1); mpz_set_str(n1,@(s[1]),16); end else mpz_set_str(n1,'1234567890',10); mp_randinit_default(state); mp_randseed(state,n1); mpz_urandomb(n1,state,bits); mpz_urandomb(n2,state,bits); mpz_ui_pow_ui(n3,2,bits); mpz_add(n1,n1,n3); mpz_add(n2,n2,n3); writeln; write('Suche erste Primzahl ...'); nextPrime(n1,maxThreads); writeln; write('... suche zweite Primzahl ...'); repeat nextPrime(n2,maxThreads); until mpz_cmp(n1,n2)<>0; mpz_mul(modul,n2,n1); mpz_sub_ui(n1,n1,1); mpz_sub_ui(n2,n2,1); mpz_mul(n3,n1,n2); writeln; writeln('... suche Exponenten ...'); repeat mpz_urandomb(e_exponent,state,min(16,bits div 2)); mpz_setbit(e_exponent,0); until mpz_invert(d_exponent,e_exponent,n3)<>0; mpz_set_ui(e_exponent,1025); mpz_sub_ui(d_exponent,modul,1000); writeln('... verschlüssele ...'); symmetricEncryption(d_exponent,pass,edEnc,'latest'); writeln('... speichere ...'); pass.free; writeln(privOut,'Modul: '+mpz_get_str(nil,16,modul)); writeln(privOut,'e-Exponent: '+mpz_get_str(nil,16,e_exponent)); writeln(privOut,'d-Exponent: '+mpz_get_str(nil,16,d_exponent)); writeln(pubOut,'Modul: '+mpz_get_str(nil,16,modul)); writeln(pubOut,'e-Exponent: '+mpz_get_str(nil,16,e_exponent)); writeln('... fertig'); mpz_clear(n1); mpz_clear(n2); mpz_clear(n3); mpz_clear(modul); mpz_clear(e_exponent); mpz_clear(d_exponent); closefile(privOut); closefile(pubOut); end; raEnc: begin mpz_init(n1); mpz_init(n2); mpz_init(n3); mpz_init(modul); mpz_init(e_exponent); mpz_init(d_exponent); if (importKey(modul,e_exponent,d_exponent,version,GetOptionValue('e','encrypt')) and $01) = 0 then begin writeln('Keinen öffentlichen Schlüssel in Datei '''+GetOptionValue('e','encrypt')+''' gefunden!'); Terminate; Exit; end; assignfile(binf,GetOptionValue('i','input')); reset(binf,1); assignfile(textf,GetOptionValue('o','output')); rewrite(textf); setlength(buff,1); setlength(buff,(mpz_sizeinbase(modul,256) div sizeof(buff[0]))-1); gelesen:=0; zulesen:=8+filesize(binf); fillchar(buff[0],length(buff)*sizeof(buff[0]),0); while gelesen0 then blockwrite(binf,buff[i],j); gelesen:=gelesen+j; end; if gelesen <> zulesen then writeln(inttostr(gelesen)+' Bytes geschrieben, aber es waren '+inttostr(zulesen)+' angekündigt!'); closefile(binf); closefile(textf); mpz_clear(n1); mpz_clear(n2); mpz_clear(n3); mpz_clear(modul); mpz_clear(e_exponent); mpz_clear(d_exponent); end; raChk: begin write('Passwort des Schlüssels eingeben: '); readlnblind(pass); mpz_init(n1); mpz_init(n2); mpz_init(modul); mpz_init(e_exponent); mpz_init(d_exponent); if importKey(modul,e_exponent,d_exponent,version,GetOptionValue('c','check')) <> $03 then begin writeln('Der Datei '''+GetOptionValue('c','check')+''' fehlt mindestens ein Schlüsselteil!'); Terminate; Exit; end; symmetricEncryption(d_exponent,pass,edDec,version); for i:=0 to 100 do begin s:=copy(inttostr(i)+paramstr(0),1,mpz_sizeinbase(modul,256)-1); mpz_set_str(n1,pchar(s),256); mpz_powm(n2,n1,e_exponent,modul); mpz_powm(n2,n2,d_exponent,modul); if mpz_cmp(n1,n2)<>0 then writeln('Entschlüsselter Text ist ungleich Original! - Passwort falsch?'); end; writeln('Tests abgeschlossen.'); mpz_clear(n1); mpz_clear(n2); mpz_clear(modul); mpz_clear(e_exponent); mpz_clear(d_exponent); end; raUpd: begin write('Passwort des Schlüssels eingeben: '); readlnblind(pass); mpz_init(n1); mpz_init(n2); mpz_init(modul); mpz_init(e_exponent); mpz_init(d_exponent); if importKey(modul,e_exponent,d_exponent,version,GetOptionValue('u','update')) <> $03 then begin writeln('Der Datei '''+GetOptionValue('u','update')+''' fehlt mindestens ein Schlüsselteil!'); Terminate; Exit; end; symmetricEncryption(d_exponent,pass,edDec,version); write('Neues Passwort vergeben? (j/n) '); readln(s); if pos('j',s)=1 then readNewPassword(pass,ceil(sqrt(mpz_sizeinbase(modul,2)/8))); version:='latest'; symmetricEncryption(d_exponent,pass,edEnc,version); pass.free; repeat write('Ziel zum Speichern eingeben: '); readln(s); until (not fileexists(s)) and (not fileexists(s+'.pub')); assignfile(privOut,s); rewrite(privOut); assignfile(pubOut,s+'.pub'); rewrite(pubOut); writeln(privOut,'Modul: '+mpz_get_str(nil,16,modul)); writeln(privOut,'Version: '+version); writeln(privOut,'e-Exponent: '+mpz_get_str(nil,16,e_exponent)); writeln(privOut,'d-Exponent: '+mpz_get_str(nil,16,d_exponent)); writeln(pubOut,'Modul: '+mpz_get_str(nil,16,modul)); writeln(pubOut,'e-Exponent: '+mpz_get_str(nil,16,e_exponent)); closefile(pubOut); closefile(privOut); mpz_clear(n1); mpz_clear(n2); mpz_clear(modul); mpz_clear(e_exponent); mpz_clear(d_exponent); end; else writeln('Fehler: Funktion noch nicht implementiert!'); end{of case}; // stop program loop Terminate; end; constructor TRSAApplication.Create(TheOwner: TComponent); begin inherited Create(TheOwner); StopOnException:=True; end; destructor TRSAApplication.Destroy; begin inherited Destroy; end; procedure TRSAApplication.WriteHelp; begin { add your help code here } writeln('Usage: ',ExeName,' -h'); writeln(' get help'); writeln('Usage: ',ExeName,' -g/--generate $key [-b/--bits $Bits] [-r/--randomize] [-t/--threads $maxThreads]'); writeln(' generate key'); writeln('Usage: ',ExeName,' -e/--encrypt $key -i/--input $input -o/--output $output'); writeln(' encrypt with key'); writeln('Usage: ',ExeName,' -d/--decrypt $key -i/--input $input -o/--output $output'); writeln(' decrypt with key'); writeln('Usage: ',ExeName,' -c/--check $key'); writeln(' check integrity of key'); writeln('Usage: ',ExeName,' -u/--update $key'); writeln(' update key, possibly change passphrase'); end; var Application: TRSAApplication; begin Application:=TRSAApplication.Create(nil); Application.Title:='RSA Application'; Application.Run; Application.Free; end.