# What does \<Parse error reading JWS\> exactly mean?

**URL:** <https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319>\
**Category:** Client dev\
**Created:** [December 11, 2020, 7:45am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319 "2020-12-11T07:45:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 7:45am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/1 "2020-12-11T07:45:45Z")

</div>

send req to  
[https://acme-staging-v02.api.letsencrypt.org/acme/new-acct](https://acme-staging-v02.api.letsencrypt.org/acme/new-acct)

get response: Parse error reading JWS

Is it means that my request format is wrong ?  
or  
Signature is incorrect ?

---

<div class="post-metadata">

**Author:** ![webprofusion](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/webprofusion/32/85310_2.png) [@webprofusion](https://community.letsencrypt.org/u/webprofusion)\
**Post date:** [December 11, 2020, 8:19am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/2 "2020-12-11T08:19:07Z")

</div>

You'd need to share an example posted message but as far as I know when boulder deserializes your JWS it expects certain fields to be in a specific order or the values may have the wrong encoding

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:23am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/3 "2020-12-11T08:23:38Z")

</div>

here is example:

```python

import requests
import url64
import json
import base64
from jwcrypto import jwk, jws
from jwcrypto.common import json_encode
from pprint import pprint as pp

#
# HEAD newNonce
#
resp = requests.head('https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce')
pp(resp.headers)
replay_nonce = resp.headers['Replay-Nonce']
print 'Nonce is:'
pp(replay_nonce)

session = requests.Session()
session.headers.update({'Content-Type': 'application/jose+json'})

protected_header = {
        "alg": "ES256",
        "nonce": url64.encode(replay_nonce),
        "url": "https://acme-staging-v02.api.letsencrypt.org/acme/new-acct",
}

payload = {
    "termsOfServiceAgreed": True,
    "contact": [
        "mailto:test_mail_new@sina.com"
    ]
}

req = {
    "protected": base64.urlsafe_b64encode(json.dumps(protected_header)),
    "payload": base64.urlsafe_b64encode(json.dumps(payload)),
}

print req

key = jwk.JWK.generate(kty='EC')

jwstoken = jws.JWS(json.dumps(payload))

jwk_param = key.export()

jwstoken.add_signature(
    key,
    'ES256',
    json.dumps(payload),
    # header=header,
    # json_encode({"kid": key.thumbprint()})
)
sig = jwstoken.serialize()

print sig

req.update({"signature": url64.encode(sig)})

print '=======req======='
pp(req)

resp = session.post(
    url='https://acme-staging-v02.api.letsencrypt.org/acme/new-acct',
    json=req,
)

print '========response========'
print resp.headers
print resp.json()

```

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 11, 2020, 8:29am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/4 "2020-12-11T08:29:50Z")

</div>

Why is your JWK not in your protected header?

You shouldn't need to urlencode the nonce.

You should be using the URL endpoints from the directory rather than hardcoding them.

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:34am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/5 "2020-12-11T08:34:45Z")

</div>

this one is also get the same error response

> [@test\_mail\_new](#):
>
> ```nohighlight
> import requests
> import url64
> import json
> import base64
> from jwcrypto import jwk, jws
> from jwcrypto.common import json_encode
> from pprint import pprint as pp
> 
> #
> # HEAD newNonce
> #
> resp = requests.head('https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce')
> pp(resp.headers)
> replay_nonce = resp.headers['Replay-Nonce']
> print 'Nonce is:'
> pp(replay_nonce)
> 
> session = requests.Session()
> session.headers.update({'Content-Type': 'application/jose+json'})
> 
> key = jwk.JWK.generate(kty='EC')
> jwk_param = key.export()
> 
> protected_header = {
> "alg": "ES256",
> "nonce": replay_nonce,
> "url": "https://acme-staging-v02.api.letsencrypt.org/acme/new-acct",
> "jwk": jwk_param
> }
> 
> payload = {
> "termsOfServiceAgreed": True,
> "contact": [
> "mailto:test_mail_new@sina.com"
> ]
> }
> 
> req = {
> "protected": base64.urlsafe_b64encode(json.dumps(protected_header)),
> "payload": base64.urlsafe_b64encode(json.dumps(payload)),
> }
> 
> print req
> 
> jwstoken = jws.JWS(json.dumps(payload))
> 
> jwstoken.add_signature(
> key,
> 'ES256',
> json.dumps(payload),
> # header=header,
> # json_encode({"kid": key.thumbprint()})
> )
> sig = jwstoken.serialize()
> 
> print sig
> 
> req.update({"signature": url64.encode(sig)})
> 
> print '=======req======='
> pp(req)
> 
> resp = session.post(
> url='https://acme-staging-v02.api.letsencrypt.org/acme/new-acct',
> json=req,
> )
> 
> print '========response========'
> print resp.headers
> print resp.json()
> 
> ```

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 11, 2020, 8:36am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/6 "2020-12-11T08:36:34Z")

</div>

What contains `jwk_param` exactly?

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:36am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/7 "2020-12-11T08:36:53Z")

</div>

