R&Q плагин для шифрования переписки между двумя крысо-клиентами посредством AES 256-bit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
ratcrypt/RatCrypt.dpr

265 lines
8.5 KiB

library RatCrypt;
uses
Classes,
windows,
plugin,
pluginutil,
CallExec,
SysUtils,
Graphics,
elAES,
Math,
MyOverLite,
Forms,
setpassform in 'setpassform.pas' {setpass};
{$I NoRTTI.inc}
{$R RatCrypt.res}
{$R 'icons.res' 'Icons/icons.rc'}
var
msg, msgcrypt, andrqPath: ansistring;
size, uin, flags, vApiVersion, currentUIN: Integer;
sSource, sDest: TStringStream;
Key: TAESKey256;
When: TDateTime;
ba: Integer;
hico: TIcon;
const
namepl: ansistring = 'RatCrypt 0.45';
function StringToHex(const value: ansistring): ansistring;
var
abyte: TBytes;
i: Integer;
begin
result := '';
abyte := TEncoding.UTF8.GetBytes(value);
for i := 0 to length(abyte) - 1 do
begin
result := result + IntToHex(abyte[i], 2);
end;
end;
function HexToString(const value: ansistring): ansistring;
var
i, idx: Integer;
abyte: TBytes;
begin
result := '';
SetLength(abyte, length(value) div 2);
i := 1;
idx := 0;
while i <= length(value) do
begin
abyte[idx] := StrToInt('$' + value[i] + value[i + 1]);
i := i + 2;
idx := idx + 1;
end;
result := TEncoding.UTF8.GetString(abyte);
end;
procedure OnButtonClick(iButton: Integer);
var MonNum: Integer;
begin
case iButton of
1:
begin
if not fileexists(userPath + 'RatCryptWho.ini') then
setpass.memo1.lines.savetofile(userPath + 'RatCryptWho.ini');
MonNum := Screen.MonitorFromWindow(GetForegroundWindow, mdNearest).MonitorNum;
setpass.Top := Screen.Monitors[MonNum].Top + ((Screen.Monitors[MonNum].Height div 2) - (setpass.Height div 2));
setpass.Left := Screen.Monitors[MonNum].Left + ((Screen.Monitors[MonNum].Width div 2) - (setpass.Width div 2));
setpass.show;
end;
0:
begin
Global := not Global;
if Global = true then
hico.Handle := LoadIcon(HInstance, 'RNQ_CRYPT')
else
hico.Handle := LoadIcon(HInstance, 'RNQ');
RQ_ChangeChatButton(ba, hico.Handle, namepl);
setpass.SaveSettings;
end;
2:
smsg(namepl + ' <EFBFBD> Mikanoshi [Algorithm: AES 256 bit]', trans_about);
end;
end;
function pluginFun(data: pointer): pointer; stdcall;
var i: Integer; stt: TStringList;
begin
result := nil;
if (data = nil) or (_int_at(data) = 0) then
exit;
case _byte_at(data, 4) of
PM_EVENT:
case _byte_at(data, 5) of
PE_INITIALIZE:
begin
RQ__ParseInitString(data, callback, vApiVersion, andrqPath, userPath, currentUIN);
{
userPath := IncludeTrailingPathDelimiter(ExtractFilePath(application.ExeName)) + 'plugins\';
if fileexists(userPath + 'RatCryptPath.ini') then
begin
stt := TStringList.create;
stt.LoadFromFile(userPath + 'RatCryptPath.ini');
userPath := stt[0];
stt.Free;
end;
}
if userPath[length(userPath)] <> '\' then
userPath := userPath + '\';
setpass := TSetPass.create(nil);
hico := TIcon.create;
Global := false;
hico.Handle := LoadIcon(HInstance, 'RNQ');
if fileexists(userPath + 'RatCrypt.ini') then
begin
stt := TStringList.create;
stt.LoadFromFile(userPath + 'RatCrypt.ini');
if stt[0] = 'on' then
begin
Global := true;
hico.Handle := LoadIcon(HInstance, 'RNQ_CRYPT');
end
else
begin
Global := false;
hico.Handle := LoadIcon(HInstance, 'RNQ');
end;
stt.Free;
end;
// smsg('RATCRYPT 7');
ba := RQ_CreateChatButton(@OnButtonClick, hico.Handle, namepl);
// smsg('RATCRYPT 8');
result := str2comm(char(PM_DATA) + _istring(namepl) + _int(APIversion));
end;
PE_FINALIZE:
begin
if ba <> 0 then
RQ_DeleteChatButton(ba);
if hico <> nil then
hico.Free;
setpass.Free;
end;
PE_MSG_SENT:
if Global = true then
if fileexists(userPath + 'RatCryptWho.ini') then
begin
RQ__ParseMsgSentString(data, uin, flags, msg);
for i := 0 to setpass.memo1.lines.count - 1 do
if setpass.memo1.lines[i] = its(uin) then
try
sSource := TStringStream.create(msg);
sDest := TStringStream.create('');
size := sSource.size;
sDest.WriteBuffer(size, SizeOf(size));
FillChar(Key, SizeOf(Key), 0);
if setpass.pass_check.Checked = true then
Move(PChar(setpass.Edit1.Text)^, Key, Min(SizeOf(Key), length(setpass.Edit1.Text)))
else if fileexists(setpass.Edit2.Text) or fileexists(userPath + setpass.Edit2.Text) then
begin
stt := TStringList.create;
if fileexists(userPath + setpass.Edit2.Text) then
stt.LoadFromFile(userPath + setpass.Edit2.Text)
else if fileexists(setpass.Edit2.Text) then
stt.LoadFromFile(setpass.Edit2.Text);
Move(PChar(stt[0])^, Key, Min(SizeOf(Key), length(stt[0])));
stt.Free;
end
else
begin
result := str2comm(char(PM_ABORT));
smsg(trans_keynotfound, trans_warn);
exit;
end;
EncryptAESStreamECB(sSource, 0, Key, sDest);
result := str2comm(char(PM_DATA) + _istring('#RCRPT:' + StringToHex(sDest.DataString)) + _istring(msg));
sSource.Free;
sDest.Free;
break;
except
result := str2comm(char(PM_ABORT));
smsg(trans_crypterr);
break;
end;
end;
PE_MSG_GOT:
begin
RQ__ParseMsgGotString(data, uin, flags, When, msg);
if pos('#RCRPT:', msg) = 1 then
try
msg := copy(msg, 8, length(msg));
sSource := TStringStream.create(HexToString(msg));
sDest := TStringStream.create('');
size := sSource.size;
sSource.ReadBuffer(size, SizeOf(size));
FillChar(Key, SizeOf(Key), 0);
if setpass.pass_check.Checked = true then
Move(PChar(setpass.Edit1.Text)^, Key, Min(SizeOf(Key), length(setpass.Edit1.Text)))
else if fileexists(setpass.Edit2.Text) or fileexists(userPath + setpass.Edit2.Text) then
begin
stt := TStringList.create;
if fileexists(userPath + setpass.Edit2.Text) then
stt.LoadFromFile(userPath + setpass.Edit2.Text)
else if fileexists(setpass.Edit2.Text) then
stt.LoadFromFile(setpass.Edit2.Text);
Move(PChar(stt[0])^, Key, Min(SizeOf(Key), length(stt[0])));
stt.Free;
end
else
begin
smsg(trans_keynotfound2, trans_warn);
exit;
end;
DecryptAESStreamECB(sSource, sSource.size - sSource.Position, Key, sDest);
msgcrypt := sDest.DataString;
while msgcrypt[length(msgcrypt)] = #00 do
msgcrypt := copy(msgcrypt, 1, length(msgcrypt) - 1);
// callStr(char(PM_CMD)+char(PC_ADD_MSG)+_int(uin)+_dt(now)+_istring(msgcrypt));
sSource.Free;
sDest.Free;
result := str2comm(char(PM_DATA) + _istring(msgcrypt));
except
result := str2comm(char(PM_DATA) + _istring(trans_origmsg + #13#10 + '#RCRPT:' + msg));
end;
end;
PE_PREFERENCES:
smsg(namepl + ' <EFBFBD> Mikanoshi [Algorithm: AES 256 bit]', trans_about);
end;
end; // cases
end; // pluginFun
exports
pluginFun;
end.