Lazarus

Programming => General => Topic started by: Conte on September 26, 2021, 06:28:19 pm

Title: The most easy encrypting/decrypting password method?
Post by: Conte on September 26, 2021, 06:28:19 pm
I searched anywhere and I found about BlowFish but I'm finding difficulties to use it.
I have a form with multiple buttons. Each button let me to login to a different server. The form ask me for username and password.
I would like to store the credentials in the registry of windows but I want to store the password encrypted in sha256.
So the next time I'll click on the button I don't need to write credentials again.

Can someone give me examples? I am newbie.
Title: Re: The most easy encrypting/decrypting password method?
Post by: ASerge on September 26, 2021, 06:31:22 pm
I want to store the password encrypted in sha256.
sha256 is designed for hashing, not encryption.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 26, 2021, 06:42:29 pm
Well I was meaning hashing then. :)
Title: Re: The most easy encrypting/decrypting password method?
Post by: ASerge on September 26, 2021, 06:45:25 pm
Well I was meaning hashing then. :)
But then it is not clear what you want to store in the registry. If only a hash, then this is not enough for registration (login/password).
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 26, 2021, 06:51:54 pm
My form will contain various button, each button is configured to let me login to a location.
Only the first time the button will ask me user and password because it will be store in the registry. For the password it will only be stored hash, the username will be clear.
Next time I'll click the button it will read the hash from the registry and should let me login directly.

I have found this code that use DCPCrypt.
This is my code how I encrypt string:
Code: Pascal  [Select][+][-]
  1. uses DCPrijndael, DCPsha256;
  2.  
  3. var
  4.   S1, S2: String;
  5.   c: TDCP_rijndael;
  6. begin
  7.   c := TDCP_rijndael.Create(nil);
  8.   try
  9.     c.InitStr('MyCustomKey', TDCP_sha256);
  10.     S1 := c.EncryptString('First string');
  11.     c.Reset;
  12.     S2 := c.EncryptString('Second string');
  13.   finally
  14.     c.Free;
  15.   end;
  16. end;  
  17.  
And decrypt:
Code: Pascal  [Select][+][-]
  1. uses DCPrijndael, DCPsha256;
  2.  
  3. var
  4.   S1, S2: String;
  5.   c: TDCP_rijndael;
  6. begin
  7.   c := TDCP_rijndael.Create(nil);
  8.   try
  9.     c.InitStr('MyCustomKey', TDCP_sha256);
  10.     S1 := c.DecryptString(SomeEncryptedVariable);
  11.     c.Reset;
  12.     S2 := c.DecryptString(SomeEncryptedVariable);
  13.   finally
  14.     c.Free;
  15.   end;
  16. end;  
  17.  
One thing I noticed. If you want to encrypt / decrypt next string using the same object, you must first reset this object by "Reset" call. Otherwise, next string will be incorrectly encrypted / decrypted

Compiling it I get error on this line:
var
  S1, S2: String;


Error is:
Compila il progetto, Destinazione: project1.exe: Codice di uscita 1, Errori: 2
unit1.pas(34,3) Error: Illegal expression
unit1.pas(35,3) Fatal: Syntax error, ";" expected but "identifier S1" found
Title: Re: The most easy encrypting/decrypting password method?
Post by: Thaddy on September 26, 2021, 08:27:40 pm
Must be in some previous answer but just in case:
A SECURE HASH CAN NOT BE DECRYPTED
Period.

For a very simple two way encrypt/decrypt start with XOR.
Otherwise, when using a hash, store the hash, not the password, and re-hash it based on user input. If the two hashes are equal, the password is OK. That also means that - when implemented correctly - the password itself is never stored or visible.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 27, 2021, 07:15:31 pm

For a very simple two way encrypt/decrypt start with XOR.
Otherwise, when using a hash, store the hash, not the password, and re-hash it based on user input. If the two hashes are equal, the password is OK. That also means that - when implemented correctly - the password itself is never stored or visible.
That's just what I'm looking for. So how do I should start to learn it?

Basically I should be able to read/write to a registry key field. Generate a md5 of a string and compare it with the string stored on the registry. If is is equal the login succeed.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 27, 2021, 08:36:33 pm
I have solved my issue, here the source code:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, DCPsha256, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     DCP_sha256_1: TDCP_sha256;
  17.     Edit1: TEdit;
  18.     Edit2: TEdit;
  19.     Label1: TLabel;
  20.     procedure Button1Click(Sender: TObject);
  21.   private
  22.     { private declarations }
  23.   public
  24.  
  25.     { public declarations }
  26.   end;
  27.  
  28. var
  29.   Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. function getsha256(S: String): String;
  38. var
  39.     Hash: TDCP_sha256;
  40.     Digest: array[0..31] of byte;  // sha256 produces a 256bit digest (32bytes)
  41.     Source: string;
  42.     i: integer;
  43.     str1: string;
  44.   begin
  45.     Source:= S;  // here your string for get sha256
  46.  
  47.     if Source <> '' then
  48.     begin
  49.       Hash:= TDCP_sha256.Create(nil);  // create the hash
  50.       Hash.Init;                        // initialize it
  51.       Hash.UpdateStr(Source);
  52.       Hash.Final(Digest);               // produce the digest
  53.       str1:= '';
  54.       for i:= 0 to 31 do
  55.         str1:= str1 + IntToHex(Digest[i],2);
  56.       //form1.Edit2.Text:= s;                   // display the digest in lower case
  57.       Form1.Edit2.Text:=UpperCase(str1);         // display the digest in capital letter
  58.     end;
  59.   end;
  60.  
  61. procedure TForm1.Button1Click(Sender: TObject);
  62.   begin
  63.     getsha256(Edit1.Text);  // show the sha256 of string in edit1
  64. end;
  65. end.
  66.  

