2016-07-27 159 views
1

我一直在试图制作一个简单的RSA加密聊天应用程序。我遇到的问题是必须通过tcp连接发送rsa公钥,就像net.Conn,据我所知只接受类型[]字节。如何通过tcp连接发送rsa.PublicKey?

问题代码

conn.Write([]byte(public_key)) 

这是我制作的complications.This代码代码是函数的handleRequest下。我明白,conn.Write只能接受类型[]字节,但是在这附近有任何地方。我如何将public_key发送给我的客户?我已经包含了所有的服务器代码以防万一。此外,如果您希望获得所有服务器/客户端代码注释,那么我将创建一个github链接。三江源

万一服务器代码

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

回答

2

如果从Go程序将数据发送到别的去了一个(如你在你的例子显示),你可以使用包encoding/gobhttps://golang.org/pkg/encoding/gob/连载(Encode)的对象为字节和反序列化的片(Decode)将接收到的字节放回到Go对象中。下面是一个例子(也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}

发送采空区的斑点可以更快,更高效然后做JSON编码,特别是如果你正在做它的很多,但是您需要决定它是否对您而言是一个重要因素,您是否喜欢用于数据传输的文本(JSON)或二进制格式(gob或protobufs)。

2

您需要将rsa.PublicKey连续编号为[]byte。有多种方式可以做到这一点,但我可能会使用JSON。

结构看起来像这样,它内部的everthing是a)public和b)用JSON序列化。

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