Cover photo

随想-selfdata + relay

一些关于点对点加密通讯的思考: 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
}