summaryrefslogtreecommitdiff
path: root/rsa.lpr
diff options
context:
space:
mode:
authorErich Eckner <git@eckner.net>2015-07-10 14:59:23 +0200
committerErich Eckner <git@eckner.net>2015-07-10 14:59:23 +0200
commita86ecfdaccf8c050e4a22fdb2807d48b1d7748b6 (patch)
tree63c4e32bea88d826ec958d4d0107e600d2b3207e /rsa.lpr
downloadrsa-master.tar.xz
initialer CommitHEADmaster
Diffstat (limited to 'rsa.lpr')
-rw-r--r--rsa.lpr430
1 files changed, 430 insertions, 0 deletions
diff --git a/rsa.lpr b/rsa.lpr
new file mode 100644
index 0000000..015c2f4
--- /dev/null
+++ b/rsa.lpr
@@ -0,0 +1,430 @@
+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 gelesen<zulesen do begin
+ if gelesen=0 then begin
+ for i:=0 to 7 do
+ buff[i]:=(filesize(binf) shr (8*i)) and $ff;
+ gelesen:=8;
+ i:=8 div sizeof(buff[0]);
+ end
+ else i:=0;
+
+ j:=min((length(buff)-i)*sizeof(buff[0]),zulesen-gelesen);
+ blockread(binf,buff[i],j);
+ gelesen:=gelesen + j;
+
+ mpz_set_ui(n1,0);
+ for j:=0 to length(buff)-1 do begin
+ mpz_mul_2exp(n1,n1,sizeof(buff[j])*8);
+ mpz_add_ui(n1,n1,buff[j]);
+ end;
+
+ mpz_powm(n2,n1,e_Exponent,modul);
+ writeln(textf,mpz_get_str(nil,16,n2));
+ end;
+
+ 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;
+
+ raDec: begin
+ write('Passwort des Schlüssels eingeben: ');
+ readlnblind(pass);
+
+ 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('d','decrypt')) and $02) = 0 then begin
+ writeln('Keinen privaten Schlüssel in Datei '''+GetOptionValue('d','decrypt')+''' gefunden!');
+ Terminate;
+ Exit;
+ end;
+ symmetricEncryption(d_exponent,pass,edDec,version);
+
+ setlength(buff,1);
+ setlength(buff,(mpz_sizeinbase(modul,256) div sizeof(buff[0]))-1);
+ fillchar(buff[0],length(buff)*sizeof(buff[0]),0);
+
+ gelesen:=0;
+ zulesen:=-1;
+
+ assignfile(textf,GetOptionValue('i','input'));
+ reset(textf);
+ assignfile(binf,GetOptionValue('o','output'));
+ rewrite(binf,1);
+ while not eof(textf) do begin
+ readln(textf,s);
+ mpz_set_str(n1,pchar(s),16);
+ mpz_powm(n2,n1,d_Exponent,modul);
+
+ for i:=length(buff)-1 downto 0 do begin
+ buff[i]:=mpz_get_ui(n2) and $ff;
+ mpz_fdiv_q_2exp(n2,n2,8);
+ end;
+
+ if gelesen=0 then begin
+ zulesen:=0;
+ for i:=0 to 7 do
+ zulesen:=zulesen*256+buff[7-i];
+ i:=8 div sizeof(buff[0]);
+ end
+ else
+ i:=0;
+
+ j:=min(zulesen-gelesen,(length(buff)-i)*sizeof(buff[0]));
+ if j>0 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.
+