jsongocryptography

How to marshal an ECC public or private key


Hello i'am trying to unmarshal object that contain ECC public key but i go umarshaling error saying that can't unmarshal object properly. i'am tring to do the followeing :

var privateKey *ecdsa.PrivateKey
var publicKey ecdsa.PublicKey
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
    log.Fatalf("Failed to generate ECDSA key: %s\n", err)
}
publicKey = privateKey.PublicKey

marshalledKey, err := json.Marshal(publicKey)
if err != nil {
    panic(err)
}

var unmarshalledKey ecdsa.PublicKey
err2 := json.Unmarshal(marshalledKey, &unmarshalledKey)
if err2 != nil {
    panic(err2)
}

and tthe error returned from (err2) is :

panic: json: cannot unmarshal object into Go struct field PublicKey.Curve of type elliptic.Curve

and there is no way in either eliptoc or 509x function to umarshal and the curve value is alwayes null


Solution

  • i found the answer finally and i will post it in case somone need it. all we need is just to creat another struct, lets name it "retrieve" and declare the value it wil read from the unmarshal. now the ECC public key contain 3 values "curve" and will append it as json:"Curve", "Y" ans will append it as json:"Y" and we will do the same for "X"

    and it will work like this :

    type retrieve struct {
        CurveParams *elliptic.CurveParams `json:"Curve"`
        MyX         *big.Int              `json:"X"`
        MyY         *big.Int              `json:"Y"`
    }
    
    //UnmarshalECCPublicKey extract ECC public key from marshaled objects
    func UnmarshalECCPublicKey(object []byte) (pub ecdsa.PublicKey) {
        var public ecdsa.PublicKey
        rt := new(retrieve)
    
        errmarsh := json.Unmarshal(object, &rt)
        if errmarsh != nil {
            fmt.Println("err at UnmarshalECCPublicKey()")
            panic(errmarsh)
        }
    
        public.Curve = rt.Key.CurveParams
        public.X = rt.Key.MyX
        public.Y = rt.Key.MyY
        mapstructure.Decode(public, &pub)
    
        fmt.Println("Unmarshalled ECC public key : ", pub)
        return
    }
    

    we will pass the the marshalled public key to UnmarshalECCPublicKey() and it will return the correct unmarshaled obj

    so the coorect use will be :

    var privateKey *ecdsa.PrivateKey
    var publicKey ecdsa.PublicKey
    privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    if err != nil {
        log.Fatalf("Failed to generate ECDSA key: %s\n", err)
    }
    publicKey = privateKey.PublicKey
    
    marshalledKey, err := json.Marshal(publicKey)
    if err != nil {
        panic(err)
    }
    
    var unmarshalledKey ecdsa.PublicKey
    unmarshalledKey = UnmarshalECCPublicKey(marshalledKey)
    

    and that should do it, u will get the ECC public unmarshalled successfully.