A big big thanks to Ericktux (https://forum.lazarus.freepascal.org/index.php?action=profile;u=56748).

The only doubts I have is that I get two hints by the compiler:
1. Warning: Local variable "Digest" does not seems to be initialized;
2. Warning: Function result does not seem to be set
Title: Re: The most easy encrypting/decrypting password method?
Post by: Thaddy on September 28, 2021, 07:06:05 am
After Hash.Final(digest) you forgot to call Hash.Free?
Note I do not use DCPxxx, but I prefer our own user Xor-El's Hash library.
https://github.com/Xor-el/HashLib4Pascal
Title: Re: The most easy encrypting/decrypting password method?
Post by: MarkMLl on September 28, 2021, 11:49:18 am
Must be in some previous answer but just in case:
A SECURE HASH CAN NOT BE DECRYPTED
Period.

That is very true, but reading things through he's not trying to recover his plaintext password/passphrase from a stored hash. What he's actually doing is taking the plaintext passphrase, storing a hash of that, and using that hash as the /actual/ passphrase... which is not bad practice subject to a couple of comments.

The first comment is that the idea of storing a hashed passphrase is so that if some lackwit uses the same passphrase for both his Squitter login and his bank account, it's not possible to trivially break into his bank account when Squitter is hacked. However this is weakened if it happens that everybody is using the same hash algorithm, since something like John The Ripper will be able to get a fairly quick match. The solution to that is to "seed" the hash with two numbers, the first being random (but applying to all passphrases stored in the same place) and the second being a hash of the name of the service being logged into.

The second is that local strings cannot be assumed to be cleared adequately when they're deallocated or their length is changed. So if a string has contained the plaintext of a password, overwrite it with something of the same length before it goes out of scope.

Apologies if anybody feels I'm stating the obvious here.

MarkMLl
Title: Re: The most easy encrypting/decrypting password method?
Post by: Thaddy on September 28, 2021, 12:24:59 pm
That is how interpreted it. But looking at the original question that was not very clear:encrypt/decrypt....
Title: Re: The most easy encrypting/decrypting password method?
Post by: MarkMLl on September 28, 2021, 12:56:31 pm
That is how interpreted it. But looking at the original question that was not very clear:encrypt/decrypt....

I know, which is why I thought going into some detail for OP's benefit might be useful :-)

MarkMLl
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 28, 2021, 08:13:42 pm
Guys I can't apply that way, because I'd like to make an auto login. That way was good if everytime I had wrote my password, is it can be compared with the stored one after the encryption. With the auto login I should set a private key used for the encryption so I'm learning this way now: https://forum.lazarus.freepascal.org/index.php?topic=10970.msg55542#msg55542
Title: Re: The most easy encrypting/decrypting password method?
Post by: MarkMLl on September 28, 2021, 08:22:22 pm
Guys I can't apply that way, because I'd like to make an auto login. That way was good if everytime I had wrote my password, is it can be compared with the stored one after the encryption. With the auto login I should set a private key used for the encryption so I'm learning this way now: https://forum.lazarus.freepascal.org/index.php?topic=10970.msg55542#msg55542

Can't reply /what/ way? Give us come context (there's a button for that).

MarkMLl
Title: Re: The most easy encrypting/decrypting password method?
Post by: Thaddy on September 28, 2021, 09:22:13 pm
Guys I can't apply that way, because I'd like to make an auto login.
That can be achieved by issuing certificates from your own authority to your users.
Not ieasy but doable even for noobs, Well, you need to know a few things.....
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 28, 2021, 09:27:37 pm
I have in mind this.
First time that the form is opened there's a button to click that will ask for username ans password and will store it.
Next time I'll open the Form and click the button it automatically login (the exe is intended for a user only so there's no need to ask user and psw again).
The exe should contain the key to decrypt the string stored.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Thaddy on September 28, 2021, 09:39:11 pm
I have in mind this.
First time that the form is opened there's a button to click that will ask for username ans password and will store it.
Hopefully not.
Quote
Next time I'll open the Form and click the button it automatically login (the exe is intended for a user only so there's no need to ask user and psw again).
The exe should contain the key to decrypt the string stored.
Never do that. Do not store anything except the hash.
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on September 28, 2021, 09:49:43 pm
I have in mind this.
First time that the form is opened there's a button to click that will ask for username ans password and will store it.
Next time I'll open the Form and click the button it automatically login (the exe is intended for a user only so there's no need to ask user and psw again).
The exe should contain the key to decrypt the string stored.
Your method is not safe. It can be easily cracked by an advanced user. However if the goal is to store the credentials in a relatively safe form(not plain text), so a regular user cannot see it then is doable.
Title: Re: The most easy encrypting/decrypting password method?
Post by: MarkMLl on September 28, 2021, 09:51:42 pm
I have in mind this.
First time that the form is opened there's a button to click that will ask for username ans password and will store it.
Next time I'll open the Form and click the button it automatically login (the exe is intended for a user only so there's no need to ask user and psw again).
The exe should contain the key to decrypt the string stored.

OK, but never UNDER ANY CIRCUMSTANCES store and use the passphrase as entered because of the risk that the lackwitted user will use the same passphrase for more than one service. Use a seeded hash on the password, if necessary truncate the result (decent hash algorithms are supposed to obfuscate bit patterns adequately), and use /that/ as the password being submitted to the remote service.

What you do locally is your responsibility: it's your computer, or you've got a professional relationship with your clients and are protected by your liability insurance. But you must ALWAYS assume that the service to which you're connecting will eventually get hacked, and you should ALWAYS assume that they aren't protecting their users' passwords adequately, hence you should NEVER put yourself in the position of passing on an incautiously-selected passphrase without hashing it.

I must admit that I do have reservations about your writing code from scratch to store passphrases locally, and if I were doing it I'd be very much inclined to research the availability of some existing library complying with PCI DSS, or interworking with one of the storage mechanisms used by various browsers etc.

(Noting Thaddy's post which has beaten me to the post, but thinking that we're in broad agreement.)
(And noting GetMem's which arrived while I was typing that...)

MarkMLl
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 28, 2021, 10:09:51 pm
Guys the software will be used by me only. It will be not shared or sold...
That's why the windows lock is enough when I'm not in front of the pc. But to connect on the db (in this case) I do not want to write anytime my username and password. To add some safety I want to store it crypted in the registry.
Codes I tried till now are not working. The only that worked is the one I used to hash a string in sha256. Problem was to decrypt then, I have not put that in mind.
But I need so an easy encryption / decryption way of a simple string.
Title: Re: The most easy encrypting/decrypting password method?
Post by: MarkMLl on September 28, 2021, 10:14:08 pm
Guys the software will be used by me only. It will be not shared or sold...
That's why the windows lock is enough when I'm not in front of the pc.

Listen old chap (or kiddo, if you lean towards Americanisms :-) As far as encryption etc. is concerned the important thing is to always assume that you're nowhere near as smart as you think you are. And if you were passably smart you'd have taken the hint given to you already about starting off with at least a partial quote to establish context :-) :-) :-) :-) :-)

MarkMLl
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on September 28, 2021, 10:16:55 pm
Quote
But I need so an easy encryption / decryption way of a simple string.
Here you go...this is a simple way to Encrypt/Decrypt a string with a key. No extra packages are needed.
Code: Pascal  [Select][+][-]
  1. unit uCrypto;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, BlowFish, Base64;
  9.  
  10.   function Encrypt(const AKey, AText: String): String;
  11.   function Decrypt(const AKey, AText: String): String;
  12.  
  13. implementation
  14.  
  15. function Encrypt(const AKey, AText: String): String;
  16. var
  17.   SS: TStringStream;
  18.   BES: TBlowFishEncryptStream;
  19. begin
  20.   Result := '';
  21.   if Trim(AText) = '' then
  22.     Exit;
  23.   SS := TStringStream.Create('');
  24.   try
  25.     BES := TBlowFishEncryptStream.Create(AKey, SS);
  26.     try
  27.       BES.Write(Pointer(AText)^, Length(AText));
  28.     finally
  29.       BES.Free;
  30.     end;
  31.     Result := EncodeStringBase64(SS.DataString);
  32.   finally
  33.     SS.Free;
  34.   end;
  35. end;
  36.  
  37. function Decrypt(const AKey, AText: String): String;
  38. var
  39.   SS: TStringStream;
  40.   BDS: TBlowFishDeCryptStream;
  41.   Str, Txt: String;
  42. begin
  43.   Result := '';
  44.   if Trim(AText) = '' then
  45.     Exit;
  46.   Str := '';
  47.   Txt := DecodeStringBase64(AText);
  48.   SS := TStringStream.Create(Txt);
  49.   try
  50.     BDS := TBlowFishDeCryptStream.Create(AKey, SS);
  51.     try
  52.       SetLength(Str, SS.Size);
  53.       BDS.Read(Pointer(Str)^, SS.Size);
  54.       Result := Str;
  55.     finally
  56.       BDS.Free;
  57.     end;
  58.   finally
  59.     SS.Free;
  60.   end;
  61. end;
  62.  
  63. end.
  64.  
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 28, 2021, 10:33:49 pm
Did you just coded it? Thanks.
If it was commented it was better to learn  :D

Edit: just read base64 is unsafe.
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on September 29, 2021, 06:21:51 am
@Conte

Quote
Edit: just read base64 is unsafe.
Blowfish, the main part of the encryption is Blowfish. Base64 is just for cosmetic purposes, so the end result don't look like a vomit.
Is it safe? No, but not because of Blowfish. Your executable can be easily disassembled, the password will reveal itself like a magic.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Thaddy on September 29, 2021, 06:59:06 am
The auto-login can be achieved by the following schematic:
First time use: compare the hashed credentials from the first login.
If that is OK, issue a public certificate to the user..
After that certificate is issued you can skip further pw logins - in code - on that machine.
The program will only run on that single machine , for a single user and nobody but its user can use the application. With e.g. OpenSSL - or with a bit more effort in code -you can create a certificate authority server side.
You can create client certificates in code or also with OpenSSL.
You may have to do some admin to have the certificate accepted on your machine or use commercially available certificates.
The only direct vulnerability is the possibility that someone else is able to access the user account: in that case it is fatal, so everything relies on strong passwords for access to that OS account. Another option is to store the user certificate on a portable medium instead of the certificate store. That would not even need further credentials. This is a bit like how RSA sticks work.
Once you understand this and implemented it you are able to create software that rely on "certificate walls" i.e. machines and domains that share data with eachother must have certificates that are part of the same certificate chain and issued by the same authority.
Title: Re: The most easy encrypting/decrypting password method?
Post by: dbannon on September 29, 2021, 07:13:22 am
I remember doing something like what Conte wants a very many years ago when security was not seen as important. With a password embedded in the binary, all you needed to see it was the strings command.  So, I broke the password up into several bits declared in different places. But the compiler's optimization put it all back together again ! Sigh.

