mattosaurus / PgpCore

.NET Core class library for using PGP
MIT License
244 stars 98 forks source link

Add multiple Private Keys to Encryption keys #277

Open civteam-amonplaisir opened 10 months ago

civteam-amonplaisir commented 10 months ago

I have a case where I have 2 .key files that are required to be within the private-keys-v1.d folder before the file can be decrypted. I currently have both private keys and when I try to decrypt the file (by adding 1 of the private keys as a public key in an array with he actual public key) I get the message "Could not find any signing keys in keyring at PgpCore.Utilities.FindBestSigningKey(PgpSecretKeyRingBundle secretKeyRingBundle)" I searched all over to find a solution and wasn't able to find one. Please let me know if you can help. Here is a snippet:

publicKeys has (FileInfo(.key), FileInfo(.asc) FileInfo privateKey = new FileInfo(fullSecondKeyFilePath); EncryptionKeys encryptionKeys = new EncryptionKeys(publicKeys, privateKey, decryptionKey.PassPhrase);

        using (PGP pgp = new PGP(encryptionKeys))
        {

            FileInfo inputFile = new FileInfo(fileUploadedPath);
            FileInfo outputFile = new FileInfo(fileOutputPath);

            await pgp.DecryptFileAsync(inputFile, outputFile);

            Stream outputStream = outputFile.OpenRead();

            string decryptedFileContentType;

            new FileExtensionContentTypeProvider().TryGetContentType(encryptedFileName, out decryptedFileContentType);

            return File(outputStream, decryptedFileContentType);
        }
mattosaurus commented 10 months ago

Hi, if you're using multiple keys to encrypt then you need to provide 2 (or more) public keys and not a public key and a private key. You're seeing this error because

I try to decrypt the file (by adding 1 of the private keys as a public key in an array with he actual public key)

The expected way of using multiple keys is illustrated in the below test.

https://github.com/mattosaurus/PgpCore/blob/4c32816dfcea74a42d7976bfe05313797312b625/PgpCore.Tests/UnitTests/Decrypt/DecryptAsync.File.cs#L331-L373

civteam-amonplaisir commented 10 months ago

The only thing is I don't have control over the encryption of the file. It is a third party doing the encryption. I have attempted to only pass in 1 of the private keys into the encryption keys constructor and I am still receiving the same error. I was wondering if I would be able to have 2 private keys passed in together (2 .key files)? And then have 1 public key (1 .asc file)?

mattosaurus commented 10 months ago

If they're using 2 public keys to encrypt the file then you should be able to decrypt it using either of the associated private keys (as demonstrated in the above test).

Is it possible that they're encrypting it with your public key and signing it with their private key? If so you'd need to use the DecryptAndVerify method with your private key and their public key.

Can you decrypt these files using a command line utility instead of PGPCore? If so it's possible PGPCore is missing some functionality or that you're using the wrong method.

civteam-amonplaisir commented 10 months ago

I am able to decrypt using gpg4win command line utility. Once I added the 2 .key files to the private-keys-v1.d folder, I was able to decrypt with only the public .asc key. I will try DecryptAndVerify and follow up

civteam-amonplaisir commented 10 months ago

I am still getting the same error after changing the method. I am getting this error when initializing the EncryptionKeys

mattosaurus commented 10 months ago

That's probably because you're adding one of the private keys as a public key.

If you can provide a self-contained solution that replicates the issue then I'll take a look in more detail.

civteam-amonplaisir commented 10 months ago

Okay sure thing I will create a solution that replicates this

civteam-amonplaisir commented 10 months ago

PgpDecryptionTest.zip I needed to scrub the files as it has private data but I placed dummy references to them there

civteam-amonplaisir commented 10 months ago

Let me see if I could encrypt a random file

mattosaurus commented 10 months ago

A few things I've spotted.

EncryptionKeys encryptionKeys = new EncryptionKeys(publicKeys[0], "Passphrase"); //Throws error here

This overload of EncryptionKeys is expecting a private key, not a public key as the first argument.

The DecryptAndVerifyAsync method requires both a public key and a private key to be provided in the EncryptionKeys object like so.

EncryptionKeys encryptionKeys = new EncryptionKeys(publicKeys, testFactory.PrivateKeyFileInfo, testFactory.Password);
civteam-amonplaisir commented 10 months ago

Okay I removed the passphrase and added all of the keys into a list of FileInfo of .asc, .key, .key. I then went to decrypt the file as DecryptAsync and received an error message of this "null reference object reference not set to an instance of an object" This is the line it throws the error "at PgpCore.EncryptionKeys.FindSecretKey(Int64 keyId)". Thats when I put all of the keys as public keys