使用 SynCrypto 的 AES 加密问题
Issues with AES Encryption using SynCrypto
我正在尝试使用 SynCrypto.pas 和 AES 256 加密文件,但如果我尝试加密大小不是 16 字节倍数的文件,它会失败。解密数据包含垃圾。
示例:
txt 文件中的原始字符串
we are testing the file
加密字符串
[ù[„|wáî}f *!4ìÙw¬•ü¨s
解密字符串
we are testing tÝp?J
这是我的加密代码
procedure TForm1.Button1Click(Sender: TObject);
var
A: TAES;
Key: TSHA256Digest;
s, B: TAESBlock;
ks: integer;
st: RawByteString;
InStream, OutStream: TFileStream;
SuperNo, TheSize, StreamSize: Int64;
begin
InStream := TFileStream.Create('test.txt', fmOpenRead);
OutStream := TFileStream.Create('out.txt', fmCreate);
InStream.Position := 0;
OutStream.Position := 0;
st := '1234essai';
ks := 256;
SHA256Weak(st, Key);
A.EncryptInit(Key, ks);
StreamSize := InStream.Size;
while InStream.Position < StreamSize do
begin
TheSize := StreamSize - InStream.Position;
if TheSize < 16 then
begin
SuperNo := StreamSize - InStream.Position;
end
else
begin
SuperNo := 16;
end;
InStream.ReadBuffer(s, SuperNo);
A.Encrypt(s, B);
OutStream.WriteBuffer(B, SuperNo);
end;
A.Done;
ShowMessage('Finish');
InStream.Free;
OutStream.Free;
end;
这是我的解密码
procedure TForm1.Button2Click(Sender: TObject);
var
A: TAES;
Key: TSHA256Digest;
s, B: TAESBlock;
ks: integer;
st: RawByteString;
InStream, OutStream: TFileStream;
SuperNo, TheSize, StreamSize: Int64;
begin
InStream := TFileStream.Create('out.txt', fmOpenRead);
OutStream := TFileStream.Create('in.txt', fmCreate);
InStream.Position := 0;
OutStream.Position := 0;
st := '1234essai';
ks := 256;
SHA256Weak(st, Key);
A.DecryptInit(Key, ks);
StreamSize := InStream.Size;
while InStream.Position < StreamSize do
begin
TheSize := StreamSize - InStream.Position;
if TheSize < 16 then
begin
SuperNo := StreamSize - InStream.Position;
end
else
begin
SuperNo := 16;
end;
InStream.ReadBuffer(s, SuperNo);
A.Decrypt(s, B);
OutStream.WriteBuffer(B, SuperNo);
end;
A.Done;
ShowMessage('Finish');
InStream.Free;
OutStream.Free;
end;
使用Delphi XE7。
AES 是一种块密码 算法。这意味着它适用于 AES 的 16 字节大小的块。因此,如果您的数据不适合 16 字节块(您的文本就是这种情况),则需要使用 padding。
与其重新发明轮子,引入错误,不如依赖现有的padding算法。你应该添加一个block chaining mode。目前您使用的默认算法是 ECB,众所周知它很弱,因为它既不使用链接模式也不使用初始化向量 (IV)。
SynCrypto
单元包含一个安全的块链接模式,如 CFB 和 PKCS7 填充,所以你可以写:
var inp,out: RawByteString;
begin
// encryption:
inp := StringFromFile('in.txt');
out := TAESCFB.SimpleEncrypt(inp,'privatekey',true,true);
FileFromString(out,'out.txt');
// or in a single line:
FileFromString(TAESCFB.SimpleEncrypt(StringFromFile('in.txt'),'privatekey',true,true),'out.txt');
// decryption
inp := StringFromFile('out.txt');
out := TAESCFB.SimpleEncrypt(inp,'privatekey',false,true);
FileFromString(out,'in.txt');
end;
以上代码安全且快速,将在提供的 'privatekey'
上使用 SHA-256 生成二进制密钥,如果您 CPU 支持,将使用 AES-NI 硬件指令。您可以使用另一种链接模式,只需将 TAESCFB
class 名称更改为另一种可用类型即可。
我正在尝试使用 SynCrypto.pas 和 AES 256 加密文件,但如果我尝试加密大小不是 16 字节倍数的文件,它会失败。解密数据包含垃圾。
示例:
txt 文件中的原始字符串
we are testing the file
加密字符串
[ù[„|wáî}f *!4ìÙw¬•ü¨s
解密字符串
we are testing tÝp?J
这是我的加密代码
procedure TForm1.Button1Click(Sender: TObject);
var
A: TAES;
Key: TSHA256Digest;
s, B: TAESBlock;
ks: integer;
st: RawByteString;
InStream, OutStream: TFileStream;
SuperNo, TheSize, StreamSize: Int64;
begin
InStream := TFileStream.Create('test.txt', fmOpenRead);
OutStream := TFileStream.Create('out.txt', fmCreate);
InStream.Position := 0;
OutStream.Position := 0;
st := '1234essai';
ks := 256;
SHA256Weak(st, Key);
A.EncryptInit(Key, ks);
StreamSize := InStream.Size;
while InStream.Position < StreamSize do
begin
TheSize := StreamSize - InStream.Position;
if TheSize < 16 then
begin
SuperNo := StreamSize - InStream.Position;
end
else
begin
SuperNo := 16;
end;
InStream.ReadBuffer(s, SuperNo);
A.Encrypt(s, B);
OutStream.WriteBuffer(B, SuperNo);
end;
A.Done;
ShowMessage('Finish');
InStream.Free;
OutStream.Free;
end;
这是我的解密码
procedure TForm1.Button2Click(Sender: TObject);
var
A: TAES;
Key: TSHA256Digest;
s, B: TAESBlock;
ks: integer;
st: RawByteString;
InStream, OutStream: TFileStream;
SuperNo, TheSize, StreamSize: Int64;
begin
InStream := TFileStream.Create('out.txt', fmOpenRead);
OutStream := TFileStream.Create('in.txt', fmCreate);
InStream.Position := 0;
OutStream.Position := 0;
st := '1234essai';
ks := 256;
SHA256Weak(st, Key);
A.DecryptInit(Key, ks);
StreamSize := InStream.Size;
while InStream.Position < StreamSize do
begin
TheSize := StreamSize - InStream.Position;
if TheSize < 16 then
begin
SuperNo := StreamSize - InStream.Position;
end
else
begin
SuperNo := 16;
end;
InStream.ReadBuffer(s, SuperNo);
A.Decrypt(s, B);
OutStream.WriteBuffer(B, SuperNo);
end;
A.Done;
ShowMessage('Finish');
InStream.Free;
OutStream.Free;
end;
使用Delphi XE7。
AES 是一种块密码 算法。这意味着它适用于 AES 的 16 字节大小的块。因此,如果您的数据不适合 16 字节块(您的文本就是这种情况),则需要使用 padding。
与其重新发明轮子,引入错误,不如依赖现有的padding算法。你应该添加一个block chaining mode。目前您使用的默认算法是 ECB,众所周知它很弱,因为它既不使用链接模式也不使用初始化向量 (IV)。
SynCrypto
单元包含一个安全的块链接模式,如 CFB 和 PKCS7 填充,所以你可以写:
var inp,out: RawByteString;
begin
// encryption:
inp := StringFromFile('in.txt');
out := TAESCFB.SimpleEncrypt(inp,'privatekey',true,true);
FileFromString(out,'out.txt');
// or in a single line:
FileFromString(TAESCFB.SimpleEncrypt(StringFromFile('in.txt'),'privatekey',true,true),'out.txt');
// decryption
inp := StringFromFile('out.txt');
out := TAESCFB.SimpleEncrypt(inp,'privatekey',false,true);
FileFromString(out,'in.txt');
end;
以上代码安全且快速,将在提供的 'privatekey'
上使用 SHA-256 生成二进制密钥,如果您 CPU 支持,将使用 AES-NI 硬件指令。您可以使用另一种链接模式,只需将 TAESCFB
class 名称更改为另一种可用类型即可。