0

I have a zip file which I'm signing using c# code with Bouncy castle. The generated signature file is identical ( I have compared output string as well as binary code) to signature file generated with openssl using following command

openssl dgst -sha256 -sign content_private_key.pem -out content.zip.sig content.zip

But when I verify signature file (generated using c# code) using openssl it shows "Verification Failure error in dgst" error. Whereas signature file generated using openssl gets verified successfully.

Command I'm using for verification is

openssl dgst -sha256 -verify content_public_key.pem -signature content.zip.sig content.zip 

openssl output

What could be the issue ?

Here is the C# code I'm using to sign the data

    /// <summary>
    /// Method to generate signature file
    /// </summary>
    private void GenerateSignatureFile(string sourceFile)
    {
        try
        {
            var bytesToSign = File.ReadAllBytes(sourceFile);
            var sig = Sign(bytesToSign);

            var fileContent = Encoding.GetEncoding(1252).GetString(sig);

            using (var sw = File.CreateText(Path.Combine(_projectLocation, _sigFileName)))
            {
                sw.Write(fileContent);
            }

        }
        catch (Exception ex)
        {
            LoggingService.Log(ex.Message);
            var errorWhileCreatingSignatureFile = Resource.ResourceManager.GetString("ErrorWhileCreatingSignatureFile");
            throw new Exception(errorWhileCreatingSignatureFile, ex);
        }
    }


    public byte[] Sign(byte[] bytes)
    {
        var key = ReadPrivateKey();
        /* Make the key */
        var keyParameter = new RsaKeyParameters(key.IsPrivate, ((RsaPrivateCrtKeyParameters)key).Modulus, ((RsaPrivateCrtKeyParameters)key).Exponent);

        /* Init alg */
        ISigner sig = SignerUtilities.GetSigner("SHA256withRSA");

        /* Populate key */
        sig.Init(true, key);

        /* Calc the signature */
        sig.BlockUpdate(bytes, 0, bytes.Length);
        return sig.GenerateSignature();

    }


    private AsymmetricKeyParameter ReadPrivateKey()
    {
        AsymmetricCipherKeyPair keyPair;

        using (var reader = new StringReader(_privateKey))
            keyPair = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject();

        return keyPair.Private;
    }
  • _The generated signature file is identical to signature file generated with openssl_ If files were identical then verification will work in both cases – pedrofb Jul 17 '17 at 06:07
  • That's the point. But is not working @pedrofb – Mohit Singh Bora Jul 17 '17 at 06:37
  • Since digital.signature verification is deterministic it means thay files are not equal. Look for diferences. And show your code so people could analyze it – pedrofb Jul 17 '17 at 06:45
  • Okay @pedrofb I've added the c# code. – Mohit Singh Bora Jul 17 '17 at 06:50
  • I am not expert in c# but seems `File.CreateText` creates a text file and the signature is binary. Probably is adding some extra character – pedrofb Jul 17 '17 at 06:54
  • @pedrofb I have compared the text of both files and it is exactly same. I tried with binary file also but it generates completely different text. – Mohit Singh Bora Jul 17 '17 at 07:59
  • How are you comparing the files? Note that they aren't text files so you can not compare with a text editor. Remove also this `var fileContent = Encoding.GetEncoding(1252).GetString(sig)` if you did not do yet – pedrofb Jul 17 '17 at 08:18
  • @pedrofb what is wrong in this line var fileContent = Encoding.GetEncoding(1252).GetString(sig). I'm using it to convert byte array to ANSI encoding. – Mohit Singh Bora Jul 18 '17 at 04:28
  • 1252 is a Text Encoding. You can not apply it to binary data because it contains non-representable characters – pedrofb Jul 18 '17 at 05:45
  • @pedrofb I tried converting byte array generated by Bouncy castle to binary text and wrote it in a file using BinaryWriter but file generated then is completely different from file generated by Openssl. Whereas my present code is generating completely identical file. Now I'm skeptical about if it is related to this line var fileContent = Encoding.GetEncoding(1252).GetString(sig) or about File.CreateText. – Mohit Singh Bora Jul 19 '17 at 07:12
  • As I said before, I am not a C# programmer to provide you an accurate answer. But I can say that a signature result of type byte[] is binary and not text. Any attempt to apply a text encoding in any language will produce unexpected results. You have an issue saving binary data to file. Please try the code answered here https://stackoverflow.com/questions/381508/can-a-byte-array-be-written-to-a-file-in-c. For example `File.WriteAllBytes(string path, byte[] bytes)` – pedrofb Jul 19 '17 at 07:18
  • @pedrofb It is also generating different result. Seems like issue could be something else. – Mohit Singh Bora Jul 19 '17 at 07:32
  • Ok, write the solution when you find it! – pedrofb Jul 19 '17 at 07:33
  • @pedrofb ohhhh It worked. Thanks a lot. – Mohit Singh Bora Jul 19 '17 at 07:42
  • Are you finally using `File.WriteAllBytes`. I will write a summary as answer – pedrofb Jul 19 '17 at 07:53
  • yes I'm using File.WriteAllBytes. – Mohit Singh Bora Jul 19 '17 at 08:04

1 Answers1

0

[Solution in comments]

If files were identical then verification will work in both cases because digital signature verification is deterministic. It means that files are not equal.

A signature result of type byte[] is binary and not text. Any attempt to apply a text encoding in any language will produce unexpected results because it contains non-representable characters

You have an issue saving binary data to file here

  var fileContent = Encoding.GetEncoding(1252).GetString(sig);

  using (var sw = File.CreateText(Path.Combine(_projectLocation, _sigFileName)))

Change it with

 File.WriteAllBytes(string path, byte[] bytes)
pedrofb
  • 37,271
  • 5
  • 94
  • 142