简体   繁体   中英

Verify a detached pgp signature in c#

here's what I have:

  • A big file called update.zip
  • A text file called update.zip.sha256sum containing...yes you guessed it, currently it's "204f687dae2e9b66afce079b29abf935949e31de838aa4f5bd8f9b4440fadf2d update.zip" (1 row)
  • A 3rd file called update.zip.sha256sum.asc containing "-----BEGIN PGP SIGNATURE----- Version: GnuPG v1... -----END PGP SIGNATURE-----" so only the signature. All these are on a website.
  • Then, of course I have the public key to verify the signature. I made it a resource inside the project, as it's not going to change.

What I need to do from code: check the update.zip's not been tempered with. Therefore check the signature, which confirms the file update.zip.sha256sum is ok, so I can use the sha256 inside it to compare with the one I calculate. All pretty basic. Problem is: the verify method always returns false. Doing it from the desktop app works, so the files are ok for sure.

What I did: of course I read all the similar questions here, specially this . I also read all the bouncy castle documentation. That was fast and easy - there is NONE.

Finally I used one of the examples, namly the one under..\crypto\test\src\openpgp\examples\DetachedSignatureProcessor.cs

so here is the (failing) code:

    private static bool VerifySignature(string fileName, Stream inputStream, Stream keyIn)
    {
        inputStream = PgpUtilities.GetDecoderStream(inputStream);

        PgpObjectFactory pgpFact = new PgpObjectFactory(inputStream);
        PgpSignatureList p3 = null;
        PgpObject o = pgpFact.NextPgpObject();

        p3 = (PgpSignatureList)o;


        PgpPublicKeyRingBundle pgpPubRingCollection = new PgpPublicKeyRingBundle(
            PgpUtilities.GetDecoderStream(keyIn));
        Stream dIn = GetStream(fileName);
        PgpSignature sig = p3[0];
        PgpPublicKey key = pgpPubRingCollection.GetPublicKey(sig.KeyId);
        sig.InitVerify(key);

        int ch;
        while ((ch = dIn.ReadByte()) >= 0)
        {
            sig.Update((byte)ch);
        }

        dIn.Close();

        if (sig.Verify())
        {
            Console.WriteLine("signature verified.");
            return true;
        }
        else
        {
            Console.WriteLine("signature verification failed.");
            return false;
        }
    }

    public static Stream GetStream(string stringData)
    {
        MemoryStream stream = new MemoryStream();
        StreamWriter writer = new StreamWriter(stream);
        writer.Write(stringData);
        writer.Flush();
        stream.Position = 0;
        return stream;
    }

The code runs through joyfully but always chooses the "signature verification failed." route.

What I'm not sure of is whether I miss some steps or whether I'm using the wrong ingredients. The 3 I use are the plain text sha256sum file (fileName), the signature file sha256sum.asc (inputStream) and the public key (keyIN).

Finally I solved it. But don't ask which step made the difference;-)

 public static bool VerifySignature(string fileName, Stream inputStream, Stream keyIn)
    {
        PgpPublicKeyRingBundle pgpPubRingCollection = new PgpPublicKeyRingBundle(keyIn);
        PgpPublicKey pubicKey = pgpPubRingCollection.GetPublicKey(4100000000000000000);    //once I knew the right one, I put it here directly as it won't change anyway
        Stream signaturStrom = PgpUtilities.GetDecoderStream(inputStream);
        PgpObjectFactory pgpWTFactory = new PgpObjectFactory(signaturStrom);
        PgpSignature signtr = ((PgpSignatureList)pgpWTFactory.NextPgpObject())[0];
        signtr.InitVerify(pubicKey);

        try
        {
            Stream dIn = ReadStream(fileName);  // get stream from ext. file

            int ch;
            while ((ch = dIn.ReadByte()) >= 0)
            {
                signtr.Update((byte)ch);
            }
            dIn.Close();

        }
        catch (Exception ex)
        {
            return false;
        }
        if (signtr.Verify())
        {
            Console.WriteLine("signature verified.");
            return true;
        }
        else
        {
            Console.WriteLine("signature verification failed.");
            return false;
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM