# 随想-selfdata + relay

By [Jacky3](https://paragraph.com/@jacky3) · 2023-08-10

---

一些关于点对点加密通讯的思考: selfdata + relay

    # ====================================Thinking1=============================================
    c->s: 
    1. c.netPriv + s.netPub ===> key
    2. data + key ===> edata
    
    s->c:
    1. s.netPriv + c.netPub ===> key
    2. data + key ===> edata
    
    
    c1->s:
    1. c1.id + c1.id ==> eid1
    2. c1.netPub + (c-s).key ===> s.pubc1
    
    c2->s:
    1. c2.id + c2.id ===> eid2
    3. c2.netPub + (c-s).key ===> s.pubc2
    
    c1->c2:
    1. c2->s(pull): (c1.id + c1.id) ===> (eid1 + s.pubc1)
    2. c2->c2(...): c2.dataPub + (c2.netPriv + s.pubc1).key ===> c2sdata
    3. c2->s(push): eid1 + c2sdata + s.pubc2(swap+sign) ===> c1.mq
    4. c1->s(pull): (c1.id + c1.id) ===> eid2 + c2sdata + s.pubc2
    5. c1->c1(...): c2sdata + (c1.netPriv + s.pubc2).key ===> c2.dataPub
    6. c1->c1(...): c1.datapub + (c1.netPriv + s.pubc2).key ===> c1sdata
    7. c1->s(push): eid2 + c1sdata + s.pubc1(swap+sign) ===> c2.mq
    8. c2->s(pull): (c2.id + c2.id) ===> eid2 + c1sdata + s.pubc1
    9. c2->c2(...): c1sdata + (c2.netPriv + s.pubc1).key ===> c1.dataPub
    # ====================================Thinking1=============================================
    
    # ====================================Thinking2=============================================
    just only for c1<->c2
    1. c1.random + c2.netPub ===> erandom
    2. (c1.netPriv + c2.netPub).key + c1.random  ===> netKey
    3. (c2.netPriv + c1.netPub).key + (erandom + c2.netPriv).random ===> netKey
    
    push/pull list
    1. public: (c1.id + c1.id).key, (public + c1.netPub + selfEncryptedKey).value
    2. c1<->c2: (c1.id + netKey).key, (c2/c3/c4.id + c2/c3/c4.netPub + public + c2/c3/c4sdata + netKey).value
    3. self.list: (c1.id + c1.dataPub).key, (data + c1.dataPub)
    4. c<->s: cdata + s.pub ===> sedata + s.priv ===> sdata + c.pub ===> cedata + c.priv ===> c.data
    # ====================================Thinking3=============================================
    
    # ====================================Thinking3=============================================
    1. self<->self: selfdata + relay, relay.store: memory.map + memory.filesystem(open source)
    
    // 考虑是否需要
    1.1. memory.filesystem: c1.fname + s.netPub ===> efname + s.netPriv ===> s.fname ===> memory.fs
    1.2. memory.filesystem: efname + s.netPriv ===> s.fname + c2.netPub ===>  efname ===> s.downloadURL
    1.3. memory.filesystem: efname + c2.netPriv ===> s.fname + s.netPub ===> efname ===> c2.downloadURL
    
    2. rc1<->rc2: selfdata + relay, relay.store: swap + redis + p2p.file(open source)
    
    3. sdc1<->sdc2: selfdata + gossip/p2p(blockchain)  
    # ====================================Thinking3=============================================
    
    # ====================================Thinking4=============================================
    1. key for mq: (c1.id + c1.id).key + (name.id + name.id).key + (email.id + email.id).key
    2. split for key: "-"
    # ====================================Thinking4=============================================
    

核心源码
----

    package rsrelay
    
    import (
        "fmt"
        "io/ioutil"
        "net/http"
    )
    
    func doCheckPermission(r *http.Request) (string, string, []string) {
        dparams, err := decodeNetParams(WebParams(r).Get("param"), v_sysPrivateKey)
        if err != nil || len(dparams) < 3 {
            LogPrint("decodeNetParams failed, detail: %+v", err, "error")
            return "", "", nil
        }
    
        selfPub := ""
        if bytes := getBytes(dparams[0]); len(bytes) > 0 {
            selfPub = string(bytes[0])
        }
        if selfPub == "" {
            if dparams[0] == dparams[len(dparams) - 1] {
                selfPub = WebParams(r).Get("data")
            } else {
                LogPrint("getPublicKey failed, selfID: " + dparams[0], "error")
                return "", "", nil
            }
        }
        if tokenVerify(dparams[1], dparams[2], []byte(selfPub), []byte(v_sysPrivateKey)) != nil {
            LogPrint("tokenVerify failed, selfID: " + dparams[0], "error")
            return "", "", nil
        }
        return dparams[0], selfPub, dparams
    }
    
    func doResponseOK(w http.ResponseWriter, r *http.Request, selfPub string, datas ...[]byte) {
        respBytes := make([][]byte, 0)
        token, signature := tokenCreate([]byte(selfPub), []byte(v_sysPrivateKey))
        respBytes = append(respBytes, token, signature)
        respBytes = append(respBytes, datas...)
        ResponseOk(w, r, WebOk(respBytes))
    }
    
    // GET /api/data/pull
    // param: [selfID, token, signature], data: demo
    func WebDataPull(w http.ResponseWriter, r *http.Request) {
        if selfID, selfPub, dparams := doCheckPermission(r); dparams != nil && selfPub != "" && selfID != "" {
            if pullBytes, err := doWebPullForBytes(r, selfID, selfPub, WebParams(r).Get("data")); err != nil {
                ResponseError(w, r, err.Error())
            } else {
                doResponseOK(w, r, selfPub, pullBytes...)
                vBytesCache.Delete(WebParams(r).Get("data"))
            }
        }
        ResponseError(w, r, "permission denied")
    }
    
    // GET /api/data/push
    // param: [selfID, token, signature], data: demo
    func WebDataPush(w http.ResponseWriter, r *http.Request) {
        if selfID, selfPub, dparams := doCheckPermission(r); dparams != nil && selfPub != "" && selfID != "" {
            recvIds := dparams[3:]
            failedIds := make([][]byte, 0)
            for i := 0; i < len(recvIds); i++ {
                if err := doWebPushForBytes(r, selfID, selfPub, recvIds[i]); err != nil {
                    failedIds = append(failedIds, []byte(recvIds[i]))
                    LogPrint(err.Error(), "error")
                }
            }
            doResponseOK(w, r, selfPub, failedIds...)
            return
        }
        ResponseError(w, r, "permission denied")
    }
    
    func doWebPushForBytes(r *http.Request, selfID, selfPub, pushID string) error {
        // cache for bytes
        buf := []byte(WebParams(r).Get("data"))
        if len(buf) == 0 {
            bytes, err := ioutil.ReadAll(r.Body)
            if err != nil {
                return err
            }
            buf = bytes[:]
        }
        if len(buf) == 0 {
            return fmt.Errorf("invalid push bytes, recvID: %s", pushID)
        }
        addBytes(pushID, buf[:])
        //infoLog("upload text successed, push: %s, size: %d", pushID, len(buf))
        return nil
    }
    
    func doWebPullForBytes(r *http.Request, selfID, sdPub, pullID string) ([][]byte, error) {
        return getBytes(pullID), nil
    }

---

*Originally published on [Jacky3](https://paragraph.com/@jacky3/selfdata-relay)*