> [@griffin](#):
>
> You should be using the URL endpoints from the directory rather than hardcoding them.

What is this mean?

In this example

I think URL endpoints is "[https://acme-staging-v02.api.letsencrypt.org/acme/new-acct](https://acme-staging-v02.api.letsencrypt.org/acme/new-acct)"

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:37am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/8 "2020-12-11T08:37:30Z")

</div>

{"crv":"P-256","d":"sM-GxMaDA\_J6mYkoH5M1wSDoLGoNw0oDeL4HlnINDBM","kty":"EC","x":"MBY9WUbM7yJ3HXEJgWNtFfPw-AGCTATgBJEyltYUmoM","y":"ycTOtaTzMP5w1v3b\_KSsnxZF9OVMZ8y6WuldZwM0RXk"}

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 11, 2020, 8:37am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/9 "2020-12-11T08:37:49Z")

</div>

It is, but you shouldn't be hardcoding the URL into your code. It's OK for testing in the shortrun though.

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:38am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/10 "2020-12-11T08:38:23Z")

</div>

Ok, I see.

This is testing code.

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 11, 2020, 8:39am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/11 "2020-12-11T08:39:21Z")

</div>

This looks fine.

Why are you reencoding the nonce though?

What is the value of `url64.encode(replay_nonce)`?

What is the value of `replay_nonce`?

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:41am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/12 "2020-12-11T08:41:05Z")

</div>

Fixed this just then.

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 11, 2020, 8:41am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/13 "2020-12-11T08:41:44Z")

</div>

What's the code look like now?

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:43am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/14 "2020-12-11T08:43:15Z")

</div>

```python
import requests
import url64
import json
import base64
from jwcrypto import jwk, jws
from jwcrypto.common import json_encode
from pprint import pprint as pp

#
# HEAD newNonce
#
resp = requests.head('https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce')
pp(resp.headers)
replay_nonce = resp.headers['Replay-Nonce']
print 'Nonce is:'
pp(replay_nonce)

session = requests.Session()
session.headers.update({'Content-Type': 'application/jose+json'})

key = jwk.JWK.generate(kty='EC')
jwk_param = key.export()

protected_header = {
        "alg": "ES256",
        "nonce": replay_nonce,
        "url": "https://acme-staging-v02.api.letsencrypt.org/acme/new-acct",
        "jwk": jwk_param
}

payload = {
    "termsOfServiceAgreed": True,
    "contact": [
        "mailto:test_mail_new@sina.com"
    ]
}

req = {
    "protected": base64.urlsafe_b64encode(json.dumps(protected_header)),
    "payload": base64.urlsafe_b64encode(json.dumps(payload)),
}

print req

jwstoken = jws.JWS(json.dumps(payload))

jwstoken.add_signature(
    key,
    'ES256',
    json.dumps(payload),
    # header=header,
    # json_encode({"kid": key.thumbprint()})
)
sig = jwstoken.serialize()

print sig

req.update({"signature": url64.encode(sig)})

print '=======req======='
pp(req)

resp = session.post(
    url='https://acme-staging-v02.api.letsencrypt.org/acme/new-acct',
    json=req,
)

print '========response========'
print resp.headers
print resp.json()

```

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:43am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/15 "2020-12-11T08:43:31Z")

</div>

And with same error response.

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 11, 2020, 8:45am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/16 "2020-12-11T08:45:17Z")

</div>

I'm wondering if your True gets converted properly.

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:48am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/17 "2020-12-11T08:48:04Z")

</div>

> [@test\_mail\_new](#):
>
> ```nohighlight
> payload = {
> "termsOfServiceAgreed": True,
> "contact": [
> "mailto:test_mail_new@sina.com"
> ]
> }
> 
> ```

this one???

payload = {  
"termsOfServiceAgreed": 'true',  
"contact": [  
"[mailto:test\_mail\_new@sina.com](mailto:test_mail_new@sina.com)"  
]  
}

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 11, 2020, 8:48am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/18 "2020-12-11T08:48:40Z")

</div>

that's a bug...

should be:  
{"termsOfServiceAgreed":true}

in the output

---

<div class="post-metadata">

**Author:** ![test\_mail\_new](https://avatars.discourse-cdn.com/v4/letter/t/97f17d/32.png) [@test\_mail\_new](https://community.letsencrypt.org/u/test_mail_new)\
**Post date:** [December 11, 2020, 8:49am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/19 "2020-12-11T08:49:36Z")

</div>

This is Python.

bool value true is "True" , bool value false is "False".

not like javascript.

---

<div class="post-metadata">

**Author:** ![griffin](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/griffin/32/50204_2.png) [@griffin](https://community.letsencrypt.org/u/griffin)\
**Post date:** [December 11, 2020, 8:50am UTC](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319/20 "2020-12-11T08:50:00Z")

</div>

Right, but JSON is a Javascript format

My own client is in PHP.

When I json\_encode this:  
[  
"termsOfServiceAgreed" =\> true  
]

I get this:  
{"termsOfServiceAgreed":true}

I'm not sure if it parses the same. I know booleans are a big source of headaches for JSON encoding.

[Next page](https://community.letsencrypt.org/t/what-does-parse-error-reading-jws-exactly-mean/140319.md?page=2)
