Jump to content

dormky

Members
  • Content Count

    111
  • Joined

  • Last visited

Everything posted by dormky

  1. Consider : program ProjectThreadProc; {$APPTYPE CONSOLE} {$R *.res} uses System.Classes, Winapi.Windows; type TMyRecord = class data: Integer; class procedure Queue(const AThread: TThread; AMethod: TThreadMethod); end; class procedure TMyRecord.Queue(const AThread: TThread; AMethod: TThreadMethod); begin OutputDebugString(PChar('In TMyRecord.Queue')) end; begin TThread.Queue(nil, procedure begin OutputDebugString(PChar('Hello !')) end); TMyRecord.Queue(nil, procedure begin OutputDebugString(PChar('Hello !')) end); end. This will give you, under 10.3 : [dcc32 Error] ProjectThreadProc.dpr(25): E2010 Incompatible types: 'TThreadMethod' and 'Procedure' Notice that the line for TThread has no problems, and this compiles if you comment the call to TMyRecord.Queue. Problem is, on the face of it those two functions have the exact same signature : So why does TMyRecord.Queue not compile ? I'm baffled. The end goal here is to pass an anonymous function to a thread, to be executed there.
  2. Here I was sitting and wondering how the hell it was compiling TThread when it should be TThreadProcedure for it too... Before noticing the overload beneath the function Delphi navigated to. God bless Delphi's function navigation, somehow worse at it than Christopher Colomb. Good job noticing this !
  3. query := TMyQuery.Create(nil); query.Connection := conn; query.SQL.Text := 'SELECT * FROM data'; query.Execute(); Every time I do something like this, a new connection to the MySQL server is established. How can I make it use the already-opened 'conn' connection ? Thanks 🙂
  4. const TT = $FFFF; TTARRAY = [$FFFF]; The second line gets "E1012 Constant expression violates subrange bounds", but it's functionally the same as the first one. Is the compiler just dumb or do I need to write this in another syntax ? The actual use case is an array of const TColor. Thanks 🙂
  5. Alright, got it. Still cannot work with TColor but it's better then nothing, example : // The highlight colors here are defined twice so the compiler doesn't complain. YELLOW: TColor = $00BBFF; BLUE: TColor = $F0CF89; HIGHLIGHT_COLORS: array[0..1] of TColor = ($00BBFF, $F0CF89); Thanks !
  6. I'm using MyDAC components and some of the data is encrypted via use of a TMyEncryptor with a password, see https://docs.devart.com/mydac/devart.dac.tcrencryptor.password.htm But they don't say what the algorithm used to generate the password is. Does anyone here know that ?
  7. Okay, so according to my understanding CBC xors the plain data with the previous block (encrypted) before applying encryption. And here instead, the plain data is encrypted directly and then xor'd with the last block. In this case, if I were to truncate my data to 8-bytes blocks, then encrypt the bytes that were removed by themselves with an IV of all 0 I could then xor the result with the last block myself, thus landing on the same result as MyDAC ? Since the last few bytes would be xor'd with the zeroed IV they wouldn't be changed before encryption, just like MyDAC is doing here.
  8. Ah. Well isn't that great. This is why I hate proprietary code ; now this project is effectively locked in with MyDAC and has no way of ever getting out of it short of a manual migration of data on demand. Good job from Devart, they win... Although I will still endeavor to do everything I can to move the company away from them. It's personal now 😛 Thank you for your help.
  9. Well, I though I had gotten it to work by using CTR, but I only get the same output up to 8 characters. You say that they are using CBC, but I can't get that to work using either LockBox3 or C#'s BouncyCastle. I have had contact with the MyDAC support and they refuse to cooperate (they did not mention any specifics of how they are handling encryption and keep referring me to the incomplete documentation). Do you know if any implementation of Blowfish that do not require to be padded to 8 bytes ? Even BouncyCastle, which to my understanding is C#'s main open-sourced cryptography library does not provide such a thing : using System; using System.Text; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using System.Security.Cryptography; namespace blowfish_test { internal class Program { const string PASSWORD = "pass"; const string DATA = "ABCDEFGHI"; static void Main(string[] args) { byte[] sha1Hash = SHA1.Create().ComputeHash(Encoding.Unicode.GetBytes(PASSWORD)); byte[] md5Hash = MD5.Create().ComputeHash(Encoding.Unicode.GetBytes(PASSWORD)); byte[] key = new byte[20 + 12]; Array.Copy(sha1Hash, 0, key, 0, 20); Array.Copy(md5Hash, 0, key, 20, 12); var cipher = CipherUtilities.GetCipher("Blowfish/CBC/NoPadding"); //cipher.Init(true, new ParametersWithIV(new KeyParameter(key), new byte[8])); cipher.Init(true, new KeyParameter(key)); byte[] encryptedData = cipher.DoFinal(Encoding.UTF8.GetBytes(DATA)); // Display the result Console.WriteLine("Encrypted Data: " + BitConverter.ToString(encryptedData).Replace("-", "")); Console.ReadLine(); } } } This fails, but if you remove the 'I' to have 8 characters you do get the same output as MyDAC. Same output when using 8 characters, but completely different when there's 9. So I guess the encryption part is correct, but the transition between blocks is implemented differently, and while I can check on what BouncyCastle is doing I can't do the same for MyDAC 😕
  10. I'm definitely using it wrong, but them having no docs and considering base64 to be an encryption algorithm doesn't help lol Edit : encrypting 'ABCDEFGH' lands on the same result with both MyDAC and LockBox3, with the caveat that LockBox3 has another 8 bytes of data. This is probably due to padding, but at least I'm sure the actually encryption is correct, yey ! Just need to figure out the padding. I had to set cfNoNounce in TCBC in order to get an empty IV because I haven't found a way of setting it myself otherwise.
  11. Yeah I know doing encryption like this is BAD (we've had multiple cases of the program not releasing a string is encrypted and using it as-is...), I'm not the one who made this... I'm the one stuck dealing with it 🙂 Jesus Christ, the bug with SetKey !! No wonder the output changes all the time... For future reference, my updated testing code with the corrections needed for it to output the same thing with Password and SetKey : var conn: TMyConnection; table1, table2: TMyTable; keyBytes, PassBytes, sha1, md5: TBytes; query: TMyQuery; begin PassBytes := BytesOf(@WideString('pass')[1], Length('pass') * SizeOf(WideChar)); SetLength(keyBytes, 36); sha1 := THashSHA1.GetHashBytes(TBytesStream.Create(PassBytes)); // Memory leak lol md5 := THashMD5.GetHashBytes(TBytesStream.Create(PassBytes)); Move(sha1[0], keyBytes[0], 20); Move(md5[0], keyBytes[20], 16); // --- // table2.Encryption.Encryptor.SetKey(keyBytes, 0, 32); // 0 to get the correct function Many thanks Kas !! I've been trying to use LockBox3 to create the same result, unfortunately I can't quite get it. 'A' is the same value no matter the encoding but I get 41 as output instead of E2. I need to check deeper into the (undocumented) code of LockBox3 to see what I'm doing wrong (hopefully it isn't MyDAC doing something wrong...) Codec := TSimpleCodec.Create(); Codec.StreamCipher := TBase64Converter.Create(); Codec.BlockCipher := TBlowFish.Create(); Codec.ChainMode := TCBC.Create(); SetLength(LBKeyBytes, 34); Move(keyBytes[0], LBKeyBytes[1], 32); LBKeyBytes[0] := 32; // Length of the key LBKeyBytes[33] := 0; // Does the key contain the sotres Codec.InitFromStream(TBytesStream.Create(LBKeyBytes)); Codec.EncryptString('A', outputText, TEncoding.UTF8); // outputText in base64, translated to hex => 41 Edit : Dear god, 41 = 'A' to begin with... This is not encrypting anything !!
  12. There is nothing added to the encrypted data. No IV, no hash, no guid, and I know this because like I said, the output is extremely small and physically cannot contain enough data. Just the letter A gives me one or 2 bytes as a result. Here is some code to reproduce : program Project; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, System.Hash, Data.DB, CREncryption, MyAccess; var conn: TMyConnection; table1, table2: TMyTable; keyBytes, sha1, md5: TBytes; query: TMyQuery; begin SetLength(keyBytes, 36); sha1 := THashSHA1.GetHashBytes('pass'); md5 := THashMD5.GetHashBytes('pass'); Move(sha1[0], keyBytes[0], 20); Move(md5[0], keyBytes[20], 16); conn := TMyConnection.Create(nil); conn.Port := 3306; conn.Username := 'root'; conn.Password := 'toor'; conn.Server := 'localhost'; conn.Connected := True; conn.ExecSQL('DROP DATABASE IF EXISTS encryptor_test;'); conn.ExecSQL('CREATE DATABASE encryptor_test;'); conn.ExecSQL('USE encryptor_test;'); conn.ExecSQL('CREATE TABLE test_data (`Name` varchar(255));'); table1 := TMyTable.Create(nil); table1.Connection := conn; table1.TableName := 'test_data'; table1.FieldDefs.Add('Name', ftString, 250); table1.Encryption.Encryptor := TMyEncryptor.Create(nil); table1.Encryption.Encryptor.DataHeader := ehNone; table1.Encryption.Encryptor.Password := 'pass'; table1.Encryption.Fields := 'Name'; table1.Active := True; table1.Insert(); table1.FieldByName('Name').Value := 'A'; table1.Post(); table2 := TMyTable.Create(nil); table2.Connection := conn; table2.TableName := 'test_data'; table2.FieldDefs.Add('Name', ftString, 250); table2.Encryption.Encryptor := TMyEncryptor.Create(nil); table2.Encryption.Encryptor.DataHeader := ehNone; table2.Encryption.Encryptor.SetKey(keyBytes, 36); table2.Encryption.Fields := 'Name'; table2.Active := True; table2.Insert(); table2.FieldByName('Name').Value := 'A'; table2.Post(); end. Strangely enough when using password the output does not change : E2. When using SetKey, the result varies so I suppose the IV is directly derived from the password. I'm getting a single byte here as output instead of 2 in the full project though, which is strange. Edit : Signing of for the day, have a nice weekend !
  13. The IV and other metadata cannot be contained in the data. I just tried with just the letter 'A' and the output is always the same 2 bytes. Therefore, the IV is a hardcoded value somewhere. Could you share this ?
  14. I don't get what you mean by "magic number", and your way of writing makes it very hard to understand what you mean 😕 If you can't provide the algorithm used that's fine I understand. I really don't get how you can encrypt with blowfish without padding, since blowfish uses 8-bytes blocks. Is the padding simply ignored with the length is known ? When I try to pass data that is not a multiple of 8 bytes, python's cryptography package raises an error. Also my encrypted test data is only 8 bytes (4 characters), I'm not using tag and hash. And all this is irrelevant as long as I don't have the algorithm that derives the key from the password, it's the only thing I need.
  15. > hence removing the need for padding That cannot be correct, Blowfish (the default algorithm which I am using here) requires padding ? The security of the encryption is not my problem here, the problem is that I cannot read the data using anything other then a Devart product. The data is already encrypted so nothing about the algorithm can be changed, I need to use the exact same process. I've tried to recreate the same process in python with PKCS7 padding but I don't get the same result.
  16. Doing a file-based comparison will always lead you into problems where something changes, but it's not something that actually impact the configuration in real-life. Better to write code to handle the comparison. If you really don't want to do that, you need empty spaces ie reserve 30 lines for drives and when saving, always sort alphabetically. Each field would have a specific length so no offset changes. But it's going to be a pain. Maybe separate the data you actually want to compare ; even in a single file you can have a marker like a line of '|' after which the data resides and you have a very small script to compare that part of the file and not the rest.
  17. Just occurred to me that I won't know how they're padding the content... So yeah.
  18. Okay I'm not sure I understand what you're saying but 1) You have the source-providing license 2) In the source you can see the Password2Key function concats the the SHA1 and MD5 of the password to generate the key ? I suppose it's still like this because TMyEncryptor just inherits from TCREncryptor and doesn't actually add anything from what I can see. Probably they wanted it named with a "My". I'll try a python script to reproduce the encryption and see if SHA1+MD5 lands me on the same results. Thanks.
  19. Done using https://www.onlinegdb.com/online_pascal_compiler, but Delphi 10.3 does the same. What the fork ?
  20. The documentation is utterly unhelpful, I've done the 3 steps outlined here : https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Creating_a_New_Component After those three steps, it says "Now you will have a minimally functional component ready to install on the Tool Palette. After installing [...]". But there is no step explaining how to install !
  21. dormky

    How do I register a component into the tool palette ?

    I feel like my time and the stability of the application will be much better served if I simply makes a class that takes my base component as a parameter. It's to draw on a bitmap anyway so not much going on at design time. Thanks anyway, at least I know not to refer to the docs on this subject 🙂
  22. dormky

    What is the best AI at Delphi

    Claude has multiple advantages for me : - You can give it a large amount of info (I've been pasting entire units into it) - Moderately better at Delphi (ie not making too much stuff up) - Won't give you entire paragraphs explaining why 1+1=2, it's way more concise and won't re-explain everything with every answer, mostly just show the code change. Not sure if this is a measure to not consume as much but it's great for since I always have to bang ChatGPT's head about giving only-code answers.
  23. When my DBGrid's datasource points to a TMyTable, its fixed rows are drawn like this : But when changing to a TClientDataSet, they are drawn like this : What can I do to prevent this change ? Is this a style problem ? Is it a difference in settings between the TClientDataSet and the TMyTable ? I haven't found one that could provoke this but it's the best idea I've got as to why this behavior occurs.
  24. (These are TBitBtns) In the first image, all buttons are enabled. In the second, the bottom two are disabled. It seems that the disabling makes every color except for pure black completely disappear (see the grey at the top of the pencil disappeared too). What can I do to prevent this ? The icon should just be greyed out, not entirely disappear. I don't want to make greyed out glyphs and switch them around for literally every button in the program either. Although if it comes down to it, I guess I could always have a custom button that takes the existing glyph and greys it ? But that sounds finicky and there's probably a better way of solving this. Thanks !
  25. dormky

    Enabled := False makes color Glyphs disappear

    A search for TBitBtn just gave me 1842 results, and that's just the "main" part of the program. Now not all of these buttons have icons of course, but a significant portion does. We're talking at least hundreds of buttons to update and check here. So no it's not every icon, but it's still a whole freaking lot.
×