diff --git a/README.md b/README.md
index 266fe2f..47dc757 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,8 @@
# KGC_TEST(狠狠感谢ljn)
-#### 1.调用Miracl库,基本实现了密钥生成
+### 1.调用Miracl库,基本实现了密钥生成
-#### 2.实现了Go语言调用C静态库,完成了大数、点和Go语言字节切片的相互转换
+### 2.实现了Go语言调用C静态库,完成了大数、点和Go语言字节切片的相互转换
+
+### 3.实现了基本的无证书的签名验签功能(Go语言实现和C语言实现)
-#### 3.实现了基本的无证书的签名验签功能
\ No newline at end of file
diff --git a/go_test/.idea/.gitignore b/go_test/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/go_test/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/go_test/.idea/.name b/go_test/.idea/.name
new file mode 100644
index 0000000..30de634
--- /dev/null
+++ b/go_test/.idea/.name
@@ -0,0 +1 @@
+main.go
\ No newline at end of file
diff --git a/go_test/.idea/go_test.iml b/go_test/.idea/go_test.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/go_test/.idea/go_test.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/go_test/.idea/modules.xml b/go_test/.idea/modules.xml
new file mode 100644
index 0000000..3b69742
--- /dev/null
+++ b/go_test/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/go_test/cert/pkpub.txt b/go_test/cert/pkpub.txt
new file mode 100644
index 0000000..462ddf4
--- /dev/null
+++ b/go_test/cert/pkpub.txt
@@ -0,0 +1 @@
+7196e9722d561a0fea21485fc16140096cc9b88f7174aec7508f14a7b85b61ba299292c726367bbcbf8f00b977849164bf9d3fd6260e55dd6498517bc0dec541
\ No newline at end of file
diff --git a/go_test/cert/prikey.txt b/go_test/cert/prikey.txt
new file mode 100644
index 0000000..101ec7b
--- /dev/null
+++ b/go_test/cert/prikey.txt
@@ -0,0 +1 @@
+6d0770e05a3ce79a32e2aea78fcda3bcb4054b86df8369e50a5ab4b7e26f1d38
\ No newline at end of file
diff --git a/go_test/cert/pubkey.txt b/go_test/cert/pubkey.txt
new file mode 100644
index 0000000..77a951d
--- /dev/null
+++ b/go_test/cert/pubkey.txt
@@ -0,0 +1 @@
+226383fbed07e3841affd83f7681f90602ad08e57bd27d6cad9a666d81b8b7ef17672b52cbc215c51d308299a1b640d6c0229bf761364cca3eae31d16c13da29
\ No newline at end of file
diff --git a/go_test/go.mod b/go_test/go.mod
new file mode 100644
index 0000000..e26fe90
--- /dev/null
+++ b/go_test/go.mod
@@ -0,0 +1,3 @@
+module example.com/m/v2
+
+go 1.20
diff --git a/go_test/gofunc.go b/go_test/gofunc.go
new file mode 100644
index 0000000..29fe98c
--- /dev/null
+++ b/go_test/gofunc.go
@@ -0,0 +1,293 @@
+package main
+
+import (
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/sha256"
+ "errors"
+ "fmt"
+ "math/big"
+ "os"
+ "path/filepath"
+)
+
+func hash1(curve elliptic.Curve, ID []byte, Qx, Qy, PKx, PKy *big.Int) *big.Int {
+ // 创建 SHA-256 散列器
+ h := sha256.New()
+
+ // 更新散列器以包含字符串 ID 的内容
+ h.Write(ID)
+
+ // 更新散列器以包含点 Q 的坐标信息
+ h.Write(Qx.Bytes())
+ h.Write(Qy.Bytes())
+
+ // 更新散列器以包含公钥 PK_pub 的坐标信息
+ h.Write(PKx.Bytes())
+ h.Write(PKy.Bytes())
+
+ // 计算 SHA-256 散列值
+ hash := h.Sum(nil)
+
+ // 将散列值转换为大整数
+ hBig := new(big.Int).SetBytes(hash)
+
+ // 对大整数 hBig 进行幂运算,幂为 1,模数为 n
+ hBig.Mod(hBig, curve.Params().N)
+
+ return hBig
+}
+
+func hash2(curve elliptic.Curve, ID []byte, Xx, Xy *big.Int) *big.Int {
+ // 计算 hash 值 H_2(ID, X)
+ hash := sha256.New()
+
+ hash.Write(ID)
+
+ hash.Write(Xx.Bytes())
+ hash.Write(Xy.Bytes())
+
+ // 计算 SHA-256 散列值
+ h2 := hash.Sum(nil)
+
+ // 转换为大整数
+ h2Big := new(big.Int).SetBytes(h2)
+
+ // 对大整数 h2Big 进行幂运算,幂为 1,模数为 n
+ h2Big.Mod(h2Big, curve.Params().N)
+
+ return h2Big
+}
+
+func hash3(curve elliptic.Curve, ID, msg []byte, Qx, Qy, Ux, Uy, PKx, PKy *big.Int) *big.Int {
+ // 创建 SHA-256 散列器
+ h := sha256.New()
+
+ // 更新散列器以包含字符串 ID 的内容
+ h.Write(ID)
+
+ // 更新散列器以包含字符串 msg 的内容
+ h.Write(msg)
+
+ // 更新散列器以包含点 Q 的坐标信息
+ h.Write(Qx.Bytes())
+ h.Write(Qy.Bytes())
+
+ // 更新散列器以包含点 U 的坐标信息
+ h.Write(Ux.Bytes())
+ h.Write(Uy.Bytes())
+
+ // 更新散列器以包含公钥 PK_pub 的坐标信息
+ h.Write(PKx.Bytes())
+ h.Write(PKy.Bytes())
+
+ // 计算 SHA-256 散列值
+ hash := h.Sum(nil)
+
+ // 将散列值转换为大整数
+ hBig := new(big.Int).SetBytes(hash)
+ hBig.Mod(hBig, curve.Params().N)
+
+ return hBig
+}
+
+func equal(lx, ly, rx, ry *big.Int) error {
+ if lx.Cmp(rx) == 0 && ly.Cmp(ry) == 0 {
+ return nil
+ }
+ return errors.New("point compare failed ")
+
+}
+
+func genKGCKey(curve elliptic.Curve) (*big.Int, *big.Int, *big.Int) {
+ // 随机生成 msk
+ msk, _ := rand.Int(rand.Reader, curve.Params().N)
+ PKx, PKy := curve.ScalarBaseMult(msk.Bytes())
+ return PKx, PKy, msk
+}
+
+func genSecret(curve elliptic.Curve) (*big.Int, *big.Int, *big.Int) {
+ // 随机生成 x
+ x, _ := rand.Int(rand.Reader, curve.Params().N)
+ Xx, Xy := curve.ScalarBaseMult(x.Bytes())
+ return Xx, Xy, x
+}
+
+func genPartialKey(curve elliptic.Curve, ID []byte, msk, Xx, Xy, PKx, PKy *big.Int) (*big.Int, *big.Int, *big.Int) {
+ // 随机生成 r
+ r, _ := rand.Int(rand.Reader, curve.Params().N)
+ Rx, Ry := curve.ScalarBaseMult(r.Bytes())
+
+ //计算h2的hash值
+ h2Big := hash2(curve, ID, Xx, Xy)
+
+ //计算 h2Big * X
+ tx, ty := curve.ScalarMult(Xx, Xy, h2Big.Bytes())
+
+ //计算 Q = R + h2 * X
+ Qx, Qy := curve.Add(Rx, Ry, tx, ty)
+
+ //计算hash1的值
+ h1Big := hash1(curve, ID, Qx, Qy, PKx, PKy)
+
+ //计算 d = r + msk * h1 mod n
+ temp := new(big.Int).Mul(msk, h1Big)
+ d := new(big.Int).Add(r, temp)
+ d.Mod(d, curve.Params().N)
+ return d, Qx, Qy
+
+}
+
+func VerifyEquation(curve elliptic.Curve, ID []byte, d, Qx, Qy, Xx, Xy, PKx, PKy *big.Int) error {
+ //计算等式左值 + h2 * X
+ lx, ly := curve.ScalarBaseMult(d.Bytes())
+ h2Big := hash2(curve, ID, Xx, Xy)
+ h2Xx, h2Xy := curve.ScalarMult(Xx, Xy, h2Big.Bytes())
+ lx, ly = curve.Add(lx, ly, h2Xx, h2Xy)
+
+ //计算 Q + h1 * PK(t)
+ h1Big := hash1(curve, ID, Qx, Qy, PKx, PKy)
+ tx, ty := curve.ScalarMult(PKx, PKy, h1Big.Bytes())
+
+ rx, ry := curve.Add(Qx, Qy, tx, ty)
+
+ err := equal(lx, ly, rx, ry)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func genPriKey(curve elliptic.Curve, ID []byte, x, d, Xx, Xy *big.Int) *big.Int {
+ //计算h2Big
+ h2Big := hash2(curve, ID, Xx, Xy)
+
+ //计算s = d + h2Big * x
+ temp := new(big.Int).Mul(h2Big, x)
+ sUser := new(big.Int).Add(d, temp)
+
+ //s = s mod n
+ sUser = sUser.Mod(sUser, curve.Params().N)
+
+ return sUser
+}
+
+func SignThumb(curve elliptic.Curve, ID, msg []byte, s, Qx, Qy, PKx, PKy *big.Int) (*big.Int, *big.Int, *big.Int) {
+ // 生成小于素数 的随机数 u
+ u, _ := rand.Int(rand.Reader, curve.Params().N)
+
+ // 生成点U
+ Ux, Uy := curve.ScalarMult(curve.Params().Gx, curve.Params().Gy, u.Bytes())
+
+ //计算h3
+ h3 := hash3(curve, ID, msg, Qx, Qy, Ux, Uy, PKx, PKy)
+
+ // 计算 v = u + h3 * s mod n
+ // 计算 tmp = sa * h_3_big
+ tmp := new(big.Int).Mul(h3, s)
+
+ // 计算 v = u + tmp
+ v := new(big.Int).Add(u, tmp)
+
+ // 计算 v = v mod N
+ v.Mod(v, curve.Params().N)
+
+ return Ux, Uy, v
+}
+
+func VerifyThumb(curve elliptic.Curve, ID, msg []byte, Qx, Qy, PKx, PKy, Ux, Uy, v *big.Int) error {
+ //计算h1和h3
+ h1Big := hash1(curve, ID, Qx, Qy, PKx, PKy)
+ h3Big := hash3(curve, ID, msg, Qx, Qy, Ux, Uy, PKx, PKy)
+
+ //验证等式 v*P = U + h_3(Q + h_1 * PK_pub)
+ //等式左边
+ lx, ly := curve.ScalarBaseMult(v.Bytes())
+
+ // 计算 t = h_1_big * PK_pub
+ tx, ty := curve.ScalarMult(PKx, PKy, h1Big.Bytes())
+
+ // 计算 out = Q + t
+ tx, ty = curve.Add(Qx, Qy, tx, ty)
+
+ // 计算 t = h_3_big * t
+ tx, ty = curve.ScalarMult(tx, ty, h3Big.Bytes())
+
+ // 计算 t = U + tmp_p
+ rx, ry := curve.Add(Ux, Uy, tx, ty)
+
+ //比较等式左右两值是否相等
+ err := equal(lx, ly, rx, ry)
+ if err != nil {
+ fmt.Println("invalid!")
+ return err
+ }
+ fmt.Println("valid!")
+ return nil
+}
+
+func writeToFolder(directory, filename string, data []byte) error {
+ // 检查 cert 文件夹是否存在
+ if _, err := os.Stat(directory); os.IsNotExist(err) {
+ // 如果文件夹不存在,则创建它
+ err := os.Mkdir(directory, 0755)
+ if err != nil {
+ return fmt.Errorf("创建文件夹时出错: %v", err)
+ }
+ }
+
+ // 构造文件的完整路径
+ filePath := filepath.Join(directory, filename)
+
+ err := os.WriteFile(filePath, []byte(data), 0644)
+ if err != nil {
+ return fmt.Errorf("写入文件时出错: %v", err)
+ }
+ fmt.Println("字符串已成功写入文件:", filePath)
+ return nil
+}
+
+func mergeBigInts(bigInts ...*big.Int) []byte {
+ var mergedBytes []byte
+
+ for _, num := range bigInts {
+ numBytes := []byte(num.Text(16))
+ mergedBytes = append(mergedBytes, numBytes...)
+ }
+
+ return mergedBytes
+}
+
+func readFileFromDirectory(directory, filename string) ([]byte, error) {
+ // 构造文件的完整路径
+ filePath := filepath.Join(directory, filename)
+
+ // 读取文件内容
+ data, err := os.ReadFile(filePath)
+ if err != nil {
+ return nil, err
+ }
+
+ return data, nil
+}
+
+func BytesToBig(bytes []byte) *big.Int {
+ //不能直接转为big,转为字符串后用16进制解码
+ big := new(big.Int)
+ big.SetString(string(bytes), 16)
+ return big
+}
+
+func bytes_halve(slice []byte) ([]byte, []byte) {
+ length := len(slice)
+
+ // 计算每个部分的长度
+ halfLength := length / 2
+
+ // 切分切片
+ part1 := slice[:halfLength]
+ part2 := slice[halfLength:]
+
+ return part1, part2
+}
diff --git a/go_test/main.go b/go_test/main.go
new file mode 100644
index 0000000..bc926ff
--- /dev/null
+++ b/go_test/main.go
@@ -0,0 +1,79 @@
+package main
+
+import (
+ "crypto/elliptic"
+ "fmt"
+)
+
+func main() {
+
+ // 创建 P256 曲线
+ curve := elliptic.P256()
+
+ //初始化用户id 和消息
+ ID := []byte("1234567890111213141516171819202122232425")
+ msg := []byte("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD")
+
+ //生成KGC公私钥
+ PKx, PKy, msk := genKGCKey(curve)
+
+ //用户生成秘密值,后经过运算返回点
+ Xx, Xy, x := genSecret(curve)
+
+ //KGC生成用户的部分私钥d和全部公钥Q
+ d, Qx, Qy := genPartialKey(curve, ID, msk, Xx, Xy, PKx, PKy)
+
+ //用户验证生成的部分私钥和全部公钥是否有效
+ err := VerifyEquation(curve, ID, d, Qx, Qy, Xx, Xy, PKx, PKy)
+ if err != nil {
+ fmt.Println("KGC生成的私钥无效!!!")
+ return
+ }
+ fmt.Println("生成的私钥有效!")
+
+ //用户生成全部私钥
+ s := genPriKey(curve, ID, x, d, Xx, Xy)
+
+ //用户对消息签名
+ Ux, Uy, v := SignThumb(curve, ID, msg, s, Qx, Qy, PKx, PKy)
+
+ //接收方对消息进行验证
+ err = VerifyThumb(curve, ID, msg, Qx, Qy, PKx, PKy, Ux, Uy, v)
+ if err != nil {
+ fmt.Println("签名验证失败!")
+ }
+
+ //fmt.Printf("KGC基点为:\nP_x:%s\nP_y:%s\n", curve.Params().Gx, curve.Params().Gy)
+ //fmt.Printf("用户的公钥为:\nPK_pub_s:%x\nPK_pub_s:%x\n", PKx, PKy)
+
+ //fmt.Println(append([]byte(PKx.Text(16)), []byte(PKy.Text(16))...))
+
+ pubdata := mergeBigInts(Qx, Qy)
+ kgcpub := mergeBigInts(PKx, PKy)
+ pridata := mergeBigInts(s)
+
+ fmt.Printf("KGC公钥为:%s\n", kgcpub)
+ fmt.Printf("用户公钥为:%s\n", pubdata)
+ fmt.Printf("用户私钥为:%s\n", pridata)
+ //fmt.Printf("用户ID为:\nID:%s\n", ID)
+ writeToFolder("./cert", "pkpub.txt", kgcpub)
+ writeToFolder("./cert", "prikey.txt", pridata)
+ writeToFolder("./cert", "pubkey.txt", pubdata)
+
+ data, _ := readFileFromDirectory("./cert", "pubkey.txt")
+ fmt.Println(data)
+ dax, day := bytes_halve(data)
+
+ Dx := BytesToBig(dax)
+ Dy := BytesToBig(day)
+ fmt.Println(Dx, Dy)
+ onCurve := curve.IsOnCurve(Dx, Dy)
+
+ if onCurve {
+ fmt.Println("点在椭圆曲线上")
+ } else {
+ fmt.Println("点不在椭圆曲线上")
+ }
+
+ //return
+}