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?

S.L. Barth
  • 8,058
  • 71
  • 49
  • 63
user2005049
  • 500
  • 5
  • 24
  • 2
    As I understand from [AES Encrypt/Decrypt Delphi & PHP](http://stackoverflow.com/a/12138580/576719), the IV is prepended in the message from the server. – LU RD Nov 13 '16 at 19:48
  • Interesting.... – user2005049 Nov 13 '16 at 19:49
  • LU RD is correct. Just to add a little more detail: The low 8 bytes of the IV is the first 8 bytes of the output. If your block size is greater than 8 bytes, the high bytes of the IV are zero. – Sean B. Durkin Nov 13 '16 at 23:12
  • P.S. I'm working on the next version of Lockbox, where you will be able to explicitly specify your own IV. – Sean B. Durkin Nov 13 '16 at 23:13
  • It's almost ready. I am just upgrading the suite of unit tests to a new unit testing framework - dunit-m. – Sean B. Durkin Nov 16 '16 at 12:26
  • ... And it's done. Locate version 3.7.0 at https://github.com/SeanBDurkin/tplockbox – Sean B. Durkin Nov 17 '16 at 12:46
  • I've edited your answer into the question. You can use the [edit] link below your post for updates. Your question now shows effort, so I'm giving you an upvote. Hope you'll be able to figure it out. – S.L. Barth Nov 30 '16 at 07:43

0 Answers0