RSA解决对称密钥分发


1、当有客户端连接成功时,就在服务器端生成一个RSA密钥对

2、服务器将公钥发送给客户端

3、客户端生成一个对称加密的密钥

4、客户端用公钥对对称加密的密钥加密,发送给服务器端

5、服务器用私钥对密文进行解密,拿到对称加密的密钥

6、双方使用对称加密的方式进行通信

server.go

func main() {
	//服务器地址信息
	udpaddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8888")
	if err != nil {
		panic(err)
	}
	conn, err1 := net.ListenUDP("udp", udpaddr)
	if err1 != nil {
		panic(err)
	}
	defer conn.Close()
	count := 0
	length := 0
	data := make([]byte, 4096)

	var aesKey []byte
	var privateKey *rsa.PrivateKey

	//通信
	for {
		count++
		//接受客户端发送来的消息
		n, raddr, err := conn.ReadFromUDP(data)
		length = n
		if count == 1 {
			//1、生成密钥对,指定密钥私钥长度为1024

			privateKey, err = rsa.GenerateKey(rand.Reader, 1024)
			if err != nil {
				panic(err)
			}

			//2、取出公钥
			publickey := privateKey.PublicKey
			//3、x509格式化公钥
			pubder, err := x509.MarshalPKIXPublicKey(&publickey)
			if err != nil {
				panic(err)
			}
			//4、pem block
			block := pem.Block{Type: "rsa publickkey",
				Bytes: pubder,
			}
			//5、pem编码得到base64编码
			var buf bytes.Buffer
			pem.Encode(&buf, &block)
			//将编码好的公钥发送给客户端
			_, err = conn.WriteToUDP(buf.Bytes(), raddr)
			if err != nil {
				panic(err)
			}

		}
		if count == 2 {
			//接受客户端发送来的对称密钥,由于客户端发送来的数据是经过16进制编码,因此要解码
			text, err := hex.DecodeString(string(data[:length]))
			if err != nil {
				panic(err)
			}
			if err != nil {
				panic(err)
			}
			//私钥解密,拿到对称加密的密钥
			aesKey, err = rsa.DecryptPKCS1v15(rand.Reader, privateKey, text)

			fmt.Println("对称加密的密钥:", aesKey)
			conn.WriteToUDP([]byte("对称密钥接受完毕"), raddr)

		}
//往后就是对称加密通信
		if count > 2 {
			//创建aes接口
			block, err := aes.NewCipher(aesKey)
			if err != nil {
				panic(err)
			}
			//创建一个使用CTR分组的接口
			stream := cipher.NewCTR(block, aesKey)
                       //解码拿到密文
			cipherText, err := hex.DecodeString(string(data[:length]))
			if err != nil {
				panic(err)
			}
			plainText := make([]byte, len(cipherText))
			stream.XORKeyStream(plainText, cipherText)
			fmt.Println("接受并解析的数据:", string(plainText))
			conn.WriteToUDP([]byte("加密数据接受完毕"), raddr)
		}
	}

}

  client.go

func main() {
	conn, err := net.Dial("udp", "127.0.0.1:8888")
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	count := 0
	var publicKey *rsa.PublicKey
	data := make([]byte, 4096)
	//以下三行产生对称加密的密钥
	hvalue := md5.Sum([]byte("1234abcd"))     //得到16字节二进制哈希值
	hexText := hex.EncodeToString(hvalue[:])  //把二进制转换为16进制字符串 长度为16*2
	aesKey := []byte(hexText)[:aes.BlockSize] //把32字节长的密钥阶段为16字节
	for {
		count++
		if count == 1 {
			//向服务器say hello
			conn.Write([]byte("hello i am client"))
			//阻塞。。。
			//收到服务器发送来的公钥
			n, err := conn.Read(data)
			if err != nil {
				panic(err)
			}
			fmt.Println(string(data[:n]))
			//pem解码
			block, _ := pem.Decode(data[:n])
			//x509解码
			pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
			if err != nil {
				panic(err)
			}

			//类型断言,拿到公钥
			publicKey = pubInterface.(*rsa.PublicKey)
		}
		if count == 2 {
			//使用公钥加密aeskey
			//通过公钥加密的密文是二进制,在网络通信时不要发送二进制,因为有不可见字符
			//最好给他编码,base64或者16进制编码,
			cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, aesKey)
			if err != nil {
				panic(err)
			}
			//发送给服务器
			conn.Write([]byte(hex.EncodeToString(cipherText)))

		}
		//开始使用对称加密通信
		if count > 2 {
			block, err := aes.NewCipher(aesKey)
			if err != nil {
				panic(err)
			}
			//创建ctr模式接口
			text := []byte("[对称加密通信]你吃了吗?")
			stream := cipher.NewCTR(block, aesKey)
			stream.XORKeyStream(text, text)
			conn.Write([]byte(hex.EncodeToString(text)))

		}
		if count > 1 {
			//阻塞
			n, _ := conn.Read(data)
			fmt.Println("接受到的数据:", string(data[:n]))
		}
		time.Sleep(time.Second)
	}
}

  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM