1

So I'm currently creating a CLI program for my encryption library. This is just a test program, as I will later build a GUI-based program for it. I am storing the encryption key in the registry, for now, might change this later. So far, I can write the key to the registry, but I can't convert the data from the registry back to a string to use as the actual key in the encryption.

Here's my current code:

internal String Encrypt()
        {
            Console.Clear();
            Console.Write("Encryption\nPlease enter the path to the file you want to encrypt: ");

            String FileInPath = Console.ReadLine();
            String FileOutPath = "";
            String FileData = "";

            while (FileInPath == "")
            {
                FileInPath = RetryPathIn();
            }

            String RetryPathIn()
            {
                Console.WriteLine(".>>");
                String PathInStr = Console.ReadLine();
                return PathInStr;
            }
            
            Console.Write("\nPlease enter the path of the file you want to decrypt: ");
            FileOutPath = Console.ReadLine();

            while (FileOutPath == "")
            {
                FileOutPath = RetryEncrypt();
            }

            String RetryEncrypt()
            {
                Console.WriteLine(".>>");
                String FileOutPathStr = Console.ReadLine();
                return FileOutPathStr;
            }
            object Key = Registry.CurrentUser.OpenSubKey(@"Software\NikkieDev Software").GetValue("Key");
            String KeyStr = Key.ToString();
            String FileOutData = "";

            if (Key!=null)
            {
               FileOutData = Crypt.Encrypt(FileData, KeyStr);
            }

            var file = File.Create(FileOutPath);
            file.Close();
            File.WriteAllText(FileOutPath, FileOutData);

            return $"Data has been encrypted and saved in {FileOutPath}";
        }

I am fairly new to the registry, and I've only recently found out how to use it as data storage in programming. I am using .NET 6 for this, and I hope that someone can help me.

[EDIT] I've shown below how I've created the register data. Due to people asking about it

internal void Initialize()
        {
            String SettingsFile = File.ReadAllText(CoreObject.DataFile);
            dynamic _JsonObj = JsonConvert.DeserializeObject(SettingsFile);

            if (_JsonObj["KeyGenerated"] == 0)
            {
                RegistryKey RegData = Registry.CurrentUser.CreateSubKey(@"Software\NikkieDev Software");
                String NewKey = Key.CreateKey();
                RegData.SetValue("Key", NewKey);
                
                _JsonObj["KeyGenerated"] = 1;

                dynamic NewData = JsonConvert.SerializeObject(_JsonObj, Formatting.Indented);
                File.WriteAllText(CoreObject.DataFile, NewData);
                RegData.Close();
            }
        }

Due to recent questions about missing code, I here provide my encryption library that I'm building this program around: https://github.com/NikkieDev/bungocrypt_cs

The CreateKey() returns a string (the key). Furthermore Crypt.Encrypt() takes the key and the data and scrambles them together and exchanges all the characters with one another.

