我有问题。我想在Delphi程序中加密文本并在java中解密它。我使用AES / CBC / NoPadding来做到这一点,但java程序不能很好地解密文本。 下一步是使用PKCS5Padding,所以有人可以回答这个问题,这将是非常棒的!
德尔福代码:
var
Cipher: TDCP_rijndael;
Key: string;
DataIn, DataOut: System.TArray<System.Byte>;
begin
Key := '0123456789012345';
DataIn := nil;
DataIn := TEncoding.UTF8.getbytes('SakisSakisSakisa');
DataOut := nil;
SetLength(DataOut, high(DataIn) + 1);
Cipher := TDCP_rijndael.create(nil);
Cipher.Algorithm := 'AES';
Cipher.Init(Key[1], 128, nil);
Cipher.EncryptCBC(DataIn[0], DataOut[0], high(DataIn) + 1);
Cipher.Free;
With TMemoryStream.create do begin
Write(DataOut[0], length(DataOut));
SaveToFile('c:\temp\encryption\sakisEnc.txt');
Free;
end;
DataIn具有以下字节: 83,97,107,105,115,83,97,107,105,115,83,97,107,105,115,97 此代码生成具有以下字节的加密字节数组DataOut: 3,207,105,252,118,38,28,145,89,77,107,8,181,205,190,165
现在是Java代码:
Path path = null;
String encryptionKey = null;
Cipher cipher = null;
SecretKeySpec key = null;
byte[] enc1;
path = FileSystems.getDefault().getPath("c:\\temp\\encryption\\SakisEnc.txt", "");
cipherText = Files.readAllBytes(path);
encryptionKey = "0123456789012345";
cipher = Cipher.getInstance("AES/CBC/NoPadding");
key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encryptionKey.getBytes()));
dec1 = cipher.doFinal(cipherText);
dec1字节数组应该具有与Delphi DataIn代码相同的字节 83,97,107,105,115,83,97,107,105,115,83,97,107,105,115,97 但它包含其他内容。
我真的无法理解我做错了什么..... Thanx提前!
答案 0 :(得分:1)
明显的区别在于你的钥匙。在您的Delphi代码中,您使用UTF-16编码密钥,但在Java代码中,您使用UTF-8编码密钥。
在Java代码中,库强制您将字节作为键传递。不幸的是,Delphi库更加宽松,让你陷入传递字符串的愚蠢行为。
我会将以下内容用于您的Delphi代码:
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {HttpClientModule, HttpClient} from '@angular/common/http';
import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {AppComponent} from './app';
// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http);
}
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
bootstrap: [AppComponent]
})
export class AppModule { }
然后将var
Key: TBytes;
....
Key := TEncoding.UTF8.GetBytes('0123456789012345');
传递给Key[0]
。
答案 1 :(得分:0)
在尝试之后,阅读,测试我做得好!
德尔福代码:
var
Cipher: TDCP_rijndael;
Key: System.TArray<System.Byte>;
DataIn, DataOut, iv: System.TArray<System.Byte>; // array of byte;
j: integer;
i :integer;
k :integer;
s: string;
sText :AnsiString;
sTextLen :integer;
paddingByte :string;
begin
Key := TEncoding.UTF8.getbytes('0123456789012345');
Iv := TEncoding.UTF8.getbytes('0123456789012345');
DataIn := TEncoding.UTF8.getBytes(memo1.Text);
//PKCS5Padding
sTextLen := high(DataIn) + 1;
i := 16 - (sTextLen mod 16);
if i <= 16 then begin
k := high(DataIn) + 1;
setLength(DataIn, sTextLen + i);
for j := k to high(DataIn) do begin
DataIn[j] := i;
end;
end;
//Encrypt.
DataOut := nil;
SetLength(DataOut, high(DataIn) + 1);
Cipher := TDCP_rijndael.create(nil);
Cipher.Algorithm := 'AES';
Cipher.Init(Key[0], length(Key) * 8, Iv);
Cipher.EncryptCBC(DataIn[0], DataOut[0], high(DataIn) + 1);
Cipher.Free;
//Save to file
With TMemoryStream.create do begin
Write(DataOut[0], length(DataOut));
SaveToFile('c:\temp\encryption\sakisEnc.txt');
Free;
end;
Java代码: 在java代码中,delphis的Iv与加密密钥相同。所以我将encryptionKey传递给:new IvParameterSpec(encryptionKey.getBytes(&#34; UTF-8&#34;))
String encryptionKey = null;
Cipher cipher = null;
SecretKeySpec key = null;
byte[] enc1;
byte[] dec1;
path = FileSystems.getDefault().getPath("c:\\temp\\encryption\\SakisEnc.txt", "");
cipherText = Files.readAllBytes(path);
encryptionKey = "0123456789012345";
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") ;
key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encryptionKey.getBytes("UTF-8")));
dec1 = cipher.doFinal(cipherText);