From f5f618ac09975c6100c27aa7f90c8460d9d35c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AF=86=E7=A0=81=E6=BC=8F=E6=B4=9E?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AE=8C=E6=88=90?= <> Date: Sun, 13 Apr 2025 02:05:41 +0800 Subject: [PATCH] add user and rsa --- .idea/workspace.xml | 21 ++- main.go | 354 ++++++++++++++++++++++++++++++++++++++++---- models/User.go | 76 ++++++++++ mydb/initialize.go | 4 +- privateKey.pem | 3 + 5 files changed, 423 insertions(+), 35 deletions(-) create mode 100644 models/User.go create mode 100644 privateKey.pem diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 007b1ae..d2923e4 100755 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,9 +5,9 @@ + - - + + + + + + + + + @@ -78,6 +86,15 @@ + + + + + + + + + diff --git a/main.go b/main.go index 8a51446..aa4e58c 100755 --- a/main.go +++ b/main.go @@ -1,7 +1,14 @@ package main import ( + "bytes" + "crypto/rand" + "crypto/rsa" + "crypto/x509" "database/sql" + "encoding/base64" + "encoding/json" + "encoding/pem" "fmt" mqtt "github.com/eclipse/paho.mqtt.golang" _ "github.com/go-sql-driver/mysql" @@ -10,7 +17,9 @@ import ( _ "go_mqtt/models" "go_mqtt/mydb" _ "go_mqtt/mydb" + "io/ioutil" "log" + "os" "strings" "time" ) @@ -177,6 +186,207 @@ func dbTest() { stmt.Exec(1) } + +// GenRsaKey generates an PKCS#1 RSA keypair of the given bit size in PEM format. +func GenRsaKey(bits int) (prvkey, pubkey []byte, err error) { + // Generates private key. + privateKey, err := rsa.GenerateKey(rand.Reader, bits) + if err != nil { + return + } + derStream := x509.MarshalPKCS1PrivateKey(privateKey) + block := &pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: derStream, + } + prvkey = pem.EncodeToMemory(block) + + // Generates public key from private key. + publicKey := &privateKey.PublicKey + derPkix, err := x509.MarshalPKIXPublicKey(publicKey) + if err != nil { + return + } + block = &pem.Block{ + Type: "RSA PUBLIC KEY", + Bytes: derPkix, + } + pubkey = pem.EncodeToMemory(block) + return +} + + + + +func parsePrivateKey(privateKeyFile string) (*rsa.PrivateKey, error) { + // 读取私钥文件 + keyData, err := ioutil.ReadFile(privateKeyFile) + if err != nil { + return nil, err + } + + // 解析PEM块 + block, _ := pem.Decode(keyData) + if block == nil { + return nil, fmt.Errorf("private key error not block in file") + } + + // 解析RSA私钥 + privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + return nil, err + } + return privateKey, nil +} + +//生成RSA私钥和公钥,保存到文件中 +func GenerateRSAKey(bits int) { + //GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥 + //Reader是一个全局、共享的密码用强随机数生成器 + privateKey, err := rsa.GenerateKey(rand.Reader, bits) + if err != nil { + return + } + //保存私钥 + //通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串 + // X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey) // PKCS1 和 9 是不一致的 + X509PrivateKey, err := x509.MarshalPKCS8PrivateKey(privateKey) + if err != nil { + fmt.Println(err.Error()) + os.Exit(0) + } + //使用pem格式对x509输出的内容进行编码 + //创建文件保存私钥 + privateFile, err := os.Create("private.pem") + if err != nil { + return + } + + //构建一个pem.Block结构体对象 + privateBlock := pem.Block{Type: "PRIVATE KEY", Bytes: X509PrivateKey} + //将数据保存到文件 + pem.Encode(privateFile, &privateBlock) + //保存公钥 + //获取公钥的数据 + publicKey := privateKey.PublicKey + //X509对公钥编码 + X509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey) + if err != nil { + return + } + //pem格式编码 + //创建用于保存公钥的文件 + publicFile, err := os.Create("public.pem") + if err != nil { + return + } + + //创建一个pem.Block结构体对象 + publicBlock := pem.Block{Type: "Public Key", Bytes: X509PublicKey} + //保存到文件 + pem.Encode(publicFile, &publicBlock) +} + +// RSA_Decrypts RSA解密支持分段解密 +func RSA_Decrypts(cipherText []byte, path string) []byte { + //打开文件 + var bytesDecrypt []byte + //file, err := os.Open(path) + //if err != nil { + // fmt.Println(err) + //} + // + ////获取文件内容 + //info, _ := file.Stat() + //buf := make([]byte, info.Size()) + //file.Read(buf) + + // 读取私钥文件 + keyData, err := ioutil.ReadFile(path) + if err != nil { + return nil + } + + //pem解码 + block, _ := pem.Decode(keyData) + //X509解码 + privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + fmt.Println(err.Error()) + os.Exit(0) + } + p := privateKey.(*rsa.PrivateKey) + keySize := p.Size() + srcSize := len(cipherText) + log.Println("密钥长度", keySize, "密文长度", srcSize) + var offSet = 0 + var buffer = bytes.Buffer{} + for offSet < srcSize { + endIndex := offSet + keySize + if endIndex > srcSize { + endIndex = srcSize + } + bytesOnce, err := rsa.DecryptPKCS1v15(rand.Reader, p, cipherText[offSet:endIndex]) + if err != nil { + return nil + } + buffer.Write(bytesOnce) + offSet = endIndex + } + bytesDecrypt = buffer.Bytes() + return bytesDecrypt +} + +// RsaEncryptBlock 公钥加密-分段 +func RsaEncryptBlock(src []byte, path string) (bytesEncrypt []byte, err error) { + //打开文件 + //file, err := os.Open(path) + //if err != nil { + // return + //} + // + ////读取文件的内容 + //info, _ := file.Stat() + //buf := make([]byte, info.Size()) + //file.Read(buf) + + // 读取公钥文件 + keyData, err := ioutil.ReadFile(path) + if err != nil { + return nil,err + } + + //pem解码 + block, _ := pem.Decode(keyData) + //x509解码 + publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + fmt.Println(err) + } + //类型断言 + publicKey := publicKeyInterface.(*rsa.PublicKey) + keySize, srcSize := publicKey.Size(), len(src) + log.Println("密钥长度", keySize, "明文长度", srcSize) + offSet, once := 0, keySize-11 + buffer := bytes.Buffer{} + for offSet < srcSize { + endIndex := offSet + once + if endIndex > srcSize { + endIndex = srcSize + } + // 加密一部分 + bytesOnce, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, src[offSet:endIndex]) + if err != nil { + return nil, err + } + buffer.Write(bytesOnce) + offSet = endIndex + } + bytesEncrypt = buffer.Bytes() + return +} + + func timing(client mqtt.Client) { //定时器,10秒钟执行一次 ticker := time.NewTicker(5 * time.Second) @@ -193,6 +403,27 @@ func timing(client mqtt.Client) { // queryOneDataByMySql(db) // //mydb.Close() //} + + //GenerateRSAKey(2048) + //publicPath := "public.pem" + //privatePath := "private.pem" + // + //var a = []byte("jack") + //encrptTxt, err := RsaEncryptBlock(a, publicPath) + //if err != nil { + // fmt.Println(err.Error()) + //} + //fmt.Println("加密后的字符串:") + //encodeString := base64.StdEncoding.EncodeToString(encrptTxt) + //fmt.Println(encodeString) + //fmt.Println("-------------------") + //decodeByte, err := base64.StdEncoding.DecodeString(encodeString) + //if err != nil { + // fmt.Println(err.Error()) + //} + //decrptCode := RSA_Decrypts(decodeByte, privatePath) + //fmt.Println("解密后的字符串:") + //fmt.Println(string(decrptCode)) } } } @@ -203,38 +434,81 @@ var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Me message := fmt.Sprintf("%s", msg.Payload()) topic := fmt.Sprintf("%s", msg.Topic()) fmt.Println(message) - result := strings.Split(message, " ") - fmt.Println(result[0]) - fmt.Println(result[1]) - - now := time.Now() - temperature := new(models.Temperature) - temperature.CreateDate = now - temperature.DataDate = now.Format("2006-01-02") - temperature.DataHour = now.Format("2006-01-02 15") - temperature.DataMinute = now.Format("2006-01-02 15:04") - temperature.Humidity = result[0] - temperature.Temperature = result[1] - temperature.Topic = topic - - if topic == "WifiSHT/7C87CE9CA4E6/SHT20" { - temperature.LocationDesc = "广东省珠海市高新区唐家湾镇东岸村水风三街28号501" - } - if topic == "WifiSHT/7C87CE9F5CBF/SHT20" { - temperature.LocationDesc = "广东省珠海市金湾区三灶镇百川路1号1栋1单元1508房" - } - if topic == "WifiSHT/4CEBD686B6AA/SHT20" { - temperature.LocationDesc = "广西壮族自治区崇左市天等县天等镇荣华村弄在屯113号" - } - fmt.Println("测温传感器地点:", temperature.LocationDesc) - - //db, err := getMySqlDB() - //if err == nil { - // insertDataByMySql(db,temperature) - // //mydb.Close() - //} + fmt.Println(topic) + + + privatePath := "privateKey.pem" + + if topic == "app_push" { + fmt.Println("珠海电厂APP收到mqtt消息") + decodeByte, err := base64.StdEncoding.DecodeString(message) + if err != nil { + fmt.Println(err.Error()) + } + decrptCode := RSA_Decrypts(decodeByte, privatePath) + fmt.Println("解密后的字符串:") + fmt.Println(string(decrptCode)) + fmt.Println("-----user--------") + var user models.User + json.Unmarshal(decrptCode, &user) + fmt.Println(user) + //models.SaveUser(&user) + + if models.GetUser(&user) { + models.UpdateUser(&user) + }else{ + models.SaveUser(&user) + } + + }else if topic == "app_push_dyw" { + fmt.Println("大亚湾电厂APP收到mqtt消息") + decodeByte, err := base64.StdEncoding.DecodeString(message) + if err != nil { + fmt.Println(err.Error()) + } + decrptCode := RSA_Decrypts(decodeByte, privatePath) + fmt.Println("解密后的字符串:") + fmt.Println(string(decrptCode)) + fmt.Println("-----user--------") + //var user models.User + //json.Unmarshal(decrptCode, &user) + //fmt.Println(user) + // + //if models.GetUser(&user) { + // models.UpdateUser(&user) + //}else{ + // models.SaveUser(&user) + //} + + }else{ + result := strings.Split(message, " ") + fmt.Println(result[0]) + fmt.Println(result[1]) + + now := time.Now() + temperature := new(models.Temperature) + temperature.CreateDate = now + temperature.DataDate = now.Format("2006-01-02") + temperature.DataHour = now.Format("2006-01-02 15") + temperature.DataMinute = now.Format("2006-01-02 15:04") + temperature.Humidity = result[0] + temperature.Temperature = result[1] + temperature.Topic = topic + if topic == "WifiSHT/7C87CE9CA4E6/SHT20" { + temperature.LocationDesc = "广东省珠海市高新区唐家湾镇东岸村水风三街28号501" + } + if topic == "WifiSHT/7C87CE9F5CBF/SHT20" { + temperature.LocationDesc = "广东省珠海市金湾区三灶镇百川路1号1栋1单元1508房" + } + if topic == "WifiSHT/4CEBD686B6AA/SHT20" { + temperature.LocationDesc = "广西壮族自治区崇左市天等县天等镇荣华村弄在屯113号" + } + fmt.Println("测温传感器地点:", temperature.LocationDesc) + models.SaveTemperature(temperature) + } + + - models.SaveTemperature(temperature) //uuid := uuid.New() //models.SaveProduct() @@ -267,6 +541,8 @@ var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Me var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) { fmt.Println("Connected") subTemperature(client) + subAppPush(client) + subAppPushDyw(client) } var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) { @@ -287,6 +563,20 @@ func subTemperature(client mqtt.Client) { fmt.Printf("Subscribed to topic: %s", topic) } +func subAppPush(client mqtt.Client) { + topic := "app_push" + token := client.Subscribe(topic, 2, nil) + token.Wait() + fmt.Printf("Subscribed to topic: %s", topic) +} +func subAppPushDyw(client mqtt.Client) { + topic := "app_push_dyw" + token := client.Subscribe(topic, 2, nil) + token.Wait() + fmt.Printf("Subscribed to topic: %s", topic) +} + + func publish(client mqtt.Client) { num := 999999000000000000 for i := 0; i < num; i++ { @@ -324,6 +614,8 @@ func main() { //sub(client) subTemperature(client) + subAppPush(client) + subAppPushDyw(client) publish(client) //client.Disconnect(1000) diff --git a/models/User.go b/models/User.go new file mode 100644 index 0000000..38e55b0 --- /dev/null +++ b/models/User.go @@ -0,0 +1,76 @@ +package models + +import ( + "errors" + "fmt" + "go_mqtt/mydb" + "gorm.io/gorm" +) + +type User struct { + Username string `gorm:"primaryKey;size:255"` + Password string `gorm:"size:255"` + Date string `gorm:"size:255"` + Imeinum string `gorm:"size:50"` + Sysversion string `gorm:"size:100"` + Phonemodel string `gorm:"size:255"` + Appversion string `gorm:"size:255"` + Name string `gorm:"size:255"` +} + +func init() { + fmt.Println("User init()") + mydb.DB.AutoMigrate(&User{}) +} + +// TableName 会将 User 的表名重写为 `user` +func (User) TableName() string { + return "user" +} + +func SaveUser(user *User) { + result := mydb.DB.Create(&user) + if result.Error != nil { + fmt.Println("Failed to create User:", result.Error) + } else { + fmt.Println("User created successfully!") + } +} + +func UpdateUser(item *User) { + fmt.Println("用户存在,更新操作") + var user User + mydb.DB.First(&user, item.Username) + user.Password=item.Password + user.Date=item.Date + user.Imeinum=item.Imeinum + user.Sysversion=item.Sysversion + user.Phonemodel=item.Phonemodel + user.Appversion=item.Appversion + user.Name=item.Name + mydb.DB.Save(&user) +} + +func GetUser(item *User) bool { + var user User + //mydb.DB.First(&user, item.Username) + + + + result := mydb.DB.First(&user, item.Username).Error + fmt.Println("-----user---->>") + fmt.Println(user) + + if errors.Is(result, gorm.ErrRecordNotFound) { + // 记录不存在 + fmt.Println("用户不存在") + } else if result == nil { + // 记录存在 + fmt.Println("用户存在") + return true + } else { + // 其他错误 + fmt.Println("查询出错") + } + return false +} diff --git a/mydb/initialize.go b/mydb/initialize.go index dae5643..89bd764 100755 --- a/mydb/initialize.go +++ b/mydb/initialize.go @@ -19,8 +19,8 @@ func initDatabase() { //dsn := "root:Skyinno251,@tcp(192.168.2.18:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local" //dsn := "root:Skyinno251,@tcp(47.242.184.139:3306)/appserver?charset=utf8mb4&parseTime=True&loc=Local" - //dsn := "root:Skyinno251,@tcp(localhost:3306)/appserver?charset=utf8mb4&parseTime=True&loc=Local" - dsn := "root:Skyinno251,@tcp(192.168.3.29:3306)/appserver?charset=utf8mb4&parseTime=True&loc=Local" + dsn := "root:Skyinno251,@tcp(localhost:3306)/appserver?charset=utf8mb4&parseTime=True&loc=Local" + //dsn := "root:Skyinno251,@tcp(192.168.3.29:3306)/appserver?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.New(mysql.Config{ DSN: dsn, // DSN data source name diff --git a/privateKey.pem b/privateKey.pem new file mode 100644 index 0000000..cebbd43 --- /dev/null +++ b/privateKey.pem @@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCYwvInDUICXbmWcOAR5hm86mz7WlKL3dDf12MSeIY2jm5QpUSSoMhrJOWLbOt5fXQepPaNO0M30A+3C4SFZrM/9WA5ehazO1u1m1LAkYzoSDRH3MMJsrJC3lCGDeOROteu+safuP9k/npU1YQu/+Ll2xEJNxyvUx4jLGM4LamiMI6ytM3gdnOAGP4YRQo9Etwo6I986yg/seCQC5rza9M4iBamoin7U8h9yOMKrM6xK/k9CcY/vn5+Uhe3Pvk4qj/2Ff3OXkkc1wfdILqdLwLOKL0Tb3ZciwG0p1CKO80yf5hyYoWjqZk5Rcd07nTo2gqTFGfLl9sqI9/+ipMDtnHlAgMBAAECggEATJd5yCC6lusdMRO5FOBUyUaUi9X2i1AU+RZKAynQySvSnbavUgExW58tRCHBUrGW9gJp59ft1N8J8hHhSO18NDY4H7laBlVdnwmYjRqtFo2VQO6sD4G8JRDION5f2iIxn/b2fYDI9H8vILfJRbNgtTSILyGlzTYUZzhLKxCh+8IsN96Nic8wa5COd1vZZmdhf2y8TG8clFWmozaScNSAATx7y+8XLVWjjWiIRZ6xQvx0uQPUParc9KihXXTKR2pA22yPIdz+U4MGD4kC0eczlcFKZ/dYv9e7OIGgnJfT0idSCu7nYb1pxJ1LxD9fS6IScNTF5dSe0OIL98e+XdyoAQKBgQDRep+5cW4iAKrEMH+djmcXAkoMiYtNVtnu0efLE8dP6vjYytQi368X9SdcASbfrQ31eEZmr/xQnlUF8oyHGkI38YS8dpAHzQcrkP3BljbbzB/3gJZaUdghGsDrK0xAJIzzmFKQpeKnGtr23vxUgaGrNsCYvQ0eQ7+5056KXS4r5QKBgQC6r8xtRSaje6L4WIydjWvYywsmRO0Of0aJLMDA/Wt2MWhHfh7ba9oI1cKGN80ap7xB2a9lQLgpv+C53wNtE5SpvjxsikAj96nUMMhGy9ojXrUith6HQhiINETz6Shnznd+AyrXP6KI/RpfA5nkDB5nrJxODwtYLP467IL7Cv7OAQKBgQCl4KxKdH/5fP28jYsAgJsxpSZt9xzQCU5Zxu396ZOSvUaApVyGoQpNtluMh3z48lhzYOKevgzW6gn5w69z7F8zXZT2iAxVoQ1kelP2z7RxKJrHqpNkwhqbXEwX7RlcUZUr8BqxYCqymJl7k+fMIzqaEalBSbLxnEReKi0I8/Bz4QKBgHK4b0ZCtVDHPEmimJ6E9l4dv/c/afF7swu+zaCK2ouiJvOwBCRQbYb6XPR/u/GCXASXUdpF4CX/vIhcDE3uN2/r8FO+zVWM7vbvF1OyF5WesG7pPW9e5ZZlkG3WvLa1wOZV6fCmMSo/ZwI2Q05JSDHrd43cXttLotrw1jiQ9C4BAoGBAKi4SOoOVQ5J5HQCDkBwPbG1AOLHFinzfoDl26GF/8Hy7fmmd1JiRTFldQp/A9VTAABz3sVYmMB92HSIaJhuDMoYJNI2Cf/cZifsv7vUL8cbLn+lPsKsebiuB0m0g4P2qLwLfegfNGEgA7lA5HIz3SELqbdp3iuqJeQl1fsJqD74 +-----END PRIVATE KEY-----