What does <Parse error reading JWS> exactly mean?

No

I print the json.dumps(payload)

Get this

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

That looks much better. :slightly_smiling_face:

You even got the email array correct.

but it is still get the same error response

Let's see... :thinking:

You only use PHP ?

Or you also use python ?

Only PHP. Nothing else.

This function is not producing correct base64url encoding.

Try using url64.encode instead (as with the signature).

1 Like

Is this:

base64.urlsafe_b64encode(json.dumps(protected_header))

converting (+ -> -) and (/ -> _) ?

So I was on target! :stuck_out_tongue:

It doesn't work.....

What's the current state?

I've moved the thread to the Client dev, which is more appropriate IMO.

1 Like

Absolutely right. :wink:

What doesn't work? I tried changing your program with that exact change, and the parse error is gone:

{'Strict-Transport-Security': 'max-age=604800', 'Server': 'nginx', 'Connection': 'keep-alive', 'Link': '<https://acme-staging-v02.api.letsencrypt.org/directory>;rel="index"', 'Cache-Control': 'public, max-age=0, no-cache', 'Date': 'Fri, 11 Dec 2020 09:05:36 GMT', 'X-Frame-Options': 'DENY', 'Replay-Nonce': '0003HnIFgBGglxRQ5-8oTG2jR30zha5IlAPhs0aBvQL-urA'}
Nonce is: 0003HnIFgBGglxRQ5-8oTG2jR30zha5IlAPhs0aBvQL-urA
{'protected': u'eyJub25jZSI6ICJNREF3TTBodVNVWm5Ra2RuYkhoU1VUVXRPRzlVUnpKcVVqTXdlbWhoTlVsc1FWQm9jekJoUW5aUlRDMTFja0UiLCAiYWxnIjogIkVTMjU2IiwgInVybCI6ICJodHRwczovL2FjbWUtc3RhZ2luZy12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL25ldy1hY2N0In0', 'payload': u'eyJ0ZXJtc09mU2VydmljZUFncmVlZCI6IHRydWUsICJjb250YWN0IjogWyJtYWlsdG86dGVzdF9tYWlsX25ld0BzaW5hLmNvbSJdfQ'}
{"payload":"eyJ0ZXJtc09mU2VydmljZUFncmVlZCI6IHRydWUsICJjb250YWN0IjogWyJtYWlsdG86dGVzdF9tYWlsX25ld0BzaW5hLmNvbSJdfQ","protected":"eyJ0ZXJtc09mU2VydmljZUFncmVlZCI6IHRydWUsICJjb250YWN0IjogWyJtYWlsdG86dGVzdF9tYWlsX25ld0BzaW5hLmNvbSJdfQ","signature":"kDvWyaUmvNkaE6O6RBfDzMf1kThGYmUx4eP_dxd33zrNudhlA6f6ejTV9zQ-cjz5Eb4OwSPj2ybvKjrDBMR_6A"}
=======req=======
{'payload': u'eyJ0ZXJtc09mU2VydmljZUFncmVlZCI6IHRydWUsICJjb250YWN0IjogWyJtYWlsdG86dGVzdF9tYWlsX25ld0BzaW5hLmNvbSJdfQ',
'protected': u'eyJub25jZSI6ICJNREF3TTBodVNVWm5Ra2RuYkhoU1VUVXRPRzlVUnpKcVVqTXdlbWhoTlVsc1FWQm9jekJoUW5aUlRDMTFja0UiLCAiYWxnIjogIkVTMjU2IiwgInVybCI6ICJodHRwczovL2FjbWUtc3RhZ2luZy12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL25ldy1hY2N0In0',
'signature': u'eyJwYXlsb2FkIjoiZXlKMFpYSnRjMDltVTJWeWRtbGpaVUZuY21WbFpDSTZJSFJ5ZFdVc0lDSmpiMjUwWVdOMElqb2dXeUp0WVdsc2RHODZkR1Z6ZEY5dFlXbHNYMjVsZDBCemFXNWhMbU52YlNKZGZRIiwicHJvdGVjdGVkIjoiZXlKMFpYSnRjMDltVTJWeWRtbGpaVUZuY21WbFpDSTZJSFJ5ZFdVc0lDSmpiMjUwWVdOMElqb2dXeUp0WVdsc2RHODZkR1Z6ZEY5dFlXbHNYMjVsZDBCemFXNWhMbU52YlNKZGZRIiwic2lnbmF0dXJlIjoia0R2V3lhVW12TmthRTZPNlJCZkR6TWYxa1RoR1ltVXg0ZVBfZHhkMzN6ck51ZGhsQTZmNmVqVFY5elEtY2p6NUViNE93U1BqMnlidktqckRCTVJfNkEifQ'}
========response========
{'Content-Length': '114', 'Server': 'nginx', 'Connection': 'keep-alive', 'Link': '<https://acme-staging-v02.api.letsencrypt.org/directory>;rel="index"', 'Cache-Control': 'public, max-age=0, no-cache', 'Date': 'Fri, 11 Dec 2020 09:05:37 GMT', 'Content-Type': 'application/problem+json', 'Replay-Nonce': '0004QvKnZI77i7CzD24uKbbEfz9hERhkz5AI8aXLMC-mbC8'}
{u'status': 400, u'type': u'urn:ietf:params:acme:error:malformed', u'detail': u'No embedded JWK in JWS header'}

You have other errors now that you need to deal with, but that's not surprising.

1 Like

Now is this one:

Get the same error

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": url64.encode(json.dumps(protected_header)),
    "payload": url64.encode(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()

Oh, it is so sad....

@_az

I said this earlier and it got fixed lower down. You're using the older code, I think. Do you get the same result from the tip code two posts above?

How about the signature method ?

Is it correct ?

I do this:

openssl_sign("$protected.$payload", $signature, $this->accountPrivateKeyPEM, "sha256WithRSAEncryption")

have you got the correct response?