NikkieDev
  • 236
  • 3
  • 12
  • 3
    The way to read it out depends on how you wrote it in. So how did you write the data to the registry? – Raymond Chen Sep 08 '22 at 14:56
  • I wrote it to the registry as a plain string. It is stored there as a REG_SZ with the key as it's value. I used ```RegistryKey RegData = Registry.CurrentUser.CreateSubKey(@"Software\NikkieDev Software"); RegData.SetValue("Key", Key.CreateKey()); RegData.Close()``` – NikkieDev Sep 08 '22 at 14:58
  • 2
    Did you encode the data to make it a string (say as a hex string or a base 64 string)? If you just took binary data and wrote it to the registry as REG_SZ, you will have a hard time trying to read it back if it contains zeros in the binary data. Try using base 64 (or, for a better debugging experience, look at https://stackoverflow.com/questions/311165/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-and-vice-versa – Flydog57 Sep 08 '22 at 15:51
  • I've now also tried an expanded string and a multi string. They both don't work. – NikkieDev Sep 08 '22 at 16:53
  • Did the value read into `KeyStr` match the value written from `NewKey`? I.e., is the problem with the registry, or is the problem with the decryption? – Raymond Chen Sep 08 '22 at 17:47
  • @RaymondChen `KeyStr` Is supposed to be the data from the registry. The registry data being the generated `NewKey`. – NikkieDev Sep 08 '22 at 17:51
  • That wasn't my question. My question is "If you look at `NewKey` in the debugger before you write it to the registry, and you look at `KeyStr` in the debugger after you read it from the registry, do they match?" – Raymond Chen Sep 08 '22 at 18:08
  • `KeyStr` Doesn't output anything as that is what causes the Error. – NikkieDev Sep 08 '22 at 18:12
  • Repeating the question: Does it match what was in `NewKey`? – Raymond Chen Sep 08 '22 at 18:29
  • I have no way of checking. I would say yes, as it directly copies the data. It just outputs it in a different variable type which I cannot log – NikkieDev Sep 08 '22 at 18:30
  • Use a debugger to see the value. – Raymond Chen Sep 08 '22 at 18:31
  • 2
    If I write a string to the registry with your code from `Initialize()` and load it again with your code from `Encrypt()`, the strings before writing and after loading are equal. It looks like the registry I/O itself is not the problem. Possibly an incorrect encoding (see Flydog57's [comment](https://stackoverflow.com/questions/73651129/converting-registry-data-to-usable-string-in-c-sharp#comment130060623_73651129)). Post the missing code for key generation, i.e. the type of `Key` in `Initialize()` or if user defined, the implementation (incl. `CreateKey()`). – Topaco Sep 11 '22 at 08:36
  • 2
    Currently it is not possible to get a complete picture because important parts of the code are missing. For instance, it is not at all clear which encryption algorithm is used, what the keys look like, etc. Post therefore also the code to `Crypt.Encrypt(FileData, KeyStr)`. For a repro to be possible, the posted code should ideally be executable, see [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Topaco Sep 11 '22 at 08:46
  • how did you write the data to the registry? – Hediye_seza Sep 11 '22 at 16:24
  • 1
    Even using the newly posted/linked code, I cannot reproduce the issue. However, `FileData` in `Encrypt()` does not seem to be filled. Other than that, the registry I/O of the key and encryption when successively calling `Initialize()` and `Encrypt()` work on my machine, and even decryption with `Crypt.Decrypt(FileOutData, KeyStr)`. You should post a complete example, i.e. also the call of the methods including sample data, so that the problem can be reproduced. – Topaco Sep 11 '22 at 16:31
  • Thank you @Topaco. I have heard enough, and I can fix it on my own now. I very much appreciate your help – NikkieDev Sep 11 '22 at 18:31

1 Answers1

1

Nikkie, your code works just fine.

You are using the Registry API correctly, and running your code the key has the correct string value (tested with dotnet6 on windows11). Here is my output adding a print:

Generated key: HYO"kjvw'l.K2IDu:*Mt-ze~=/,Ls6Zgf_]WSc[<F7Q185@NTB?^rxP)J#p$4VX q(&nh!Go\3Ci|a}EdR{+;b9>`0AyUm%
Key value from reg: HYO"kjvw'l.K2IDu:*Mt-ze~=/,Ls6Zgf_]WSc[<F7Q185@NTB?^rxP)J#p$4VX q(&nh!Go\3Ci|a}EdR{+;b9>`0AyUm%

Do not forget to always close the key when you do not need it anymore (well done in your initialization, but not done after). Close the RegistryKey as soon as you can. For instance in your Initialize function, it would be better to close the key before doing your JSON serialization and IO as some exceptions may occur there.

An other point, regData.SetValue will definitely accept empty string (but will throw if null is given). So this can also be a way to debug if you have the same problem again, somewhere you might be writing something empty as mentioned in comments.

Some recommendations as you are saying that you are new on some concepts:

  1. Strongly recommended to check for nullity. For instance Registry.CurrentUser.OpenSubKey may return null. You do want to check that before continuing.

  2. Instead of using Key.ToString(), what you will prefer is String KeyStr = (String)Key or String? KeyStr = Key as String. In the first one, an exception will be thrown if the cast is not possible. In the second one, do not forget to check for nullity if the cast can't be done.

  3. Starting with dotnet6, try to use the built-in JSON serializer in System.Text.Json which is fairly nice now, and has very nice options to customize serialization behavior.

  4. I strongly recommend that you read the security part of this documentation from Microsoft, as you are planning to continue working with cryptography and keys. I don't know the exact scope of your keys, but it's a good reading anyway.

glihm
  • 1,138
  • 13
  • 29