【问题标题】:send and read a [] byte between two microservices golang在两个微服务 golang 之间发送和读取一个 [] 字节
【发布时间】:2018-08-06 12:35:31
【问题描述】:

我有一个返回 [] 字节的数据加密函数。当然,已经加密的内容必须在另一个微服务中(通过另一个函数)解密。 当我通过 JSON 发送 []byte 时会出现问题:[]byte 被转换为字符串,然后当我通过调用读取 JSON 时,结果不再相同。

我必须能够通过 JSON 传递由加密函数创建的原始 []byte,或者通过如下所示的调用传递 []byte。另一种可能是改解密功能,但我没有成功。

调用函数

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))
}

通过 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)
}

加解密函数

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)
}

一切正常,当我在c.JSON () 中打印cipherjson 时产生了问题:[]byte 被转换为字符串。 在调用函数读取和读取它时,它被读取为字符串,并且 ioutil.ReadAll () 创建读取字符串的 [] 字节。 相反,我必须能够将被调用函数中使用的 Encrypt 函数的返回值传递给 Decryot 函数。

希望我说清楚了,提前谢谢

【问题讨论】:

  • 如果可以选择在微服务之间使用直接 TCP 连接,而不是 HTTP,则可以使用 Gob 对数据进行编码和解码,而无需将其转换为字符串:medium.com/@kpbird/…
  • 发送二进制数据,使用gob、protobuf等,但是JSON是文本格式!

标签: json go httprequest


【解决方案1】:

在解密之前您没有对响应进行解码。换句话说,您将密文的 JSON 编码交给 Decrypt。这显然不会做你想做的事。要恢复明文,您必须以相反的顺序精确撤消加密和编码的所有操作。

在解密之前解码,或者不在服务器上进行 JSON 编码。例如:

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)

虽然不清楚你为什么会首先遇到 JSON 编码的麻烦。你还不如直接写密文。如果您真的想对密文进行编码,则不应将其转换为字符串。密文只是一堆随机字节,与 UTF-8 编码的字符串不太相似,所以不要把它当作一个。 encoding/json 自动对字节切片使用 base64 编码,这比大量的 unicode 转义序列更清晰(可能更短)的密文表示。

与您选择的编码无关(如果有),您的 Encrypt 功能已损坏。

// 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

第一个参数是加密的目的地。如果不需要保留明文,通过json[:0];否则通过nil

此外,Decrypt 期望密文以随机数作为前缀,但 Encrypt 不会在它前面添加。

【讨论】:

  • 我不熟悉杜松子酒,但从文档来看,您会调用 Data 而不是 JSON
  • 谢谢你,成功了!!我做了一些改变,但没有帮助我永远不会成功。
猜你喜欢
  • 2016-08-10
  • 2011-02-10
  • 1970-01-01
  • 2021-02-12
  • 2016-08-07
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2017-06-12
相关资源
最近更新 更多