Parse error reading JWS

I have tried doing this for weeks but i still can't get rid off the error.
What i think is the problem is the signature because i have changed it too many times.
And i have checked on the other posts about this topic bot eather 1. I don't understand. 2. it isn't my problem.

The error comes up when i try to create a new account using pebble
This is my custom made client in C#

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Numerics;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace ACMEClient
{
    class CertDirectorys
    {
		public string newNonce { get; private set; }
		public string newAccount { get; private set; }
		public string newOrder { get; private set; }
		public string newAuthz { get; private set; }
		public string revokeCert { get; private set; }
		public string keyChange { get; private set; }
        public struct metadata
        {
			public string termsOfService;
			public string website;
			public string[] caaIdentities;
			public bool externalAccountRequired;
		}
		public metadata meta;
		public CertDirectorys(string json)
        {
			//Paths
			newNonce = JSON.GetValue(json, "newNonce");
			newAccount = JSON.GetValue(json, "newAccount");
			newOrder = JSON.GetValue(json, "newOrder");
			newAuthz = JSON.GetValue(json, "newAuthz");
			revokeCert = JSON.GetValue(json, "revokeCert");
			keyChange = JSON.GetValue(json, "keyChange");
			//meta
			json = JSON.Navigate(json, "meta");
			json = "{" + json + "}";
			meta.termsOfService = JSON.GetValue(json, "termsOfService");
			meta.website = JSON.GetValue(json, "website");
			meta.externalAccountRequired = JSON.GetValue(json, "externalAccountRequired") == null ? false : bool.Parse(JSON.GetValue(json, "externalAccountRequired"));
			int caaInd = JSON.ElementsIn(json, "caaIdentities");
            if (caaInd != -1)
            {
                meta.caaIdentities = new string[caaInd];
                for (int i = 0; i < caaInd; i++)
                {
                    meta.caaIdentities[i] = JSON.GetValue(json, "caaIdentities[" + i + "]");
                }
            }
        }
    }
    static class Program
    {
        static void Main(string[] args)
        {
            IPAddress iPAddress = Dns.GetHostAddresses(GetHostOfLink(DirPath))[0];  //----IMPORTANT
            TcpClient client = new TcpClient(iPAddress.ToString(), port);
            SslStream stream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(Validatecerts));
            stream.AuthenticateAsClient(iPAddress.ToString(), null, SslProtocols.Tls12, false);
            byte[] buffer = Encoding.UTF8.GetBytes(
                "GET "+GetPathOfLink(DirPath)+" HTTP/1.1\r\n" +
                "Accept-Language: en\r\n" +
                "Host: "+Host+"\r\n" +
                "\r\n"
            );

            stream.Write(buffer, 0, buffer.Length);
            buffer = new byte[8192];
            int size = stream.Read(buffer, 0, 8192);
            string message = Encoding.UTF8.GetString(buffer, 0, size);
			message = message.Substring(message.IndexOf("\r\n\r\n") + 4);
            dirs = new CertDirectorys(message);
            Console.WriteLine(dirs.newNonce);

            string Nonce;
            //Check if already have Nonce
            if (!File.Exists("./nonce.txt"))
            {
                Stream Fstream = File.Create("./nonce.txt");
                Fstream.Close();
            }
            using (StreamReader Fstream = new StreamReader("./nonce.txt"))
            {
                Nonce = Fstream.ReadLine();
            }
            if (Nonce == "" || Nonce == null || true)
            {
                Nonce = getNonce(stream);
                Console.WriteLine("got new nonce: " + Nonce);
                if (Nonce == null)
                {
                    Console.WriteLine("Nonce is not valid");
                    Console.ReadKey();
                }
            }

            //Generate elepric curve for keys
            ECDsaCng dsa = new ECDsaCng();
            dsa.HashAlgorithm = CngAlgorithm.Sha256;
            dsa.KeySize = 256;
            dsa.GenerateKey(ECCurve.NamedCurves.nistP256);
            ECP = dsa.ExportParameters(true);
            
            byte[] Protected = Encoding.UTF8.GetBytes(
                "   {\n" +
                "       \"alg\": \"ES256\",\n" +// ECDSA using P-256 curve and SHA-256 hash algorithm https://openid.net/specs/draft-jones-json-web-signature-04.html#Signing
                "       \"jwk\": {\n" +
                "           \"kty\": \"EC\",\n" +
                "           \"crv\": \"P-256\",\n" +
                "           \"x\": \"" + base64url(dsa.Key.Export(CngKeyBlobFormat.EccPublicBlob).split(8, 32)) + "\",\n" +
                "           \"y\": \"" + base64url(dsa.Key.Export(CngKeyBlobFormat.EccPublicBlob).split(8+32, 32)) + "\"\n" +
                //"           ,\"d\": \"" + base64url(dsa.Key.Export(CngKeyBlobFormat.EccPrivateBlob).split(8+32+32, 32)) + "\"\n" +
                "       },\n" +
                "       \"nonce\": " + Nonce + ",\n" +
                "       \"url\": \"" + dirs.newAccount + "\"\n" +
                "   }\n");

            byte[] Payload = Encoding.UTF8.GetBytes(
                "   {\n" +
                "       \"termsOfServiceAgreed\": true\n" +
                "   }\n");
            /*
             * 
             */
            byte[] signature = Encoding.ASCII.GetBytes(base64url(Protected)+"."+base64url(Payload));// maby need convertion to ascii
            //Encode with ES256
            signature = dsa.SignData(signature, HashAlgorithmName.SHA256);
            string json = 
                "{\n" +
                "   \"payload\": \"" + base64url(Payload) + "\",\n" +
                //"   \"header\": {},"+ //Just to check that the JSON isn't wrong
                "   \"protected\": \"" + base64url(Protected) + "\",\n" +
                "   \"signature\": \"" + base64url(signature) + "\"\n" +
                "}";
            buffer = Encoding.UTF8.GetBytes(
                "POST " + GetPathOfLink(dirs.newAccount) + " HTTP/1.1\r\n" +
                "Host: "+Host+"\r\n" +
                //"Host: letsencrypt.org\r\n" +
                "Content-Type: application/jose+json\r\n" +
                "Content-Length: " + json.Length + "\r\n" +
                "\r\n" + json
            );
            Console.WriteLine(Encoding.UTF8.GetString(buffer, 0, buffer.Length));
            stream.Write(buffer, 0, buffer.Length);
            buffer = new byte[8192];
            size = stream.Read(buffer, 0, 8192);
            message = Encoding.UTF8.GetString(buffer, 0, size);
            Console.WriteLine("---------------------------------------------\r\n"+message);
            Console.ReadKey();
        }
    }
}

