Delphi XE8 と LockBox 3 を暗号化に使用して RESTful サーバーを構築しています。AES を使用してデータ (JSON) を暗号化し、それを Android デバイス (クライアント) に送信します。
暗号化されたデータをクライアントに送信し、クライアントが暗号化キーを知っている場合、LB3 によって内部的に自動管理されているため、IV を知らずにデータを復号化するにはどうすればよいでしょうか?
Delphi XE8を使用しています
最初: LockBox の最新バージョンをインストールしました。
2 番目: IV の設定方法に関するドキュメントはありません。
IV (暗号文からの最初の 8 バイト) を取得することができました。
function TAESEnrypt.EncryptAES_String(const str: string): string;
var
Codec1: TCodec;
CryptographicLibrary1: TCryptographicLibrary;
bt:TByteArray;
m:TMemoryStream;
AEncoding: TEncoding;
pCipher: TBytes;
bytes: TBytes;
text: string;
Encoding: TEncoding;
iv:TBytes;
cipher:TBytes;
i:integer;
begin
Result:='';
KeyHex:='';
KeyBin:=TMemoryStream.Create;
Codec1 := TCodec.Create( nil);
CryptographicLibrary1 := TCryptographicLibrary.Create( nil);
Codec1.CryptoLibrary := CryptographicLibrary1;
Codec1.StreamCipherId := BlockCipher_ProgId;
Codec1.BlockCipherId := 'native.AES-128';
Codec1.ChainModeId := CBC_ProgId;
Codec1.Password := Password;
Codec1.EncryptString(str, CipherText, TEncoding.UTF8);
Result:=CipherText;
Codec1.Key.SaveToStream(KeyBin);
Codec1.Free;
CryptographicLibrary1.Free;
//key ==> HEX
KeyBin.Position:=0;
SetLength(KeyHex,KeyBin.Size*2);
SetLength(bt, KeyBin.Size);
KeyBin.Read(bt[0],KeyBin.Size);
KeyBin.Position:=0;
BinToHex(bt[0],pchar(KeyHex),KeyBin.Size);
//key ==> base64
Key64:=TNetEncoding.Base64.EncodeBytesToString(bt);
//
{
Ciphertext = Base64
IV ==> Extract the first 8 bytes (64 bits)
1. Base64 ==> Binary
2. get IV
3. Binary ==> Base64 (Ciphertext)
4. Binary ==> Base64 (IV)
5. Binary ==> HEX (Ciphertext)
6. Binary ==> HEX (IV)
}
bytes := TNetEncoding.Base64.DecodeStringToBytes(CipherText);//result => binary data
iv:=Copy(bytes,0,8);//get first 8 bytes (iv) => binary data
cipher:=Copy(bytes,8,Length(bytes)-8);//the rest is the encrypted data => binary data
//Bin => base64
iv64:=TNetEncoding.Base64.EncodeBytesToString(iv);
cipher64:=TNetEncoding.Base64.EncodeBytesToString(cipher);
//Bin => HEX
SetLength(ivHex,Length(iv)*2);
BinToHex(iv[0],pchar(ivHex),Length(iv));
SetLength(CipherHex,Length(cipher));
BinToHex(Cipher[0],pchar(CipherHex),Length(Cipher));
end;
例 (128):
iv_64 : P7NJIfhws2k=
iv_hex: 3FB34921F870B369
cipher_64 : 5UvFMw==
cipher_hex: E54B
Key_64 : /dn9yyUOTWobOQx1A+ZfAg==
Key_hex: FDD9FDCB250E4D6A1B390C7503E65F02
クライアント側 (Android) では、「Bad base 64」または「復号化で最後のブロックが不完全です」というエラーが表示されます。これが私のコードです (テスト専用です)。
[IVをゼロで完成させます]
byte[] out=new byte[16];
byte[] zero="00000000".getBytes();
byte[] ivBytes; byte[] keyBytes; byte[] textBytes;
ivBytes=Base64.decode("9pdfnd4JvpI=".getBytes("UTF-8"),Base64.DEFAULT);
System.arraycopy(ivBytes,0,out,0,ivBytes.length);
System.arraycopy(zero,0,out,ivBytes.length,zero.length);
keyBytes=Base64.decode("/dn9yyUOTWobOQx1A+ZfAg==".getBytes("UTF-8"),Base64.DEFAULT);
textBytes=Base64.decode("+JnDcw==".getBytes("UTF-8"),Base64.DEFAULT);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(out);
SecretKeySpec newKey = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING");
cipher.init(Cipher.DECRYPT_MODE, newKey,ivSpec);
byte[] decodedBytes = cipher.doFinal(textBytes);
String plain=new String(decodedBytes,"UTF-8");
これを Android で実行すると、「復号化が不完全な最後のブロック」が表示され、getBytes() から「UTF-8」を削除すると、「悪い base-64」が表示され、解決方法がわかりません。何か案が?