0

I'm trying to rewrite this old code from C# to delphi 10.3 (using library lockbox 3.7). The output crypto are used for PHP script handling the DB running on the remote server, that PHP I cannot edit.

internal static string DecryptString_forPHP(string cipherText, byte[] key, byte[] iv)
        {
            string plainText = "";
            try
            {
                Aes encryptor = Aes.Create();
                encryptor.Mode = CipherMode.CBC;
                byte[] aesKey = new byte[32];
                Array.Copy(key, 0, aesKey, 0, 32);
                encryptor.Key = aesKey;
                encryptor.IV = iv;

                MemoryStream memoryStream = new MemoryStream();
                ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);
                try
                {
                    byte[] cipherBytes = Convert.FromBase64String(cipherText);
                    cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);
                    cryptoStream.FlushFinalBlock();
                    byte[] plainBytes = memoryStream.ToArray();
                    plainText = Encoding.UTF8.GetString(plainBytes, 0, plainBytes.Length);
                }
                finally
                {
                    memoryStream.Close();
                    cryptoStream.Close();
                }
            }
            catch (Exception e)
            {
                ErrorLog(1, System.Environment.NewLine + e.Message);
            }
            return plainText;
        }


internal static string EncryptString_forPHP(string plainText, byte[] key, byte[] iv)
        {
            string cipherText = "";
            try
            {
                Aes encryptor = Aes.Create();
                encryptor.Mode = CipherMode.CBC;
                byte[] aesKey = new byte[32];
                Array.Copy(key, 0, aesKey, 0, 32);
                encryptor.Key = aesKey;
                encryptor.IV = iv;
                MemoryStream memoryStream = new MemoryStream();
                ICryptoTransform aesEncryptor = encryptor.CreateEncryptor();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);
                byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
                cryptoStream.Write(plainBytes, 0, plainBytes.Length);
                cryptoStream.FlushFinalBlock();
                byte[] cipherBytes = memoryStream.ToArray();
                memoryStream.Close();
                cryptoStream.Close();
                cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);
            }
            catch (Exception e)
            {
               ErrorLog(1, System.Environment.NewLine + e.Message);
            }
            return cipherText;
        }

Called for example with:

string password = "xxxxxxxxxxxxxxxxx";
                    // Create sha256 hash
                    SHA256 mySHA256 = SHA256Managed.Create();
                    byte[] key = mySHA256.ComputeHash(Encoding.UTF8.GetBytes(password));
                    // Create secret IV
                    byte[] iv = new byte[16] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
                    string encrypted = EncryptString_forPHP(message, key, iv);
                    string decrypted = DecryptString_forPHP(message, key, iv);

I read and tried these, but always ended with different output then I expected or with some new error. How to use AES-256 encryption in lockbox 3 using delphi Turbopower Lockbox3 - Can I control initialization vector and padding for AES-256 encryption? LockBox 3 Encrypting not matching online tool, suspect padding or key problem Turbopower Lockbox3 - Can I control initialization vector and padding for AES-256 encryption?

This seems code for decrypt seems to me as most possible copy of the original C#, but the output is not equal. Is there problem with the used library (lockbox 3.7), version of delphi (10.3) or did I something simply overlook?

function DecryptAES256FromBase64String(const Value: String): String;
var
  Codec: TCodec;
  CryptographicLibrary: TCryptographicLibrary;
  CipherStream, PlainTextStream: TStream;
  buffer: array of Byte;
  mySHA256 : THashSHA2;
  key : TBytes;
begin
  Codec := TCodec.Create( nil);
  CryptographicLibrary := TCryptographicLibrary.Create(Codec);
  CipherStream := TMemoryStream.Create;
  PlainTextStream := TMemoryStream.Create;

  try
    Codec.CryptoLibrary := CryptographicLibrary;
    Codec.StreamCipherId := BlockCipher_ProgID;
    Codec.BlockCipherId := Format(AES_ProgId,[256]);
    Codec.AsymetricKeySizeInBits := 256;
    Codec.Cipher  := '[AES-256*]';
    Codec.ChainModeId := CBC_ProgId;

    mySHA256 := THashSHA2.Create();
    key := mySHA256.GetHashBytes(password, SHA256);

    CipherStream.WriteBuffer(key[0], Length(key));
    CipherStream.Position := 0;
    Codec.InitFromStream(CipherStream);
    CipherStream.Size := 0;
    CipherStream.WriteBuffer(IV[0], Length(IV));

    Base64_to_stream(TNetEncoding.Base64.DecodeStringToBytes(Value), CipherStream);
    CipherStream.Position := 0;
    Codec.DecryptStream(PlainTextStream, CipherStream);
    PlainTextStream.Position := 0;
    SetLength(buffer, PlainTextStream.Size);
    PlainTextStream.ReadBuffer(buffer[0], Length(buffer));
    Result := TNetEncoding.Base64.EncodeBytesToString(buffer);

  finally
    CipherStream.Free;
    PlainTextStream.Free;
    Codec.Free;
    CryptographicLibrary.Free;
  end;
end;
  • Hints: AES is not asymmetric and TCodec has a key property. The IV / nonce is written or retrieved from the stream automagically. *Upgrading* from C# to Delphi, oh well. – Maarten Bodewes Mar 10 '23 at 05:08
  • I might be a little late to the party, so maybe this comment won't be read. I have a few questions: (1) Is the encryptor under your control?; (2) Do you have control over the encryptor selection of IV?; (3) Is the encryptor LB3?; (4) Is the decryptor under your control?; (5) It appears that you are trying to write the decryptor in Delphi with LB3 but dont have control of the encryptor - please confirm; (6) Where did you source LB3? More questions to follow. – Sean B. Durkin Mar 19 '23 at 09:14
  • Please supply full test data. These include (1) Full ciphertext including IV as base64 string; (2) Is the IV tranported via a separate channel? or LockBox style as a ciphertext prepend? (3) The plaintext string; (4) The encoding of the plaintext (UTF-8 or UTF-16LE)? This last one may seem unimportant, but it is very important. Natively PHP is UTF-8. Natively Delphi is UTF-16LE.; (5) What is the key as a base64 string. (6) If the encryptor is not LB3, what padding scheme and block termination scheme does the encryptor use? (7) What library and language was used to encrypt? – Sean B. Durkin Mar 19 '23 at 09:20

0 Answers0