如何在 go 中通过 tcp 连接发送 rsa.PublicKey?

How to send a rsa.PublicKey over a tcp connection in go?

我一直在尝试制作一个简单的 RSA 加密聊天应用程序。我遇到的问题是必须通过 tcp 连接发送 rsa Public 密钥,因为 net.Conn 据我所知只接受类型 []byte。

问题代码

 conn.Write([]byte(public_key))

这是生成我的代码的代码 complications.This 代码在函数 handleRequest 下。我知道 conn.Write 只能接受 []byte 类型,但它周围有任何地方吗?如何将 public_key 交付给我的客户?为了以防万一,我已经包含了我所有的服务器代码。此外,如果您希望获得所有 server/client 代码注释,那么我将创建一个 github link。谢谢

以防万一-服务器代码

main.go

package main

import (
    "fmt"
    "github.com/jonfk/golang-chat/tcp/common"
    "io"
    "log"
    "net"
    "os"
)

const (
    CONN_HOST = "0.0.0.0"
    CONN_PORT = "3333"
    CONN_TYPE = "tcp"
)

var (
    connections []net.Conn
)

func main() {
    setUP(3072)
    l, err := net.Listen(CONN_TYPE, CONN_HOST+":"+CONN_PORT)
    if err != nil {
        fmt.Println("Error listening:", err.Error())
        os.Exit(1)
    }
    // Close the listener when the application closes.
    defer l.Close()
    fmt.Println("Listening on " + CONN_HOST + ":" + CONN_PORT)
    for {
        // Listen for an incoming connection.
        conn, err := l.Accept()
        if err != nil {
            fmt.Println("Error accepting: ", err.Error())
            os.Exit(1)
        }
        // Save connection
        connections = append(connections, conn)
        // Handle connections in a new goroutine.
        go handleRequest(conn)
    }
}

// Handles incoming requests.
func handleRequest(conn net.Conn) {
    //I use the common library but this is how it would look like using go's net library.
    conn.Write([]byte(public_key))
    //Using the import common library this is what the command would be 
    //common.WriteMsg(conn,string(public_key))
    for {
        msg, err := common.ReadMsg(conn)
        if err != nil {
            if err == io.EOF {
                // Close the connection when you're done with it.
                removeConn(conn)
                conn.Close()
                return
            }
            log.Println(err)
            return
        }
        broadcast(conn, msg)
    }
}

func removeConn(conn net.Conn) {
    var i int
    for i = range connections {
        if connections[i] == conn {
            break
        }
    }
    connections = append(connections[:i], connections[i+1:]...)
}

func broadcast(conn net.Conn, msg string) {
    for i := range connections {
        if connections[i] != conn {
            err := common.WriteMsg(connections[i], msg)
            if err != nil {
                log.Println(err)
            }
        }
    }
}

encryption.go

package main
import (
    "crypto/md5"
    "crypto/rand"
    "crypto/rsa"
    "log"
    )
var private_key *rsa.PrivateKey
var public_key *rsa.PublicKey
var encrypted,decrypted []byte
func setUP(size int) bool{
    var err error
    if private_key,err = rsa.GenerateKey(rand.Reader,size); err != nil {
        log.Fatal(err)
        return false
    }
    private_key.Precompute()
    if err= private_key.Validate();err != nil {
        log.Fatal(err)
        return false
    }
    public_key = &private_key.PublicKey
    return true
}
func encrypt(msg string) string {
    var err error
    var label []byte
    md5h := md5.New()
    if encrypted,err = rsa.EncryptOAEP(md5h,rand.Reader,public_key,[]byte(msg),label); err != nil {
        log.Fatal(err)
    }
    return string(encrypted)
}
func decrypt(msg string) string {
    var err error
    var label []byte
    md5h := md5.New()
    if decrypted,err = rsa.DecryptOAEP(md5h,rand.Reader,private_key,[]byte(msg),label); err != nil {
        log.Fatal(err)
    }
    return string(decrypted)
}

您需要将 rsa.PublicKey 序列化为 []byte。有多种方法可以做到这一点,但我可能会选择 JSON.

结构看起来像这样,其中的所有内容是 a) Public 和 b) 可序列化为 JSON。

type PublicKey struct {
    N *big.Int // modulus
    E int      // public exponent
}

如果您将数据从一个 Go 程序发送到另一个 Go 程序(如您的示例所示),您可以使用包 encoding/gob https://golang.org/pkg/encoding/gob/ to serialize (Encode) an object into a slice of bytes and deserialize (Decode) the received bytes back into the Go object. Here's an example (also https://play.golang.org/p/3bxbqGtqQY):

package main

import (
    "bytes"
    "crypto/rand"
    "crypto/rsa"
    "encoding/gob"
    "fmt"
    "log"
)

func main() {
    priv, _ := rsa.GenerateKey(rand.Reader, 512) // skipped error checking for brevity
    pub := priv.PublicKey
    // adapted from https://golang.org/pkg/encoding/gob/#example__basic:
    // Initialize the encoder and decoder.  Normally enc and dec would be
    // bound to network connections and the encoder and decoder would
    // run in different processes.
    var network bytes.Buffer        // Stand-in for a network connection
    enc := gob.NewEncoder(&network) // Will write to network.
    dec := gob.NewDecoder(&network) // Will read from network.
    enc.Encode(&pub)
    var pub2 = rsa.PublicKey{}
    dec.Decode(&pub2)
    if pub.N.Cmp(pub2.N) != 0 || pub.E != pub2.E {
        log.Fatal("Public Keys at source and destination not equal")
    }
    fmt.Printf("OK - %#v\n", pub2)
}

输出类似于:

OK -rsa.PublicKey{N:10881677056019504919833663670523712169444878787643568603135265932739968735275981472697621424678110007129031867528249518560683510901399549383480944574041391, E:65537}

发送 gob blob 比 JSON 编码更快更有效,尤其是当您进行大量编码时,但您需要确定这对您来说是否是一个重要因素以及您是否更喜欢文本(JSON) 或二进制格式(gob 或 protobufs)用于数据传输。

我有这个问题,答案很简单,serialising whit marshal

private_key, err = rsa.GenerateKey(rand.Reader, 2048)
public_key = &private_key.PublicKey
pubInJason,err:=json.Marshal(public_key)
fmt.Println("public key in jason: ",string(pubInJason))
pub2:=&rsa.PublicKey{}
err=json.Unmarshal(pubInJason,pub2)
fmt.Println("public key from jason: ",pub2)