But, what Conte wants is not that different to what we do with our browsers every day, we go to some web site, perhaps gitlab, enter our password and the browser wants to save it for us.  Come back tomorrow and its all there cached. I am guessing Firefox encrypts your (not mine) password and decrypts it when its needed the next day ?

OAuth and similar systems are better ....

Davo
Title: Re: The most easy encrypting/decrypting password method?
Post by: Thaddy on September 29, 2021, 07:16:02 am
Quote
OAuth and similar systems are better ....
Actually, that is an implementation of part of what I described  :D
For OP this is a good solution too and we have OAUTH/OAuth2 code as standard in the FPC standard libraries. (Actally two) e.g. the google one. The downside is it requires internet access, so is less applicable to private networks. It also requires a Google Key to develop.
Title: Re: The most easy encrypting/decrypting password method?
Post by: MarkMLl on September 29, 2021, 09:02:13 am
But, what Conte wants is not that different to what we do with our browsers every day, we go to some web site, perhaps gitlab, enter our password and the browser wants to save it for us.  Come back tomorrow and its all there cached. I am guessing Firefox encrypts your (not mine) password and decrypts it when its needed the next day ?

I've not investigated in detail how it works but it's possible to use an external program to decode and dump Mozilla's stored passphrases for backup purposes. And while Firefox etc. are commendably thorough about asking for the master password at startup and when anything is to be displayed in clear, my recollection is that the dump program doesn't- even when first installed.

And again I'd emphasise that Mozilla's way of doing it is questionable in that it does absolutely nothing to prevent a user using the same passphrase for multiple online services.

Having said which, as a modestly clued-up user who is careful to not reuse passphrases, I'm rather happier with Mozilla's password management than I am with any third-party service that manages plaintext passphrases.

MarkMLl
Title: Re: The most easy encrypting/decrypting password method?
Post by: linnemann on September 29, 2021, 10:03:12 am
Just wanted to add this great article about PW hashing.

https://medium.com/@marcusfernstrm/hash-it-like-you-mean-it-proper-password-hashing-in-freepascal-55c85bad4a96

Title: Re: The most easy encrypting/decrypting password method?
Post by: MarkMLl on September 29, 2021, 10:19:44 am
Just wanted to add this great article about PW hashing.

https://medium.com/@marcusfernstrm/hash-it-like-you-mean-it-proper-password-hashing-in-freepascal-55c85bad4a96

Thanks for that, and kudos to the original author. I skimmed it half-way then went back to the beginning to read it properly: it really is a very worthwhile summary.

MarkMLl
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 29, 2021, 08:27:38 pm
Just wanted to add this great article about PW hashing.

https://medium.com/@marcusfernstrm/hash-it-like-you-mean-it-proper-password-hashing-in-freepascal-55c85bad4a96
It's still difficult to apply encryption/decryption for auto login for me. :(
Title: Re: The most easy encrypting/decrypting password method?
Post by: Thaddy on September 29, 2021, 09:03:17 pm
Well, we explained it to you in very simple terms and some - like me - somewhat more difficult. I will see what I can do in the weekend.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 29, 2021, 09:36:13 pm
Also, that article explain how to generate a good hash. That's also too strong for what I need because for me sha256 security is enough. The problem is to get the decrypt to create an autologin. For sha256 it cannot exist without a private key that can be easily found.
Should be enough a simple encryption way that cannot be decoded online or with tools like notepad++ (base64).

@Thaddy thanks.

Just studying this to understand if it is what I'm looking for: https://stackoverflow.com/a/13146105/3147886
Title: Re: The most easy encrypting/decrypting password method?
Post by: MarkMLl on September 29, 2021, 10:09:57 pm
Just studying this to understand if what's I'm looking for: https://stackoverflow.com/a/13146105/3147886

No, you need an introductory text on basic cryptography.

MarkMLl
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on September 30, 2021, 10:34:59 pm
I'm blocked with the auto-login. I was able to encrypt a string but didn't realized it cannot be decrypted.
So problem changed: I need a safe way to store the password without success.
I found some tips about windows credential manager and the usage with delphi but I'm only getting errors.
Title: Re: The most easy encrypting/decrypting password method?
Post by: devEric69 on September 30, 2021, 10:41:25 pm
So problem changed: I need a safe way to store the password, without success.

