1

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」が表示され、解決方法がわかりません。何か案が?

4

0 に答える 0