我一直在尝试制作一个简单的RSA加密聊天应用。我遇到的问题是必须通过tcp连接发送rsa公钥,因为net.Conn,据我所知只接受type []字节。
问题代码
conn.Write([]byte(public_key))
这是产生我的复杂功能的代码。此代码位于函数handleRequest下。我知道conn.Write只能接受type []字节,但是它周围的任何地方都有。如何将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)
}
答案 0 :(得分:2)
您需要将rsa.PublicKey
序列化为[]byte
。有多种方法可以做到这一点,但我可能会选择JSON。
结构看起来像这样,并且在其中的内容是a)Public和b)使用JSON进行序列化。
type PublicKey struct {
N *big.Int // modulus
E int // public exponent
}
答案 1 :(得分:2)
如果您要将Go程序中的数据发送到另一个Go程序(如您在示例中所示),则可以使用程序包encoding/gob
https://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}
发送gob blob可以比JSON编码更快更高效,特别是如果你做了很多,但你需要确定它是否是一个重要的因素,你喜欢文本(JSON)还是二进制格式(gob或protobufs)用于数据传输。
答案 2 :(得分:0)
我有这个问题,并且有一个简单的答案,序列化白方元帅
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)