# Account Key Roll-over : Parse error reading JWS

**URL:** <https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305>\
**Category:** Client dev\
**Created:** [October 1, 2017, 4:53am UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305 "2017-10-01T04:53:41Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![anindya](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/anindya/32/27017_2.png) [@anindya](https://community.letsencrypt.org/u/anindya)\
**Post date:** [October 1, 2017, 4:53am UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/1 "2017-10-01T04:53:41Z")

</div>

I am writing a client for Account Key Roll-over. I followed this docs [https://ietf-wg-acme.github.io/acme/draft-ietf-acme-acme.html#rfc.section.7.3.6](https://ietf-wg-acme.github.io/acme/draft-ietf-acme-acme.html#rfc.section.7.3.6) and this one [https://tools.ietf.org/html/draft-ietf-acme-acme-06#section-7.3.3](https://tools.ietf.org/html/draft-ietf-acme-acme-06#section-7.3.3)

I am posting the following data to /acme/key-change

`{"header":{"alg":"RS256","kid":"https:\/\/acme-v01.api.letsencrypt.org\/acme\/reg\/21941027","jwk":{"kty":"RSA","n":"smmXFfmi_e2vb1QKC9LTFEsYwbKT2csLPENgqTREEqGpQ90117TJyYFA3n6qWwl9PDfG6y4AYhs38PA4DE5dKXiwmiyWua6a7r9-iOz9F1EvckuNSU_OFYcSJvT9WTwDfWydoJBYKOhDl0ev_Jr9UWKGfWdUN_sy1sKV6skymq0DO1_6sIcE7uPiH06PPt28_5YPumTYhK8LX9_pMTJy5gkfgYa3Lty8AecZSBY2hJ4TbmQ5hRq7WZnm5xEnukemGHPDSC_E4zrDB0hZDVNP2okxxWGLlD1nwoO3opL3IxLF7EUyqRO4bwJr5wmkHdiswZBIoJxEKXujIlcNScjjmJLPgc8Z8tC3d9SJ1i_VJssXK3yqQYK1Wfnka5yLm0R-N5l-hgrvES_ZfAvUi4jvj4Q-AUJb0r-pepzw6hRZdVldIUT5NpobfBkuw6jgtlPNSK4JpXckrVpZXVrs4zNFg_wn7MdECtimDB2Kk6681swSoPuNx76D_Jx8q86h6CbwVvESTslB0eHTEMlG9MyGbrdjHHD69pAAVoRMwHEtDlj3tta_u0-rYt_BgNsM6fM_oNcfEx-RufF83ZeTe9cvF5yXZr1Egx7srH0SOSzgb6A1lTyEAJuhQBRnbWHw1xbzloRFZmkxbCra2o4XYkl0RaOX4I_4G80_TarBUBEh_3k","e":"AQAB"}},"protected":"eyJhbGciOiJSUzI1NiIsImtpZCI6Imh0dHBzOlwvXC9hY21lLXYwMS5hcGkubGV0c2VuY3J5cHQub3JnXC9hY21lXC9yZWdcLzIxOTQxMDI3IiwiandrIjp7Imt0eSI6IlJTQSIsIm4iOiJzbW1YRmZtaV9lMnZiMVFLQzlMVEZFc1l3YktUMmNzTFBFTmdxVFJFRXFHcFE5MDExN1RKeVlGQTNuNnFXd2w5UERmRzZ5NEFZaHMzOFBBNERFNWRLWGl3bWl5V3VhNmE3cjktaU96OUYxRXZja3VOU1VfT0ZZY1NKdlQ5V1R3RGZXeWRvSkJZS09oRGwwZXZfSnI5VVdLR2ZXZFVOX3N5MXNLVjZza3ltcTBETzFfNnNJY0U3dVBpSDA2UFB0MjhfNVlQdW1UWWhLOExYOV9wTVRKeTVna2ZnWWEzTHR5OEFlY1pTQlkyaEo0VGJtUTVoUnE3V1pubTV4RW51a2VtR0hQRFNDX0U0enJEQjBoWkRWTlAyb2t4eFdHTGxEMW53b08zb3BMM0l4TEY3RVV5cVJPNGJ3SnI1d21rSGRpc3daQklvSnhFS1h1aklsY05TY2pqbUpMUGdjOFo4dEMzZDlTSjFpX1ZKc3NYSzN5cVFZSzFXZm5rYTV5TG0wUi1ONWwtaGdydkVTX1pmQXZVaTRqdmo0US1BVUpiMHItcGVwenc2aFJaZFZsZElVVDVOcG9iZkJrdXc2amd0bFBOU0s0SnBYY2tyVnBaWFZyczR6TkZnX3duN01kRUN0aW1EQjJLazY2ODFzd1NvUHVOeDc2RF9KeDhxODZoNkNid1Z2RVNUc2xCMGVIVEVNbEc5TXlHYnJkakhIRDY5cEFBVm9STXdIRXREbGozdHRhX3UwLXJZdF9CZ05zTTZmTV9vTmNmRXgtUnVmRjgzWmVUZTljdkY1eVhacjFFZ3g3c3JIMFNPU3pnYjZBMWxUeUVBSnVoUUJSbmJXSHcxeGJ6bG9SRlpta3hiQ3JhMm80WFlrbDBSYU9YNElfNEc4MF9UYXJCVUJFaF8zayIsImUiOiJBUUFCIn0sIm5vbmNlIjoiTGl2S2tFTjBHWHRPZFU5QnpwN0VKVVlYbnRhUFVlbWN4Z1dUeVduTUhjdyIsInVybCI6Imh0dHBzOlwvXC9hY21lLXYwMS5hcGkubGV0c2VuY3J5cHQub3JnXC9hY21lXC9rZXktY2hhbmdlIn0","payload":"eyJyZXNvdXJjZSI6ImtleS1jaGFuZ2UiLCJwcm90ZWN0ZWQiOiJleUpoYkdjaU9pSlNVekkxTmlJc0ltcDNheUk2ZXlKcmRIa2lPaUpTVTBFaUxDSnVJam9pZFdWVmNYaHNVRzFoWDAxaE5HcGlOMFpETTFwdVZETmxhRXR0TjB0eU4zZFNZV3BmV2poQ2FrOUxjVVJET0ZBMVFWVkdaRU5TVkhOVlVqUk5hbE5PYWs1UmRVMVZhazh3U0hOd1JVSm9lRzh4YWpOSFdGOVdTbnBUY1cxMWF6Qkpka1YyTkcxbVNtazJjVlZUWWw5VmFEbHdUbmx3Y25JMlluZHFVMGh2TTFKWWQwczJkVVZmVUc5UU56STBSa1kxZW5oNFMySkZRbTlRZEdwclNGZEpXblJmWDBsVVpUTlpOR2d5UWpCTmNIUlZPRmN5VVZkZlJtZHBOM0F5VVhSME5YcEVlbVZIVHpKSWN6VnNaMFJIYkUxVWJESnZTamhhUlZWVmRIZFlZMU5YV1RoV1YySnpTVEY2WjI1bE9XNWphbTB3UXpOdmNqTnhOa1oyZUROUWRGQTJTMXBEUW5SUVVVcFRTMmRpWDBnd01tTmtNREF5VDBwaWVURldRV1IxT1VWTE9HOVhkbUV3WW5OeFdrZERMVkEwWTBKMVVIZENSbWhvVjA1bGVrNXVTbmRqVUhKcVdGTXlNWFJ4TFZBdFJFWjFiREpOVldnMVoyeDJUV1J2WkVjMlJHaExhbUZEVFRWT1pUTmFaREJvUWpGaFJIbHBhelV4UVY5VldrODBjbFJPVVRKVkxUTXpaM0UyVlU5TGVraDBVRFZNVjBWS00wWnJaMVJVZDJWR2JGTjVVVjkyTVhkcVUwZEZaRnBUTWs1S1R6SndUakkyWTAwd2VVWTNkbWhaVUU0M2EzaE5kRE4zUjNCQk1tbEVSa1pGYW1KRmNXOUhZMmxNTUY5NVFrbzNOa1pXUm5oNmNuQmxZbGREWkZaamRVeGlNVGhTYlZSdWNUWlNlbXB2ZFRSMmJIUm5VbVZCVUdwRVdqZzBTRTFIU1V4VFlrSlhkbFphZW5FMGR5MVpRa0pFWjFOd1NFeEJWMGxWT0ZobFdEbHpRMmxwT1c5Q2QwNUhObWhhV2s1c2QwWm9iR2xHWlVOMWVtdHpVemhGTTFwTlNHOHlSbGRFVlRWVmFsTjFSWEZrUTJ0S1ltcERMVWcyUVhkVk9IUXpka2d4TUhKc2MzZE5Wa1ZhZVRRNGNIY3pTMHc0TkRnNGFHWnZNVk5DWTNoT1pscHhZWGxGVFRObk0wY3hSa0Y0YlRVNWVEazJhbFVpTENKbElqb2lRVkZCUWlKOUxDSjFjbXdpT2lKb2RIUndjenBjTDF3dllXTnRaUzEyTURFdVlYQnBMbXhsZEhObGJtTnllWEIwTG05eVoxd3ZZV050WlZ3dmEyVjVMV05vWVc1blpTSjkiLCJwYXlsb2FkIjoiZXlKaFkyTnZkVzUwSWpvaWFIUjBjSE02WEM5Y0wyRmpiV1V0ZGpBeExtRndhUzVzWlhSelpXNWpjbmx3ZEM1dmNtZGNMMkZqYldWY0wzSmxaMXd2TWpFNU5ERXdNamNpTENKdVpYZExaWGtpT25zaWEzUjVJam9pVWxOQklpd2liaUk2SW5WbFZYRjRiRkJ0WVY5TllUUnFZamRHUXpOYWJsUXpaV2hMYlRkTGNqZDNVbUZxWDFvNFFtcFBTM0ZFUXpoUU5VRlZSbVJEVWxSelZWSTBUV3BUVG1wT1VYVk5WV3BQTUVoemNFVkNhSGh2TVdvelIxaGZWa3A2VTNGdGRXc3dTWFpGZGpSdFprcHBObkZWVTJKZlZXZzVjRTU1Y0hKeU5tSjNhbE5JYnpOU1dIZExOblZGWDFCdlVEY3lORVpHTlhwNGVFdGlSVUp2VUhScWEwaFhTVnAwWDE5SlZHVXpXVFJvTWtJd1RYQjBWVGhYTWxGWFgwWm5hVGR3TWxGMGREVjZSSHBsUjA4eVNITTFiR2RFUjJ4TlZHd3liMG80V2tWVlZYUjNXR05UVjFrNFZsZGljMGt4ZW1kdVpUbHVZMnB0TUVNemIzSXpjVFpHZG5nelVIUlFOa3RhUTBKMFVGRktVMHRuWWw5SU1ESmpaREF3TWs5S1lua3hWa0ZrZFRsRlN6aHZWM1poTUdKemNWcEhReTFRTkdOQ2RWQjNRa1pvYUZkT1pYcE9ia3AzWTFCeWFsaFRNakYwY1MxUUxVUkdkV3d5VFZWb05XZHNkazFrYjJSSE5rUm9TMnBoUTAwMVRtVXpXbVF3YUVJeFlVUjVhV3MxTVVGZlZWcFBOSEpVVGxFeVZTMHpNMmR4TmxWUFMzcElkRkExVEZkRlNqTkdhMmRVVkhkbFJteFRlVkZmZGpGM2FsTkhSV1JhVXpKT1NrOHljRTR5Tm1OTk1IbEdOM1pvV1ZCT04ydDRUWFF6ZDBkd1FUSnBSRVpHUldwaVJYRnZSMk5wVERCZmVVSktOelpHVmtaNGVuSndaV0pYUTJSV1kzVk1ZakU0VW0xVWJuRTJVbnBxYjNVMGRteDBaMUpsUVZCcVJGbzRORWhOUjBsTVUySkNWM1pXV25weE5IY3RXVUpDUkdkVGNFaE1RVmRKVlRoWVpWZzVjME5wYVRsdlFuZE9SelpvV2xwT2JIZEdhR3hwUm1WRGRYcHJjMU00UlROYVRVaHZNa1pYUkZVMVZXcFRkVVZ4WkVOclNtSnFReTFJTmtGM1ZUaDBNM1pJTVRCeWJITjNUVlpGV25rME9IQjNNMHRNT0RRNE9HaG1iekZUUW1ONFRtWmFjV0Y1UlUwelp6TkhNVVpCZUcwMU9YZzVObXBWSWl3aVpTSTZJa0ZSUVVJaWZYMCIsInNpZ25hdHVyZXMiOiJqeVlWSTR5MWcxekExbGZqMDN3UkRoa1llYWp2LUpsMXUydnFzSk8yenFEamlxRVdBNVNLRGQtOHJvc0prYktWNUI3SDBPMjBDVlYxUnFjMmJ0Z2RkWVZaQ3hjcExTVFBMUlhOWTFGbWNEellZclpCSWUyVjlseVpIVjJSYU9CU2kxNmIycWVVT015Q3g3YzRpb0hUZGlPX1AxcVlYUlVPcnZBM1FzeEtRTml3aWFvemxJa0xjcjhuM0NZbU10eUxOWU9hTFJUS1ZMTlhmRFBxSDBhWElaNl90aUdGU3VkNzVRXzBNXzVaZzJuclR2aXR4VzVHSEh4Ml9WTkVRSExlRzFuSjVGWWZNblltOGhDejhkYnBXZGFrUGZoV0ttNXlGUWswbHFORjZoLUo3NENjVk5DNzg5ZDBlNFU3WG14UHBSbHpIWnFtZlBoeGVBcmpUV2w5UWJtb18wSEJuLS10THkzWUk5T0N6cW4yWjQxSUtDeDZyc1hGcndVZGpDWDdFamlPT1U5bHRyY20zbnM0RVJxZWd2TXpMRFFOZldkaDhfNGtDZ0x2Wl9GejAxOTZBM2VkdGV3MzN5SV9mSEpzM3pZcERsREZ3d0NzN2hoenN5OVJSLUIyS1VqLV9HQVZNaXF3UVM3VGpIMzNKZFVLcWhZWXBidkRPS0w3NGFUbGVMR1hVTXI1dXhqVmNUMHBuQVJKdWtHX2lJLW9jYTRONmxnQkhnckRmMk4tTl9VdjNiOS1mLWVXUWhRQ3ZQWEI2b1o5Z1lvM2pLY0dHSm9VUmpyZFM2YnBVaHlJZUNwaU1mSjFMMjhNUmQ2aTZQRS15dHpDOGtITlVWbExKbk4wclRzLTRYYUhDbVdBZmhMbUQ4Zkt5SllrT0dxYThYWUJGcG5HTFMxdUNxNCJ9","signature":"CAFtV9fs2Wk74iJ5ZHqm55mS8eP0ri8JeRMH8CxqaapMEUAX0ayTWEesWtaoA1QMVqs7qzyYhaNSc-OBrblFXClAOuct6BcCH2am597ugEoHdnXSy1aLERdw9afpPDfMXeV5ZQR2VmiWFBC_ECcS7Zt3k0FqcSL3gQFwQDFXVcrsyN7CQiUyHloCrGfXcTmYMN_fUcwebGUeg8etKTTjF5C2SO0N5t6XXQtTLedqOS3lK3UiHxKnWdWfsBzKnVja5zARuxxXO-rxGcnu7cKGScR3UTmCYivJYsX9bV0XK9HdGt5uLzcnogei-pTTDMNLk1N-PhYaX1jIHDgPfpyN2KLH8smlY_PHmMbeuPGrZoOt19D8bQ9Lu6nBqi2xQ_H5nN9tM2rq7nhbDZN7t74lgYPvgk6FJEBJiSDS-KCMDPRD0LKiWbuU9zvvMaz9KIbrm6cNdNUsZz3YkRj_fQbqj1t7kSbYjJFnpqZTE-cKfBfWneiYNq-qRBjInPtfothEPkC7lbrUd7Knj5AVMbU5be-gQrX13Ds21ld0s1GrglWx2LTv3fEV8ObNr1IICb0fKhUGfB8ELUwWLx4ukehciFKxTFc6z-7P5Hvq1-BcgCwhZiI1ICyJZHbeJO2eWgUS3gUhndv8luP9fjUqepzWHF0xG-gzLE0OQi9k5qPFgcU"}`

And getting following responce:

```
    Array
    (
        [type] => urn:acme:error:malformed
        [detail] => Parse error reading JWS
        [status] => 400
    )

```

I am providing exact same value (JWK representation of new private key) for “newKey” and “jwk” of the inner JWS. The inner JWS is signed by new key and outer JWS is signed by the existing (or if we call it old) key.

Can’t find out where I am doing wrong. Please help.  
Thank you.

---

<div class="post-metadata">

**Author:** ![ahaw021](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/ahaw021/32/14882_2.png) [@ahaw021](https://community.letsencrypt.org/u/ahaw021)\
**Post date:** [October 1, 2017, 12:33pm UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/2 "2017-10-01T12:33:56Z")

</div>

i would suggest you install certbot on a test machine and run the change process there.

The logs will show you the messages that certbot submits (including the JWS packages)

You can then compare your signature and see if there are any differences

I would also suggest that you use the staging environment for your testing as well

Andrei

---

<div class="post-metadata">

**Author:** ![cpu](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/cpu/32/84514_2.png) [@cpu](https://community.letsencrypt.org/u/cpu)\
**Post date:** [October 2, 2017, 3:31pm UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/3 "2017-10-02T15:31:48Z")

</div>

Hi @anindya,

> [@anindya](#):
>
> I followed this docs [Automatic Certificate Management Environment (ACME)](https://ietf-wg-acme.github.io/acme/draft-ietf-acme-acme.html#rfc.section.7.3.6) and this one [draft-ietf-acme-acme-06](https://tools.ietf.org/html/draft-ietf-acme-acme-06#section-7.3.3)

Since you're developing against the Let's Encrypt service & [Boulder](https://github.com/letsencrypt/boulder) make sure you also [take into consideration our list of ACME divergences](https://github.com/letsencrypt/boulder/blob/b80b129d1a459005ebf52862136108cdc1528be3/docs/acme-divergences.md). Boulder doesn't strictly implement any exact draft RFC at this time since it evolved alongside of them.

In particular our key change implementation [differs somewhat from spec](https://github.com/letsencrypt/boulder/blob/b80b129d1a459005ebf52862136108cdc1528be3/docs/acme-divergences.md) but is closest to [draft-05](https://tools.ietf.org/html/draft-ietf-acme-acme-05#section-6.3.3).

Is the code you're using to create the JWS available anywhere?

> [@ahaw021](#):
>
> i would suggest you install certbot on a test machine and run the change process there.
> 
> The logs will show you the messages that certbot submits (including the JWS packages)

This would be a good idea normally but unfortunately [Certbot doesn't implement ACME account key change](https://github.com/certbot/certbot/issues/5124).

---

<div class="post-metadata">

**Author:** ![anindya](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/anindya/32/27017_2.png) [@anindya](https://community.letsencrypt.org/u/anindya)\
**Post date:** [October 3, 2017, 4:15am UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/4 "2017-10-03T04:15:54Z")

</div>

Hello @cpu,

Thank you for help. However, I am getting the same error. I am posting the following data structure.

```
{
     "protected": base64url({
       "alg": "ES256",
       "jwk": /* old key */,
       "nonce": "K60BWPrMQG9SDxBDS_xtSw"
     }),
     "payload": base64url({
       "resource": "key-change",
       "protected": base64url({
         "alg": "ES256",
         "jwk": /* new key */
       }),
       "payload": base64url({
         "account": "https://example.com/acme/acct/1",
         "newKey": /* new key */
       }),
       "signature": "Xe8B94RD30Azj2ea...8BmZIRtcSKPSd8gU"
     }),
     "signature": "5TWiqIYQfIDfALQv...x9C2mg8JGPxl5bI4"
   }

```

I am using [this script](https://github.com/analogic/lescript/blob/master/Lescript.php) and written the following code based on it.

```
    <?php 
           // generate and save new key pair for the account       
            
           $new_key_path = dirname($this->accountKeyPath)."/new";
            
           //Generate new key if not exist
           if (!is_file($new_key_path."/private.pem") && !is_file($new_key_path."/public.pem")) {
               
               $this->generateKey($new_key_path);
               
           }
           
           $privateKey_New = $this->readPrivateKey($new_key_path."/private.pem");
            
           $details_New = openssl_pkey_get_details($privateKey_New);
           
           $jwk_New = array(
               "e" => Base64UrlSafeEncoder::encode($details_New["rsa"]["e"]),
               "kty" => "RSA",
               "n" => Base64UrlSafeEncoder::encode($details_New["rsa"]["n"])
           );
                   
           $protected_inner = array(
               "alg" => "RS256",
               "jwk" => $jwk_New
           );        
           
           $protected_inner64 = Base64UrlSafeEncoder::encode(json_encode($protected_inner));
           
          /**The URL for account being modified. The content of 
          * this field the exact string provided in the Location header field
          * in response to the new-account request that created the account.
          */
           $account = "https://acme-v01.api.letsencrypt.org/acme/reg/21941027";
            
           $payload_inner = array(
               "account" => $account,
               "newKey" => $jwk_New
           );
                   
           $payload_inner64 = Base64UrlSafeEncoder::encode(str_replace('\\/', '/', json_encode($payload_inner)));
            
           openssl_sign($protected_inner64.'.'.$payload_inner64, $signature_inner_New, $privateKey_New, "SHA256");
            
           $signature_inner_New64 = Base64UrlSafeEncoder::encode($signature_inner_New);
            
           $payload_outer = array(
               'resource' => 'key-change',
               'protected' => $protected_inner64,
               'payload' => $payload_inner64,
               'signatures' => $signature_inner_New64
           );
            
           // request certificates creation
           $result = $this->signedRequest("/acme/key-change", $payload_outer);
                     
           if ($this->client->getLastCode() == 200) {
               
               $this->log('Account Key Roll-over successful.');
              
               /**
                * Code to delete old key and rename new account key
                */
                          
           }
           else{           
               throw new \RuntimeException("Invalid response code: " . $this->client->getLastCode() . ", " . json_encode($result));                
           }
?>
```

---

<div class="post-metadata">

**Author:** ![cpu](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/cpu/32/84514_2.png) [@cpu](https://community.letsencrypt.org/u/cpu)\
**Post date:** [October 4, 2017, 5:03pm UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/5 "2017-10-04T17:03:01Z")

</div>

Hi @anindya,

I haven’t forgotten about this thread - I’ll try to circle back around to this question in a little while when I’ve finished some other things I’ve fallen behind on.

---

<div class="post-metadata">

**Author:** ![anindya](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/anindya/32/27017_2.png) [@anindya](https://community.letsencrypt.org/u/anindya)\
**Post date:** [October 4, 2017, 5:25pm UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/6 "2017-10-04T17:25:15Z")

</div>

Hi @cpu,

Thank you so much! Looking forward for your reply.

---

<div class="post-metadata">

**Author:** ![cpu](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/cpu/32/84514_2.png) [@cpu](https://community.letsencrypt.org/u/cpu)\
**Post date:** [October 13, 2017, 6:43pm UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/7 "2017-10-13T18:43:50Z")

</div>

Hi @anindya,

Apologies for the long delay getting back to you! I hope you didn't lose faith 🙂

I think I understand what's wrong with the example key roll-over request you submitted. I [wrote a small test program](https://gist.github.com/cpu/8c562d7b59e7c2bc606ad8350f01761d) that uses the same [JOSE library as Boulder](https://github.com/square/go-jose/tree/v2) to see more detail about the error. To save you some trouble I put the full output of the program at the top of its sourcecode so you don't have to run it yourself.

The outer JWS was fine - it verifies as expected 👍 - the parse error happens on trying to read the outer JWS' payload as an inner JWS:

> Err parsing outer JWS payload as an inner JWS: json: cannot unmarshal string into Go value of type jose.rawSignatureInfo

Looking at the raw outer JWS JSON payload we can see that it looks like:

```nohighlight
{
  "resource": "key-change",
  "protected": "<snipped base64url_raw data>",
  "payload": "<snipped base64url_rawl data>",
  "signatures": "jyYVI4y1g1zA1lfj03wRDhkYeajv-Jl1u2vqsJO2zqDjiqEWA5SKDd-8rosJkbKV5B7H0O20CVV1Rqc2btgddYVZCxcpLSTPLRXNY1FmcDzYYrZBIe2V9lyZHV2RaOBSi16b2qeUOMyCx7c4ioHTdiO_P1qYXRUOrvA3QsxKQNiwiaozlIkLcr8n3CYmMtyLNYOaLRTKVLNXfDPqH0aXIZ6_tiGFSud75Q_0M_5Zg2nrTvitxW5GHHx2_VNEQHLeG1nJ5FYfMnYm8hCz8dbpWdakPfhWKm5yFQk0lqNF6h-J74CcVNC789d0e4U7XmxPpRlzHZqmfPhxeArjTWl9Qbmo_0HBn--tLy3YI9OCzqn2Z41IKCx6rsXFrwUdjCX7EjiOOU9ltrcm3ns4ERqegvMzLDQNfWdh8_4kCgLvZ_Fz0196A3edtew33yI_fHJs3zYpDlDFwwCs7hhzsy9RR-B2KUj-_GAVMiqwQS7TjH33JdUKqhYYpbvDOKL74aTleLGXUMr5uxjVcT0pnARJukG_iI-oca4N6lgBHgrDf2N-N_Uv3b9-f-eWQhQCvPXB6oZ9gYo3jKcGGJoURjrdS6bpUhyIeCpiMfJ1L28MRd6i6PE-ytzC8kHNUVlLJnN0rTs-4XaHCmWAfhLmD8fKyJYkOGqa8XYBFpnGLS1uCq4"
}

```

The crux of the problem is that you are using JWS multi-signature support by sending a `"signatures"` key that would normally have an array as a value. In your case the value is a single string. You should instead send an inner JWS that has a `signature` (singular, note the lack of `s` on the end) key with a single string value.

The [struct go-jose.v2 uses to represent a JWS](https://github.com/square/go-jose/blob/5da986dcfc71b4e390b8e08783e8d1eb6c8375f3/jws.go#L28:L35) expects to marshal the `signatures` field to an array of `rawSignatureInfo` complex types while the `signature` field is just a byte string. So when you send a simple string value for the `signatures` field it produces an unmarshal error trying to make a `string` into a `[]jose.rawSignatureInfo`.

~~I'm not familiar with PHP or your JOSE library to offer more concrete help but I think this will be enough for you to troubleshoot further on your end.~~ I replied with a suggestion based on the PHP code after another read.

Thanks again for being patient waiting for my response 🙂

---

<div class="post-metadata">

**Author:** ![cpu](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/cpu/32/84514_2.png) [@cpu](https://community.letsencrypt.org/u/cpu)\
**Post date:** [October 13, 2017, 6:47pm UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/8 "2017-10-13T18:47:21Z")

</div>

Looking at your example PHP code again I think you might be able to change:

```auto
            
           $payload_outer = array(
               'resource' => 'key-change',
               'protected' => $protected_inner64,
               'payload' => $payload_inner64,
               'signatures' => $signature_inner_New64
           );
            

```

to:

```auto
            
           $payload_outer = array(
               'resource' => 'key-change',
               'protected' => $protected_inner64,
               'payload' => $payload_inner64,
               'signature' => $signature_inner_New64
           );
            

```

---

<div class="post-metadata">

**Author:** ![anindya](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/anindya/32/27017_2.png) [@anindya](https://community.letsencrypt.org/u/anindya)\
**Post date:** [October 14, 2017, 4:02pm UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/9 "2017-10-14T16:02:19Z")

</div>

@cpu  
Thanks a million for your help. It fixed the issue. Account Key Roll-over is successful now.

Yes, I didn’t lose faith. 🙂

Thanks again.

---

<div class="post-metadata">

**Author:** ![cpu](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/cpu/32/84514_2.png) [@cpu](https://community.letsencrypt.org/u/cpu)\
**Post date:** [October 14, 2017, 4:30pm UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/10 "2017-10-14T16:30:36Z")

</div>

> [@anindya](#):
>
> Thanks a million for your help. It fixed the issue. Account Key Roll-over is successful now.

🎉🎉 woohoo! Glad to hear it worked 🎉🎉

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/letsencrypt/original/3X/c/a/ca6c06ea1ea201324bba7048c6841ce60236468d.png) [@system](https://community.letsencrypt.org/u/system)\
**Post date:** [November 13, 2017, 4:30pm UTC](https://community.letsencrypt.org/t/account-key-roll-over-parse-error-reading-jws/43305/11 "2017-11-13T16:30:49Z")

</div>

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