1

I'm building a RESTful server using Delphi XE8 with LockBox 3 for encryption. I use AES to encrypt data (JSON) and send it to an Adroid device - Client.

If I send the encrypted data to client and the client knows the encryption key, how could he decrypt the data without knowing the IV because it auto managed by LB3 internally?

I'm using Delphi XE8

First: I installed LockBox last version.

Second: there is no documentation on how to set the IV.

I managed to get the IV (first 8 bytes from ciphertext):

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;

For example (128):

iv_64 : P7NJIfhws2k=
iv_hex: 3FB34921F870B369
cipher_64 : 5UvFMw==
cipher_hex: E54B
Key_64 : /dn9yyUOTWobOQx1A+ZfAg==
Key_hex: FDD9FDCB250E4D6A1B390C7503E65F02

On the client side (Android) I get the error "Bad base 64" or "last block incomplete in decryption" and here is my code (it's only for testing):

[I complete the IV with zeros]

            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");

When I run this in Android I get: "last block incomplete in decryption" and when I remove the "UTF-8" from getBytes() I get "bad base-64", and I don't know how to solve it, any idea?

user2005049
  • 510
  • 1
  • 5
  • 26

0 Answers0