dousong5161 2018-08-06 12:35
浏览 102
已采纳

在两个微服务golang之间发送和读取[]字节

I have a data encryption function that returns a [] byte. Of course, what has been encrypted must be decrypted (through another function) in another micro-service. The problem is created when I send the []byte via JSON: the []byte is transformed into a string and then when I go to read the JSON through the call, the result is no longer the same.

I have to be able to pass the original []byte, created by the encryption function, through JSON or otherwise pass the []byte through a call like the one you can see below. Another possibility is to change the decryption function, but I have not succeeded.

caller function

func Dati_mono(c *gin.Context) {
   id := c.Param("id")
   oracle, err := http.Get("http://XXXX/"+id)
   if err != nil {
       panic(err)
   }
   defer oracle.Body.Close()

   oJSON, err := ioutil.ReadAll(oracle.Body)
   if err != nil {
       panic(err)
   }

   oracleJSON := security.Decrypt(oJSON, keyEn)

   c.JSON(http.StatusOK, string(oJSON))
}

function that is called with the url

func Dati(c *gin.Context) {
    var (
       person Person
       result mapstring.Dati_Plus
       mmap []map[string]interface{}
    )

    rows, err := db.DBConor.Query("SELECT COD_DIPENDENTE, MATRICOLA, COGNOME FROM ANDIP021_K")

    if err != nil {
       fmt.Print(err.Error())
    }

    for rows.Next() {
       err = rows.Scan(&person.COD_DIPENDENTE, &person.MATRICOLA, &person.COGNOME)
       ciao := structs.Map(&person)
       mmap = append(mmap, ciao)
    }
    defer rows.Close()

    result = mapstring.Dati_Plus{
       len(mmap),
        mmap,
    }

    jsonEn := []byte(mapstring.Dati_PlustoStr(result))
    keyEn := []byte(key)

    cipherjson, err := security.Encrypt(jsonEn, keyEn)
    if err != nil {
       log.Fatal(err)
    }

    c.JSON(http.StatusOK, cipherjson)
}

encryption and decryption functions

func Encrypt(json []byte, key []byte) (string, error) {
    k, err := aes.NewCipher(key)
    if err != nil {
       return "nil", err
    }

    gcm, err := cipher.NewGCM(k)
    if err != nil {
       return "nil", err
    }

    nonce := make([]byte, gcm.NonceSize())
    if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
       return "nil", err
    }
return gcm.Seal(nonce, nonce, json, nil), nil
        }

func Decrypt(cipherjson []byte, key []byte) ([]byte, error) {
    k, err := aes.NewCipher(key)
    if err != nil {
       return nil, err
    }

    gcm, err := cipher.NewGCM(k)
    if err != nil {
       return nil, err
    }

    nonceSize := gcm.NonceSize()
    if len(cipherjson) < nonceSize {
        return nil, errors.New("cipherjson too short")
    }

    nonce, cipherjson := cipherjson[:nonceSize], cipherjson[nonceSize:]
    return gcm.Open(nil, nonce, cipherjson, nil)
}

Everything works, the problem is created when I print cipherjson in c.JSON (): the []byte is translated into a string. At the time it is taken and read by the calling function it is read as string and ioutil.ReadAll () creates the [] byte of the read string. Instead I must be able to pass to the Decryot function the return of the Encrypt function used in the called function.

I hope I was clear, thanks in advance

  • 写回答

1条回答 默认 最新

  • dongmo6937 2018-08-06 13:41
    关注

    You are not decoding the response before decrypting. In other words, you are handing the JSON encoding of the ciphertext to Decrypt. That is obviously not going to do what you want. To recover the plaintext you have to precisely undo all of the operations of the encryption and encoding in reverse order.

    Either decode before decrypting, or don't JSON encode on the server. For instance:

    oJSON, err := ioutil.ReadAll(oracle.Body)
    if err != nil {
        panic(err)
    }
    
    var ciphertext string
    if err := json.Unmarshal(oJSON, &ciphertext); err != nil {
        // TODO: handle error
    }
    
    oracleJSON := security.Decrypt(ciphertext, keyEn)
    

    Although it is unclear why you even go through the trouble of JSON encoding in the first place. You might as well just write the ciphertext directly. If you really want to encode the ciphertext, you should not convert it to a string. The ciphertext is just a bunch of random bytes, not remotely resembling a UTF-8 encoded string, so don't treat it like one. encoding/json uses the base64 encoding for byte slices automatically, which is a much cleaner (and probably shorter) representation of the ciphertext than tons of unicode escape sequences.

    Independent of the encoding you choose (if any), your Encrypt function is broken.

    // The plaintext and dst must overlap exactly or not at all. To reuse
    // plaintext's storage for the encrypted output, use plaintext[:0] as dst.
    Seal(dst, nonce, plaintext, additionalData []byte) []byte
    

    The first argument is the destination for the encryption. If you don't need to retain the plaintext, pass json[:0]; otherwise pass nil.

    Also, Decrypt expects the ciphertext to be prefixed by the nonce, but Encrypt doesn't prepend it.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 ffmpeg如何安装到虚拟环境
  • ¥188 寻找能做王者评分提取的
  • ¥15 matlab用simulink求解一个二阶微分方程,要求截图
  • ¥30 乘子法解约束最优化问题的matlab代码文件,最好有matlab代码文件
  • ¥15 写论文,需要数据支撑
  • ¥15 identifier of an instance of 类 was altered from xx to xx错误
  • ¥100 反编译微信小游戏求指导
  • ¥15 docker模式webrtc-streamer 无法播放公网rtsp
  • ¥15 学不会递归,理解不了汉诺塔参数变化
  • ¥15 基于图神经网络的COVID-19药物筛选研究