{Urn ietf:params:acme error malformed Parse error reading JWS status 400}


#1

Need Hep With

{
“type”: “urn:ietf:params:acme:error:malformed”,
“detail”: “Parse error reading JWS”,
“status”: 400
}

Request

{
“header”: {
“alg”: “RS256”,
“jwk”: {
“e”: “AQAB”,
“kty”: “RSA”,
“n”: “pSb37Nx2sCZFbC0uIsNn7USlYi0mhXuiDOUmv7CqhgdvBFiLG3aupF1BRD1y5J97Qw_dyFBOprFqoaYw7MIbxQbjTkCttZWiVdyzwj4A1DGydBI9vES7FabjjWjn4lkJhrxglemaq-6WTh6K5_WD4SF5_LcYBNqZwnrGGo1q_rhrREyhu9Q0agSXkVmO44Gu1UzahV0FtCc6pCY8zhM1MChRWzOrCRW25RxoxZWy9jfS1frUMbhRfGq8XbHE3e5Z8K5-h2aRg5HmRJWOsHffYmXunziO4lis5LvSyn7F10hlF149IZ6hVjP7JaincXf1GPrRptpVtm4O5KKWYQeZKw”
}
},
“protected”: “ewogImFsZyI6ICJSUzI1NiIsCiAiandrIjogewogICJlIjogIkFRQUIiLAogICJrdHkiOiAiUlNBIiwKICAibiI6ICJwU2IzN054MnNDWkZiQzB1SXNObjdVU2xZaTBtaFh1aURPVW12N0NxaGdkdkJGaUxHM2F1cEYxQlJEMXk1Sjk3UXdfZHlGQk9wckZxb2FZdzdNSWJ4UWJqVGtDdHRaV2lWZHl6d2o0QTFER3lkQkk5dkVTN0ZhYmpqV2puNGxrSmhyeGdsZW1hcS02V1RoNks1X1dENFNGNV9MY1lCTnFad25yR0dvMXFfcmhyUkV5aHU5UTBhZ1NYa1ZtTzQ0R3UxVXphaFYwRnRDYzZwQ1k4emhNMU1DaFJXek9yQ1JXMjVSeG94Wld5OWpmUzFmclVNYmhSZkdxOFhiSEUzZTVaOEs1LWgyYVJnNUhtUkpXT3NIZmZZbVh1bnppTzRsaXM1THZTeW43RjEwaGxGMTQ5SVo2aFZqUDdKYWluY1hmMUdQclJwdHBWdG00TzVLS1dZUWVaS3ciCiB9LAogImtpZCI6ICIiLAogIm5vbmNlIjogIkcwN0pYS190NWI3amhWenNtS3ZaaGFZcDdqSzg1NzFZSUZzU2RFdkdndk0iLAogInVybCI6ICJodHRwczovL2FjbWUtdjAyLmFwaS5sZXRzZW5jcnlwdC5vcmcvYWNtZS9uZXctYWNjdCIKfQ”,
“payload”: “ewogInRlcm1zT2ZTZXJ2aWNlQWdyZWVkIjogdHJ1ZSwKICJjb250YWN0IjogWwogICJtYWlsdG86c2V0ZGNAZ21haWwuY29tIiwKICAibWFpbHRvOnNldGRjMUBnbWFpbC5jb20iCiBdCn0”,
“signature”: “X2eGFaT6pj4ENsmjbCqIaQJKF9KD9Kyu7SJz2ixFy6SJLLGab7uNanZtUUciw0jKtWKyn-Eul59mPNlwnWhWuO6d3AJJ_wAyO2YbdwJPJT0Gm5R2Ikvbr99kzc_zqNUp135AOY4TqNa56n01_y2r75cqWTNVSR6drvS0SAdphHjR2tgisX4fBuRLpViDVMowxSVSnIYDbOt7KUGwWg0RAjcrA_IDZftAVv66QdUxdz-KGIyCqmx1OBJxO9vZrNVv1rs4JCD4v0Gh-yYz1_eVIi5nmhziAsKAhEk1WAeNC5u1zjqXNcuTtOo1C_JmSc0UkIoi3FKxg1kqlyW9UgaiuA”
}