What i send

POST /sign-me-up HTTP/1.1
Host: 127.0.0.1
Content-Type: application/jose+json
Content-Length: 635

{
   "payload": "ICAgewogICAgICAgInRlcm1zT2ZTZXJ2aWNlQWdyZWVkIjogdHJ1ZQogICB9Cg",
   "protected": "ICAgewogICAgICAgImFsZyI6ICJFUzI1NiIsCiAgICAgICAiandrIjogewogICAgICAgICAgICJrdHkiOiAiRUMiLAogICAgICAgICAgICJjcnYiOiAiUC0yNTYiLAogICAgICAgICAgICJ4IjogIlBDZkpzbGN3YVJvd1lVVkNIaG8wLWpoNTJ0QTBpQ1lrVjVpQ05QQkZ3czQiLAogICAgICAgICAgICJ5IjogIlJCQ05Mckl5aEQ3RFZEUDR6WG5yU0VubDM1WkxvRlpmSV9paEZGb3BWdTQiCiAgICAgICB9LAogICAgICAgIm5vbmNlIjogZml4U3JTOUw0NUVEWUxCSnlVM0tkZywKICAgICAgICJ1cmwiOiAiaHR0cHM6Ly8xMjcuMC4wLjEvc2lnbi1tZS11cCIKICAgfQo",
   "signature": "UjVCJiyU-I5bNB6Uoi7Ivosh4aqsoDzo-II6bq0ft5WLgK_3wDkqhFGgHdo7mP4yu7-90A5gtATvL3qnbcMzTQ"
}

The error message

