mattosaurus / PgpCore

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

clearsign signature verification and removal #221

Closed gicoprasico closed 1 year ago

gicoprasico commented 1 year ago

Hi and thanks to all developers of this great library that simplify PGP encryption. The only part that I am not able to do is to verify clearsign signature (the embedded one within the file) and I was not able to remove the signature and produce the cleartext file.

For a encrypted and signed file (with clearsign) I got an error (Org.BouncyCastle.Bcpg.OpenPgp.PgpException: 'File was not signed.') while I was trying to decrypt and verify it:

        public static async Task<(bool, string)> DecryptAndVerify(string fileName, string publicKeyFilename, string privateKeyFilename, string passphrase) {

            var decryptedFilename = fileName.Replace(".asc.pgp", ".asc");
            FileInfo publicKey = new FileInfo(publicKeyFilename);
            FileInfo privateKey = new FileInfo(privateKeyFilename);
            EncryptionKeys encryptionKeys = new EncryptionKeys(publicKey, privateKey, passphrase);

            FileInfo inputFile = new FileInfo(fileName);
            FileInfo decryptedFile = new FileInfo(fileName.Replace(".asc.pgp", ""));

            PGP pgp = new PGP(encryptionKeys);
            await pgp.DecryptFileAndVerifyAsync(inputFile, decryptedFile);

            return (File.Exists(decryptedFilename), decryptedFilename);
        }

For clearsign signature removal I did not found any way to do it. At the end I used the command line, but if there is any other way I would appreciate the feedback.

        public static bool RemoveSignature(string fileName, out string unsignedFilename) {
            unsignedFilename = fileName.Replace(".asc", "");

            var removeSignatureCommand = string.Format(@"gpg --batch --yes --output {0} --verify {1}", unsignedFilename, fileName);
            var startInfo = new System.Diagnostics.ProcessStartInfo {
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
                FileName = "cmd.exe",
                Arguments = "/C " + removeSignatureCommand
            };

            var process = new System.Diagnostics.Process {
                StartInfo = startInfo
            };
            process.Start();
            process.WaitForExit();
            return File.Exists(unsignedFilename);
        }
gicoprasico commented 1 year ago

Oh, I found the answer within the unit tests.

           public static async Task<(bool, string)> VerifyAndRemoveSignature(string signedFileName, string publicKeyFilename) {

            var cleartextFile = signedFileName.Replace(".asc", "");
            var inputFile = new FileInfo(signedFileName);

            var publicKey = new FileInfo(publicKeyFilename);
            var encryptionKeys = new EncryptionKeys(publicKey);
            var pgp = new PGP(encryptionKeys);

            var result = await pgp.VerifyAndReadClearFileAsync(inputFile);
            File.WriteAllText(cleartextFile, result.ClearText);

            return (File.Exists(cleartextFile) && result.IsVerified, cleartextFile);
        }

Thank you.

gicoprasico commented 1 year ago

This can be closed as invalid.