Response

{
“type”: “urn:ietf:params:acme:error:malformed”,
“detail”: “Parse error reading JWS”,
“status”: 400
}

Code

package main

import (
“net/http”
“bytes”
“encoding/base64”
“crypto/rsa”
“log”
“crypto/rand”
“math/big”
“fmt”
“encoding/json”

“io/ioutil”
“crypto/sha256”
“crypto”
)

type Jwk struct {
E string json:"e"
Kty string json:"kty"
N string json:"n"
}

type Header struct {
Alg string json:"alg"
Jwk Jwk json:"jwk"
}

type Protected struct {
Alg string json:"alg"
Jwk Jwk json:"jwk, omitempty"
Kid string json:"kid, omitempty"
Nonce string json:"nonce"
URL string json:"url"
}

type Payload struct {
TermsOfServiceAgreed bool json:"termsOfServiceAgreed"
Contact []string json:"contact"
}

type AcmeRequest struct {
Header Header json:"header"
Protected Protected json:"protected"
Payload Payload json:"payload"
Signature string json:"signature"
}

type Signature struct {
Protected string
Payload string
}

func (signature Signature) join() string {

return fmt.Sprintf("%s.%s", signature.Protected, signature.Payload)
}

type Account struct {
Status string json:"status"
Contact []string json:"contact"
TermsOfServiceAgreed bool json:"termsOfServiceAgreed"
Orders string json:"orders"
}

func Send(b []byte) {
request, _ := http.NewRequest(“POST”, “https://acme-staging-v02.api.letsencrypt.org/acme/new-acct”, bytes.NewBuffer(b))
request.Header.Set(“Content-Type”, “application/jose+json”)
request.Header.Set(“User-Agent”, “Vighnesh-Go v2.0”)
request.Header.Set(“Accept-Language”, “en”)
request.Header.Set(“Access-Control-Allow-Origin”, “*”)

client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
panic(err)
}
defer resp.Body.Close()

body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(“response Body:”, string(body))
}

func GetNonce() (string, error) {
response, err := http.Get(“https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce”)
return response.Header[“Replay-Nonce”][0], err
}

func main() {

nonce, _ := GetNonce()
fmt.Println(nonce)
acmeRequest := AcmeRequest{}

privkey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
log.Printf(“failed to generate private key: %s”, err)
return
}

pubKey := &privkey.PublicKey
e := base64URLEncode(big.NewInt(int64(pubKey.E)).Bytes())
n := base64URLEncode(pubKey.N.Bytes())
kty := “RSA”

acmeRequest.Header.Alg = “RS256”
acmeRequest.Header.Jwk.E = e
acmeRequest.Header.Jwk.Kty = kty
acmeRequest.Header.Jwk.N = n

acmeRequest.Protected.Alg = “RS256”
acmeRequest.Protected.URL = “https://acme-v02.api.letsencrypt.org/acme/new-acct

acmeRequest.Protected.Jwk.E = e
acmeRequest.Protected.Jwk.Kty = kty
acmeRequest.Protected.Jwk.N = n

acmeRequest.Protected.Nonce = nonce

contact := []string{“mailto:setdc@gmail.com”, "mailto:setdc1@gmail.com"}
acmeRequest.Payload.Contact = contact
acmeRequest.Payload.TermsOfServiceAgreed = true

protectedJson, _ := json.MarshalIndent(acmeRequest.Protected, “”, " ")
//fmt.Println(“protected:”, string(protectedJson))

payloadJson, _ := json.MarshalIndent(acmeRequest.Payload, “”, " ")
//fmt.Println(“payload:”, string(payloadJson))

urlEncodedProtected := base64URLEncode(protectedJson)
urlEncodedPayload := base64URLEncode(payloadJson)

acmeRequest.Signature = Signature{urlEncodedProtected, urlEncodedPayload}.join()

type EncodedAcmeRequest struct {
Header Header json:"header"
Protected string json:"protected"
Payload string json:"payload"
Signature string json:"signature"
}