HTTP/1.1 400 Bad Request
Cache-Control: public, max-age=0, no-cache
Content-Type: application/problem+json; charset=utf-8
Replay-Nonce: Ivr8UX-_qYOUDZ3gYqdS7g
Date: Sat, 08 Jan 2022 11:45:41 GMT
Content-Length: 111

{
   "type": "urn:ietf:params:acme:error:malformed",
   "detail": "Parse error reading JWS",
   "status": 400
}
2 Likes

I'm not sure you'll get many useful replies with such a short post. Usually this brief of an explanation of the issue with just a whole bunch of code is not the correct way to ask for help.

See for example: How to Properly Ask for Help in Coding | by Jere Xu | Better Programming

4 Likes

I don't realy know what exactly to add but i should add what i have sent and the reply.

POST /sign-me-up HTTP/1.1
Host: 127.0.0.1
Content-Type: application/jose+json
Content-Length: 635

{
   "payload": "ICAgewogICAgICAgInRlcm1zT2ZTZXJ2aWNlQWdyZWVkIjogdHJ1ZQogICB9Cg",
   "protected": "ICAgewogICAgICAgImFsZyI6ICJFUzI1NiIsCiAgICAgICAiandrIjogewogICAgICAgICAgICJrdHkiOiAiRUMiLAogICAgICAgICAgICJjcnYiOiAiUC0yNTYiLAogICAgICAgICAgICJ4IjogIlBDZkpzbGN3YVJvd1lVVkNIaG8wLWpoNTJ0QTBpQ1lrVjVpQ05QQkZ3czQiLAogICAgICAgICAgICJ5IjogIlJCQ05Mckl5aEQ3RFZEUDR6WG5yU0VubDM1WkxvRlpmSV9paEZGb3BWdTQiCiAgICAgICB9LAogICAgICAgIm5vbmNlIjogZml4U3JTOUw0NUVEWUxCSnlVM0tkZywKICAgICAgICJ1cmwiOiAiaHR0cHM6Ly8xMjcuMC4wLjEvc2lnbi1tZS11cCIKICAgfQo",
   "signature": "UjVCJiyU-I5bNB6Uoi7Ivosh4aqsoDzo-II6bq0ft5WLgK_3wDkqhFGgHdo7mP4yu7-90A5gtATvL3qnbcMzTQ"
}
HTTP/1.1 400 Bad Request
Cache-Control: public, max-age=0, no-cache
Content-Type: application/problem+json; charset=utf-8
Replay-Nonce: Ivr8UX-_qYOUDZ3gYqdS7g
Date: Sat, 08 Jan 2022 11:45:41 GMT
Content-Length: 111

{
   "type": "urn:ietf:params:acme:error:malformed",
   "detail": "Parse error reading JWS",
   "status": 400
}
2 Likes

Based on your openings post (OP):

  • I have no idea what you're trying to do;
  • I have no idea what setup you're using;
  • I have to guess the coding language based on the code you've pasted;
  • You've only pasted 4 words of the error message in the threads title;
  • There is no context around the error message, no details what so ever.
  • I cannot see any effort of debugging the issue from your end. Maybe you have done hours or research, but please let us know how you did that and what the results of those hours or researching this issue were.

Please also see threads like: How do I ask a good question? - Help Center - Stack Overflow

4 Likes

i have added some new info on the original post

1 Like

What i have tested is changed because i realised that it was a vialation of the standard.

2 Likes

What have you tried already to debug this yourself?

3 Likes

I have tried different formats on the signature header like
"signature": base64url(protected)+'.'+base64url(payload)+'.'+base64url(signature)
But i think that is just wrong and i didn't even know what the signature whuld be here.
And right now i am using ECDsaCng.SignData() to sign the signature and have this
"signature": base64url(signature)
instead.
signature = dsa.SignData( base64url(Protected)+"."+base64url(Payload), SHA256)

2 Likes

Did you put the value of the nonce in double-quotes?

7 Likes

You are correct but i do not like that.
It works now but i will live in shame for making that mistake.

4 Likes

Do not live in shame because of that, please do not be so harsh towards yourself. Everybody does mistake and that is human.

5 Likes

I thought they were making a joke but just in case they were not I agree with you

5 Likes

Speek 4 yurslef.
I nver maek misstaks!

LOL

5 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.