You should take a look at OnGuard (https://github.com/graemeg/onguard) (when we know nothing about cryptology, like me, except XOR, it's the easiest O:-) ).
Title: Re: The most easy encrypting/decrypting password method?
Post by: dbannon on October 01, 2021, 01:38:25 am
So problem changed: I need a safe way to store the password without success.

Look Conte, you are thinking of this as a technical problem, its not, its a social one.  What you mean by 'safe' depends entirely on context.  If you live in a house 100 km from anyone else, never have visitors and never connect to the internet, a Post It Note stuck on the side of your screen is quite safe.

If you share a house with a comsci student, a gamer and a person who loves practical jokes, its a very different situation. You need to do a careful risk assessment and balance that off against the level of convenience you believe you must have.

* The Post It Note ?  Someone might see it and guess its a password ...
* A plain text file with all your passwords ?  What if you leave your laptop on a train ....
* Use GemMem's really good code snip it and encrypt your passwords using a key hard wired in your code ? Someone (who finds your laptop on the train) might look through your code, see what the password is and decrypt your password file.  Or they may use your application to connect, with your passwords the the sites you use it with.
* Same as above but you use one password, that you can remember to unlock your app. Now, as long as you don't leave the app running when you leave the laptop on the train ...

Then look at the impact of the risks.

* Well, one of the passwords gets me into Dad's company's bank account, hmm...
....
* One of the passwords is for the Lazarus forum, I don't use that much. But that practical joker ...

Then, look at the convenience issue.
* The Post It note is always there when I need it.
* If I forget the one password I need to unlock the application, I loose all my passwords .....

I personally use KeepPassX, my wife uses her own version, its relatively easy, I copy and paste the password I need. But I do have to remember its unlock password and I have to remember to put EVERY password I create in there.

There, I have answered your question without a single line of code !

Davo
Title: Re: The most easy encrypting/decrypting password method?
Post by: MarkMLl on October 01, 2021, 08:41:30 am
I'm blocked with the auto-login. I was able to encrypt a string but didn't realized it cannot be decrypted.

In that case you didn't encrypt it, you hashed it. Go back and read what everybody has been trying to tell you.

Apart from that I echo the good advice that Davo's given you, but would add that software is readily available which can (a) find less-than-random data in a binary file and highlight it as text or trivially-obfuscated text (b) find fully-random data in a binary file and highlight it as a possible encryption key. There's ways round that, but if you intend to roll your own then you urgently need to learn about the underlying techniques for both defence and attack.

MarkMLl
Title: Re: The most easy encrypting/decrypting password method?
Post by: devEric69 on October 01, 2021, 09:03:24 am
@Conte, AMHO, practically speaking, you sould need:
- an encryption-decryption algorithm - said, named Crypto_x - and stored in your program;
- an overall administration key-phrase for (administration role to manage each program's key-phrase, server side) your encrypting program, which must be known only to you, never encrypted;
- a key-phrase only for your program (program specific, used for all program's clients) must itself be encrypted and stored inside your programm (by your overall administration keyphrase), stored encrypted or not on the serveur side;
So, already said, but never ever reveal your overall and your program encryption keys to your client's side, of course. @dbannon, btw, I also use KeepPassX in order to store the key-phrases.
- your client's side information (password, or license number, ...). I don't know what you want to use as protection, verification, ... But this information must - too - be already encrypted and stored (specific for each client of the same program) in the program.

➔ If you have injected inside your software, in hexadecimal: the encrypted keyphrase (of your program) + the information of your client (what is called a composite license, said) + the algo. named Crypto_x, 
then you can decrypt the already crypted information in your program. You can already display this roughly when you start your program: "licence: decrypted num#' and\or 'client name: decrypted client name'. This is already disusasive.

It's also possible to imagine making a "match" request on the internet, if this information exists in a database on the .net. You could pass, for example, the encrypted data over the request, and it's the algo. Crypto_x on the HTTP server side that will decrypt and check if it matches something on the server's database, etc.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 01, 2021, 09:20:47 am
@devEric69
The app can connect to multiple databases. Each with a user/password. I want to avoid to type every time the credential (or to copy paste from KeepPassX). To add a simple measure of security of course it should be encrypted (the password only). It not need to be strong but not easy to decrypt too.
That's why I am thinking that using windows credential manager could be enough. Because creating what you said is of course more safe, but I don't need that level of security.
I'm trying the code suggested here but the compiler gives a lot of errors:
https://stackoverflow.com/questions/13145112/secure-way-to-store-password-in-windows
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on October 01, 2021, 10:49:11 am
@Conte

You don't listen do you? Since this annoying thread is keep popping up in my feed, I translated the Windows Credential Manger functions for you. Now please close this thread.

Functions:
Code: Pascal  [Select][+][-]
  1. uses jwaWindows;
  2.  
  3. function CredReadGenericCredentials(const Target: WideString; var Username, Password: WideString): Boolean;
  4. var
  5.   Credential: PCREDENTIALW;
  6.   Le: DWORD;
  7.   ErrMsg: WideString;
  8. begin
  9.   Result := False;
  10.   Credential := nil;
  11.   if not CredReadW(PWideChar(Target), CRED_TYPE_GENERIC, 0, {var}credential) then
  12.   begin
  13.     Le := GetLastError;
  14.     ErrMsg := 'Could not get "' + Target + '" generic credentials: ' + WideString(SysErrorMessage(Le)) + ' ' + WideString(IntToStr(Le));
  15.     OutputDebugStringW(PWideChar(ErrMsg));
  16.     Exit;
  17.   end;
  18.   try
  19.     Username := Credential^.UserName;
  20.     SetString(Password, PWideChar(Credential^.CredentialBlob), Credential^.CredentialBlobSize div 2);
  21.   finally
  22.     CredFree(Credential);
  23.   end;
  24.   Result := True;
  25. end;
  26.  
  27. function CredWriteGenericCredentials(const Target, Username, Password: WideString): Boolean;
  28. var
  29.   Credentials: CREDENTIALW;
  30. begin
  31.   ZeroMemory(@Credentials, SizeOf(Credentials));
  32.   Credentials.TargetName := PWideChar(Target);
  33.   Credentials.Type_ := CRED_TYPE_GENERIC;
  34.   Credentials.UserName := PWideChar(Username);
  35.   Credentials.Persist := CRED_PERSIST_LOCAL_MACHINE;
  36.   Credentials.CredentialBlob := PByte(Password);
  37.   Credentials.CredentialBlobSize := 2*(Length(Password));
  38.   Credentials.UserName := PWideChar(Username);
  39.   Result := CredWriteW(@Credentials, 0);
  40. end;
  41.  
  42. function CredDeleteGenericCredentials(const Target: WideString): Boolean;
  43. begin
  44.   Result := CredDeleteW(PWideChar(Target), CRED_TYPE_GENERIC, 0);
  45. end;  


Usage:
Code: Pascal  [Select][+][-]
  1. const
  2.   Target: WideString = 'Conte''s super safe password until the first memory dump';
  3.  
  4. procedure TForm1.Button1Click(Sender: TObject);
  5. var
  6.   Username: WideString;
  7.   Password: WideString;
  8. begin  
  9.   Username := 'conte';
  10.   Password := '12345';
  11.   if CredWriteGenericCredentials(Target, UserName, Password) then
  12.     ShowMessage('Successfully stored the password!')
  13.   else
  14.     ShowMessage('Crap!');
  15. end;
  16.  
  17. procedure TForm1.Button2Click(Sender: TObject);
  18. var
  19.   UserName: WideString;
  20.   Password: WideString;
  21. begin
  22.   Username := '';
  23.   Password := '';
  24.   if CredReadGenericCredentials(Target, Username, Password) then
  25.     ShowMessage('Username: ' + Username + sLineBreak + 'Password: ' + Password)
  26.   else
  27.     ShowMessage('Crap!')
  28. end;
  29.  
  30. procedure TForm1.Button3Click(Sender: TObject);
  31. begin
  32.   if CredDeleteGenericCredentials(Target) then
  33.     ShowMessage('Succesfully deleted!')
  34.   else
  35.     ShowMessage('Crap!')
  36. end;          


Proof it works:
See attached screenshot.

Title: Re: The most easy encrypting/decrypting password method?
Post by: Warfley on October 01, 2021, 11:54:36 am
The question with respect to cryptography is always what you want to archive.

Your goal is to store the password so the user does not need to reenter it every time. So my first question is, why do you want to use cryptography in the first place? To make it secure? Well, bad news for you, it isn't.
Encryption can be thought of as putting some information into a box and putting a padlock on it. To open it you need the key for the padlock. If you use cryptography to store a single password, you just moved the problem one step further, because now what do you do with the encryption key? Let the user enter it each time the application starts? Then you traded one password for another, and as users are lazy, probably the exact same password anyway. In the padlock analogy this is like carrying a key so you can open a box with another key inside.
Another solution would be to hardcode the password as a constant in your program, in which case a simple string search through your binary reveals the password. You could try to be smart and obfuscate the password, e.g. let it be generated through a pseudo random number generator like an LSR with a fixed random seed, so it requires some reverse engineering, but thats not real security either. This is basically like just leaving the key hanging in the padlock
Lastly you could simply store the encryption password somewhere on hard disk, but then, why not simply store the original password on hard disk? Which is badically storing the key right next to the box
To get back to the padlock analogy, a padlock is useless if you place the key right next to the box. It is only secure if the key is kept somewhere secure. And if you find the local filesystem of your computer not secure,  there is no point in storing the key there.

Long story short, all you do is replace one password with another but still have the same problems as before.

Simple solution, just don't bother. Programs like Firefox or Chrome store passwords locally without encryption. They encode them differently (I think FF uses Base64 encoding) to not have it in plain text (and thereby easiely searchable) but after all, any additional effort to try to be smart is simply a waste of time. It doesn't get any more secure and you are just making your life harder
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 01, 2021, 08:34:38 pm
@GetMem I had put the wrong uses, I was using jwawincred. Anyway it doesn't work for me. If I run the exe from Lazarus' compiler button it gives me back 'External SIGSEGV error'. If I run the exe as administrator I just receive the 'Crap!' message.
This is the header part of my unit1 before your function starts:
Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, jwawindows;

type

  { TForm1 }
                                   

     
    TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);

  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}     

SIGSEGV error appears only when button1 is clicked, the other 2 just show 'crap!'.
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on October 02, 2021, 08:46:40 am
What is the error message inside function CredWriteGenericCredential? Put the following line to the end of the function:
Code: Pascal  [Select][+][-]
  1.   //...
  2.   Credentials.UserName := PWideChar(Username);
  3.   Result := CredWriteW(@Credentials, 0);
  4.   ShowMessage(SysErrorMessage(GetLastError) ;  // this one
Did you try to run the program as admin? Also what is your windows version?
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 02, 2021, 09:02:06 am
I have run it as admin. I have wind10 64bit.
To set a breakpoint I just set the red ? point on the left of the line?
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on October 02, 2021, 09:05:01 am
I edited my previous post. Try to get the last os error.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 02, 2021, 09:28:09 am
'Incorrect parameter!'
Crap!

This is my current code pastebin.com/NdVL1k9x
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on October 02, 2021, 10:12:39 am
Quote
Incorrect parameter!'
This message makes no sense to me. Anyways I' m out of office until Monday so I cannot help. Maybe somebody else can test the code, if not I will take a look Monday.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 02, 2021, 10:26:44 am
It looks like an error that returns from the windows credential manager? Maybe it worked to your that have windows in english language.
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on October 02, 2021, 10:31:03 am
I don't think it's related to language, must be something else. Do you have 32 or 64 bit Lazarus/FCP?
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 02, 2021, 10:34:57 am
x86_64-win64-win32/win64.
That's what is wrote in the informazion window of lazarus. Not really clear.
I'm looking on google for a way to know exactly what it is.

Edit: it's 64 bit or the version for cross compiling.
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on October 02, 2021, 10:42:43 am
64 bit. Install a 32 bit version with fpcupdeluxe, it won't interfere with your current installation. Run a few test with the 32  bit version.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 02, 2021, 11:32:10 am
Yes, problem was lazarus bit version. With the 32bit works now.
So how do i decide if something must be compiled in 64 or 32 bit?

Also with this 32bit version the compiler take a lot of time to compile.
Title: Re: The most easy encrypting/decrypting password method?
Post by: GetMem on October 02, 2021, 11:58:05 am
Quote
Yes, problem was lazarus bit version. With the 32bit works now.
Good!  Finally some progress...now we have to figure out why does not work with the 64 bit version. Again I'm not home now, but you can try the following:
in the 64 bit version replace {$mode objfpc}{$H+} with {$mode Delphi}. If does not work then you have to wait until Monday. Work with the 32 bit version for now.
Title: Re: The most easy encrypting/decrypting password method?
Post by: DonAlfredo on October 02, 2021, 01:45:36 pm
This is code that works on win32 and win64.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   { TForm1 }
  12.   TForm1 = class(TForm)
  13.     Button1: TButton;
  14.     procedure Button1Click(Sender: TObject);
  15.   private
  16.   public
  17.   end;
  18.  
  19. var
  20.   Form1: TForm1;
  21.  
  22. implementation
  23.  
  24. {$R *.lfm}
  25.  
  26. uses
  27.   Windows;
  28.  
  29. const
  30.   Target: WideString = 'Conte''s super safe password until the first memory dump';
  31.  
  32.   CRED_TYPE_GENERIC          = 1;
  33.   CRED_PERSIST_LOCAL_MACHINE = 2;
  34.  
  35. type
  36.   CREDENTIAL_ATTRIBUTE = record
  37.     Keyword: LPTSTR;
  38.     Flags: DWORD;
  39.     ValueSize: DWORD;
  40.     Value: LPBYTE;
  41.   end;
  42.   PCREDENTIAL_ATTRIBUTE = ^CREDENTIAL_ATTRIBUTE;
  43.  
  44.   CREDENTIALW = record
  45.     Flags: DWORD;
  46.     Type_: DWORD;
  47.     TargetName: LPTSTR;
  48.     Comment: LPTSTR;
  49.     LastWritten: FILETIME;
  50.     CredentialBlobSize: DWORD;
  51.     CredentialBlob: LPBYTE;
  52.     Persist: DWORD;
  53.     AttributeCount: DWORD;
  54.     Attributes: PCREDENTIAL_ATTRIBUTE;
  55.     TargetAlias: LPTSTR;
  56.     UserName: LPTSTR;
  57.   end;
  58.   PCREDENTIALW = ^CREDENTIALW;
  59.  
  60. function CredWriteW(Credential: PCREDENTIALW; Flags: DWORD): Boolean; stdcall; external 'Advapi32.dll';
  61.  
  62. function CredWriteGenericCredentials(const Target, Username, Password: WideString): Boolean;
  63. var
  64.   Credentials: CREDENTIALW;
  65. begin
  66.   ZeroMemory(@Credentials, SizeOf(Credentials));
  67.   Credentials.TargetName := PChar(Target);
  68.   Credentials.Type_ := CRED_TYPE_GENERIC;
  69.   Credentials.UserName := PChar(Username);
  70.   Credentials.Persist := CRED_PERSIST_LOCAL_MACHINE;
  71.   Credentials.CredentialBlob := PByte(Password);
  72.   Credentials.CredentialBlobSize := 2*(Length(Password));
  73.   Result := CredWriteW(@Credentials, 0);
  74. end;
  75.  
  76. { TForm1 }
  77.  
  78. procedure TForm1.Button1Click(Sender: TObject);
  79. var
  80.   Username: WideString;
  81.   Password: WideString;
  82. begin
  83.   Username := 'conte';
  84.   Password := '12345';
  85.   if CredWriteGenericCredentials(Target, UserName, Password) then
  86.     ShowMessage('Successfully stored the password!')
  87.   else
  88.     ShowMessage('Crap!');
  89. end;
  90.  
  91. end.
  92.  
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 02, 2021, 03:40:00 pm
Thanks everyone for helping me. GetMem said it is a crap security by the way. :D
We can take this topic open to look forward and find a safer auto login? Could be interesting for a lot of people imo.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Warfley on October 02, 2021, 04:18:34 pm
As I discussed at length in my earlier post: Link (https://forum.lazarus.freepascal.org/index.php?topic=56489.msg420237#msg420237) there is no secure way of archiving this.

I'm currently on my phone. Later when I'm at my desktop l can give you some more detailed explaination of different approaches ans their advantages
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 02, 2021, 04:25:29 pm
@Warfley ok.
@DonAlfredo yes it works. Button1 only! I've left the same code for button2 and 3 and it gives error: unit1.pas(19,15) Error: Forward declaration not solved "Button2Click(TObject);"
The same with button3.

type

  { TForm1 }

    TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);   

Edit: it doesn't work anymore. I have just reopened the old project when it was working and it not work anymore. This time I think the problem is lazarus. I open a new project and it compile me the closed one. Is it a known bug?
I retried the same identical code of GetMem in the 32bit lazarus and the buttons do no actions.

Edit2: I had to delete the project folder. Re-create another project with the same code of the previous and it works. What was wrong with lazarus?
Title: Re: The most easy encrypting/decrypting password method?
Post by: Warfley on October 02, 2021, 08:07:54 pm
As promised here is my more detailed explaination.

As already stated, just encrypting the password is basically just exchanging one password for another, which you then have the exact same problem of storing.
So the question is what do you want to protect against. Generally I see three levels of protection: 1. Protect against accedental access (e.g. accidentally delting, overriding or sharing the data), 2. protecting against accidentally finding or simple searches for the data (e.g. via filesystem scan), 3. protecting against unauthorized access.

The most simple solution that does not protect anything is to just write the data plain to a file in Documents, the users home folder or the program folder.
The first step of protection then is really simple, just store the data somewhere obscure like the AppData directory. Normally this directory is not visited by the user, so it is very unlikely that a user will accidentally delete, modify or share (e.g. by zipping all of the program folder and sending it to someone) the data.
The problem here is that if you simply do a filesystem search for the username, you will easiely find the file, or if someone finds a suspicious looking file and opens it can read it directly. To protect against that, simply encode your data. Encoding is changing the representation. For example, the text "Hello World" can be encoded as Base64 to read "SGVsbG8gV29ybGQ=". Decoding this isn't hard by any means, but no one will accidentally find your data and it protects against simple filesystem searches. This in combination with the first step (hidden directories) is what most applications like Browsers, FTP clients and co are using.

Lastly the protection against unauthorized users. This is done using password stores, such as the one provided by the Windows API. There are different levels of protection such can provide, but basically they all do the following: The passwords are stored by the password store encrypted with the users login credentials. When the user logs into the system with their account, the password store will be opend under that user. Applications can now request passwords from the password store. The password store verifies if the application is allowed to access the requested password (e.g. by checking if the user that started the application is also the same user who owns the password). Some password stores (I think the Windows one actually does this) make use of hardware modules provided by Intel and AMD CPUs which ensure that the system was booted under the correct circumstances, meaning if someone boots under a different OS (e.g. live Linux) these modules will not allow access to the password store.
This protects against a few different attacks. First you can only access passwords of a user that is currently logged in, and only by the user that stored the password, meaning another user (or someone who got hold of the HDD on a different machine) can not access the data. Some Implementations like on iOS or Android even make sure that only certain applications (i.e. applications by the same developer) can access shared data, meaning other applications even though the user is logged in can not access the data.
While all this filtering is neat and all, this isn't as secure as it sounds. Because systems can be hacked (e.g. iOS can be jailbroken) meaning all these neat checks if the requests come from authroized programs can be circumvented. The only real security it gives you is that as long as the user is not logged in (i.e. provided the password) you can not access the data. Or to put it differently, to get access to the data you need to have access to the users account and/or password. But if someone starts the PC and loggs in, there is no "hard" barrier between an attacker and the password anymore. That said, it is still massively more complicated than a normal approach.

To sum this up, the usage of a hidden folder only secures some stupid oopsies by the user like accidentally deleting the files. The encoding helps to secure against accidentally disocovering the password, e.g. if you have someone over and they get access to your PC with little time such that they don't stumble over your data by clicking the wrong things or using the filesystem search. The last one, the systems password store secures against people with hardware access to your device but not access to your system user.


So with that out of the way, what is right for you. Well generally speaking, it depends on two things, how valuable is the password and how likely is it that it will be attacked.
For example the password for my raspi is not very valuable as my raspi is just a mostly empty system lying somewhere in a drawer 99.9% of the time turned off. Accessing the Raspi also requires someone to break into my home making it rather unlikely that it will be attacked. This does not need a high level of protection.
My bank details on the other hand are highly valuable but if I only have them written on a piece of paper in my home, it is again rather unlikely someone will attack them. But if I store them in a password file on a cloud service or something similar, this changes and therefore require a high degree of security.

I would always make use of the first two measures (hidden folder, encoded data), as this is basically free (doesn't take much effort, easiely portable). This is what for examples browsers like Firefox or Chrome use to store the Passwords. Whats secure enough for these applications is probably secure enough for your application as well.
The password store is only required on multi user systems where you need to protect against other users on that system (e.g. in a corporate setting, where PCs are shared e.g. by using a Windows Domain Server) or, if you fear that someone will break into your home, steal your PCs hard drive just to get to that password.
If your data is so valuable that people would break into your home just to get it, then I would suggest to not store that password at all and have the user enter it every time. Users should be expected to take these 10 seconds to enter the password if the data is so valuable.
Title: Re: The most easy encrypting/decrypting password method?
Post by: Conte on October 02, 2021, 11:15:59 pm
@Warfley thank you!
TinyPortal © 2005-2018