encodedACMERequest := EncodedAcmeRequest{}

signed, signError := Sign(privkey, []byte(acmeRequest.Signature))
if signError != nil {
fmt.Println(“Could not sign”, signError)
}
//fmt.Println(“signed”, string(signed))
signature := base64URLEncode(signed)
fmt.Println(signature)

encodedACMERequest.Protected = urlEncodedProtected
encodedACMERequest.Header = acmeRequest.Header
encodedACMERequest.Payload = urlEncodedPayload
encodedACMERequest.Signature = signature

b, err := json.MarshalIndent(encodedACMERequest, “”, " ")
unsigned := Unsign(pubKey, []byte(acmeRequest.Signature), signed)
fmt.Println(“unsigned”, unsigned)
fmt.Println(string(b))
Send(signed)

}

func Sign(privateKey *rsa.PrivateKey, data []byte) ([]byte, error) {
sha := sha256.New()
sha.Write(data)
sha256Hash := sha.Sum(nil)
return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, sha256Hash)
}

// Unsign verifies the message using a rsa-sha256 signature
func Unsign(publicKey *rsa.PublicKey, message []byte, signed []byte) error {
sha := sha256.New()
sha.Write(message)
sha256Hash := sha.Sum(nil)
return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, sha256Hash, signed)
}

func base64URLEncode(data []byte) string {
return base64.RawURLEncoding.EncodeToString(data)
}

func base64URLDecode(data string) ([]byte, error) {
return base64.RawURLEncoding.DecodeString(data)
}


#2

@jsha

Can you take a look at this…

(I might having the same issue when i’m getting certs from zerossl and sslforfree.com)

Thank you


#3

This error means that the JSON you sent was malformed, or that jose.ParseSigned considers it malformed. I’d recommend running your generated JSON through a JSON decoder (e.g. python -mjson.tool) and correcting errors until it parses correctly. Assuming it parses correctly as JSON, try using the square/go-jose library and run jose.ParseSigned on your output and tweak until that passes.


#4

What kind of hosting provider did u use exactly?


#5

It is a standalone program, no speciffic provider.
I want to develop a library.


#6

There’s quite a few issues in the code.

The main one that is stopping you is pretty simple - you’re not actually sending the marshaled buffer to the ACME server.

Yep, this is a PKCS#1v1.5 signature over the JWS signature.

OK, this is the final JWS encapsulation that we need to send over the wire.

Wait what? Perhaps you meant:

    Send(b)

I second the suggestion to use go-square/jose, or copy how golang/x/crypto/acme does it without external dependencies, or use @eggsampler’s excellent acme v2 library at https://github.com/eggsampler/acme


#7

Yes, i have to send b, err := json.MarshalIndent(encodedACMERequest, “”, " ")

 b, err := json.MarshalIndent(encodedACMERequest, "", " ")

unsigned := Unsign(pubKey, []byte(acmeRequest.Signature), signed)
fmt.Println(“unsigned”, unsigned)
fmt.Println(string(b))
Send(b)

even getting same reponse

{
“type”: “urn:ietf:params:acme:error:malformed”,
“detail”: “Parse error reading JWS”,
“status”: 400
}


#8

Like I said, that mistake is not the only issue in your code.

Here’s a heavily refactored version that runs successfully.

package main

import (
	"bytes"
	"crypto/rand"
	"crypto/rsa"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"math/big"
	"net/http"

	"crypto"
	"crypto/sha256"
	"io/ioutil"
)

type Jwk struct {
	E   string `json:"e"`
	Kty string `json:"kty"`
	N   string `json:"n"`
}

// type Header struct {
// 	Alg string `json:"alg"`
// 	Jwk Jwk    `json:"jwk"`
// }

type Protected struct {
	Alg   string `json:"alg"`
	Jwk   Jwk    `json:"jwk,omitempty"`
	Kid   string `json:"kid,omitempty"`
	Nonce string `json:"nonce"`
	URL   string `json:"url"`
}

type Payload struct {
	TermsOfServiceAgreed bool     `json:"termsOfServiceAgreed"`
	Contact              []string `json:"contact"`
}

