2016-07-27 156 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 
}