type AcmeRequest struct {
	// Header    Header    `json:"-"`
	Protected Protected `json:"protected"`
	Payload   Payload   `json:"payload"`
	Signature string    `json:"signature"`
}

type Signature struct {
	Protected string
	Payload   string
}

func (signature Signature) join() string {

	return fmt.Sprintf("%s.%s", signature.Protected, signature.Payload)
}

type Account struct {
	Status               string   `json:"status"`
	Contact              []string `json:"contact"`
	TermsOfServiceAgreed bool     `json:"termsOfServiceAgreed"`
	Orders               string   `json:"orders"`
}

func Send(b []byte) {
	fmt.Println("req", string(b))
	request, err := http.NewRequest("POST", "https://acme-staging-v02.api.letsencrypt.org/acme/new-acct", bytes.NewBuffer(b))
	if err != nil {
		panic(err)
	}
	request.Header.Set("Content-Type", "application/jose+json")
	request.Header.Set("User-Agent", "Vighnesh-Go v2.0")
	// request.Header.Set("Accept-Language", "en")
	// request.Header.Set("Access-Control-Allow-Origin", "*")

	client := &http.Client{}
	resp, err := client.Do(request)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Println("response Body:", string(body))
}

func GetNonce() (string, error) {
	response, err := http.Get("https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce")
	return response.Header["Replay-Nonce"][0], err
}

func main() {

	nonce, _ := GetNonce()
	fmt.Println(nonce)

	privkey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		log.Printf("failed to generate private key: %s", err)
		return
	}

	pubKey := &privkey.PublicKey
	e := base64URLEncode(big.NewInt(int64(pubKey.E)).Bytes())
	n := base64URLEncode(pubKey.N.Bytes())
	kty := "RSA"

	prot := Protected{}
	prot.Alg = "RS256"
	prot.URL = "https://acme-staging-v02.api.letsencrypt.org/acme/new-acct"
	prot.Jwk.E = e
	prot.Jwk.Kty = kty
	prot.Jwk.N = n
	prot.Nonce = nonce

	payload := &Payload{}

	payload.Contact = []string{"mailto:setdc@gmail.com", "mailto:setdc1@gmail.com"}
	payload.TermsOfServiceAgreed = true

	protectedJson, _ := json.MarshalIndent(prot, "", " ")
	//fmt.Println("protected:", string(protectedJson))

	payloadJson, _ := json.MarshalIndent(payload, "", " ")
	//fmt.Println("payload:", string(payloadJson))

	urlEncodedProtected := base64URLEncode(protectedJson)
	urlEncodedPayload := base64URLEncode(payloadJson)

	sig := Signature{urlEncodedProtected, urlEncodedPayload}.join()

	var encoded struct {
		Protected string `json:"protected"`
		Payload   string `json:"payload"`
		Signature string `json:"signature"`
	}

	signed, signError := Sign(privkey, []byte(sig))
	if signError != nil {
		fmt.Println("Could not sign", signError)
	}
	signature := base64URLEncode(signed)

	encoded.Protected = urlEncodedProtected
	encoded.Payload = urlEncodedPayload
	encoded.Signature = signature

	b, err := json.MarshalIndent(encoded, "", " ")

	Send(b)
}

func Sign(privateKey *rsa.PrivateKey, data []byte) ([]byte, error) {
	sha := sha256.New()
	sha.Write(data)
	sha256Hash := sha.Sum(nil)
	return privateKey.Sign(rand.Reader, sha256Hash, crypto.SHA256)
}

// Unsign verifies the message using a rsa-sha256 signature
func Unsign(publicKey *rsa.PublicKey, message []byte, signed []byte) error {
	sha := sha256.New()
	sha.Write(message)
	sha256Hash := sha.Sum(nil)
	return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, sha256Hash, signed)
}

func base64URLEncode(data []byte) string {
	return base64.RawURLEncoding.EncodeToString(data)
}

func base64URLDecode(data string) ([]byte, error) {
	return base64.RawURLEncoding.DecodeString(data)
}

#9

Thank You, it is working
:grinning:


#10

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