use token instead of using tls cert

This commit is contained in:
www-git-cn 2024-04-24 17:06:06 +08:00
parent 2e1c6a2498
commit 53b4b70ed7
19 changed files with 638 additions and 93 deletions

View File

@ -1,74 +0,0 @@
# FlashChain
## 1、需求
运行FlashChain你至少需要golang (version >= 1.19).
## 2、如何去使用
### 运行代码
`go run main.go`
## 3、修改配置文件
### 配置文件地址(config--config.yaml).
```yml
block:
# 区块大小
blksize: 50
# 区块的生成时间单位ms
createBlockTime: 300
# 是否查看状态数据库
showStateDB: true
# 是否查看区块链账本数据库
showBlockchainDB: true
config:
# 地址数量
addrNum: 1000
# 发送的事务数量
txNum: 1000
# 发送事务时的偏斜度
skewness: 1
# 发送事务的读占比
ratio: 0.5
# 是否限制发送速率
isLimited: false
# 发送速率(单位:个/每秒)
rate: 35000
# 合约名(目前只支持 SmallBank 和 KvStore 两个合约)
contractName: "SmallBank"
organizations:
- name: org1
ports:
- ":1308"
client:
MSPID: "*.lkq.com"
IdentityPath: "cert/client.pem"
KeyPath: "cert/client.key"
peer:
address: ":1308"
MSPID: "*.lkq.com"
IdentityPath: "cert/peer.pem"
KeyPath: "cert/peer.key"
order:
address: ":1309"
MSPID: "*.lkq.com"
IdentityPath: "cert/order.pem"
KeyPath: "cert/order.key"
ca:
crt: "cert/ca.crt"
```
## 4、证明满足原子性和一致性
打开main.go中用于测试事务的原子性的代码
```golang
// 将以下代码注释打开
//from := source.Intn(int(config.AddrNum))
//to := source.Intn(int(config.AddrNum))
//args = [][]byte{
// []byte("sendPayment"),
// []byte(fmt.Sprintf("%x", from)),
// []byte(fmt.Sprintf("%x", to)),
// []byte("10"),
//}
```

Binary file not shown.

BIN
blockDB_1408/000025.log Normal file

Binary file not shown.

BIN
blockDB_1408/000027.ldb Normal file

Binary file not shown.

View File

@ -1 +1 @@
MANIFEST-000000
MANIFEST-000026

1
blockDB_1408/CURRENT.bak Normal file
View File

@ -0,0 +1 @@
MANIFEST-000023

View File

@ -6,3 +6,116 @@
20:19:40.896273 db@open done T·6.1627ms
20:19:41.776608 db@close closing
20:19:41.777120 db@close done T·512.1µs
=============== Apr 18, 2024 (CST) ===============
22:03:00.561989 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
22:03:00.562985 version@stat F·[] S·0B[] Sc·[]
22:03:00.562985 db@open opening
22:03:00.562985 journal@recovery F·1
22:03:00.563982 journal@recovery recovering @1
22:03:00.569048 memdb@flush created L0@2 N·10 S·73KiB "blo..\x11\x17\xd6,v10":"blo..n\x01\x04,v9"
22:03:00.570044 version@stat F·[1] S·73KiB[73KiB] Sc·[0.25]
22:03:00.581352 db@janitor F·3 G·0
22:03:00.581352 db@open done T·18.3669ms
22:03:01.313892 db@close closing
22:03:01.313892 db@close done T·0s
=============== Apr 18, 2024 (CST) ===============
22:03:43.483566 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
22:03:43.484562 version@stat F·[1] S·73KiB[73KiB] Sc·[0.25]
22:03:43.484562 db@open opening
22:03:43.485558 journal@recovery F·1
22:03:43.485558 journal@recovery recovering @3
22:03:43.489545 memdb@flush created L0@5 N·20 S·69KiB "blo..\x11\x17\xd6,d12":"blo..n\x01\x04,d21"
22:03:43.490542 version@stat F·[2] S·143KiB[143KiB] Sc·[0.50]
22:03:43.502502 db@janitor F·4 G·0
22:03:43.502502 db@open done T·17.9395ms
22:03:43.586702 db@close closing
22:03:43.586702 db@close done T·0s
=============== Apr 22, 2024 (CST) ===============
15:33:20.698996 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
15:33:20.698996 version@stat F·[2] S·143KiB[143KiB] Sc·[0.50]
15:33:20.698996 db@open opening
15:33:20.699993 journal@recovery F·1
15:33:20.699993 journal@recovery recovering @6
15:33:20.709958 memdb@flush created L0@8 N·18 S·63KiB "blo..\xb6\x9eg,d33":"blo..n\x01\x04,d42"
15:33:20.711963 version@stat F·[3] S·206KiB[206KiB] Sc·[0.75]
15:33:20.727650 db@janitor F·5 G·0
15:33:20.727650 db@open done T·28.6542ms
15:33:21.553041 db@close closing
15:33:21.553041 db@close done T·0s
=============== Apr 24, 2024 (CST) ===============
16:48:03.414524 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
16:48:03.415562 version@stat F·[3] S·206KiB[206KiB] Sc·[0.75]
16:48:03.415562 db@open opening
16:48:03.415562 journal@recovery F·1
16:48:03.418338 journal@recovery recovering @9
16:48:03.424210 memdb@flush created L0@11 N·16 S·67KiB "blo..-&\x8f,v65":"blo..n\x01\x03,d59"
16:48:03.424777 version@stat F·[4] S·274KiB[274KiB] Sc·[1.00]
16:48:03.439725 db@janitor F·6 G·0
16:48:03.439725 db@open done T·24.1639ms
16:48:03.439725 table@compaction L0·4 -> L1·0 S·274KiB Q·68
16:48:03.447363 table@build created L1@14 N·8 S·66KiB "blo..-&\x8f,v65":"blo..n\x01\x03,v66"
16:48:03.447363 version@stat F·[0 1] S·66KiB[0B 66KiB] Sc·[0.00 0.00]
16:48:03.453340 table@compaction committed F-3 S-207KiB Ke·0 D·56 T·13.6142ms
16:48:03.453845 table@remove removed @11
16:48:03.453845 table@remove removed @8
16:48:03.454850 table@remove removed @5
16:48:03.454976 table@remove removed @2
16:48:04.364509 db@close closing
16:48:04.364509 db@close done T·0s
=============== Apr 24, 2024 (CST) ===============
16:53:40.438835 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
16:53:40.439835 version@stat F·[0 1] S·66KiB[0B 66KiB] Sc·[0.00 0.00]
16:53:40.439835 db@open opening
16:53:40.439835 journal@recovery F·1
16:53:40.442835 journal@recovery recovering @12
16:53:40.447835 memdb@flush created L0@15 N·18 S·69KiB "blo..-&\x8f,d69":"blo..n\x01\x04,v85"
16:53:40.447835 version@stat F·[1 1] S·136KiB[69KiB 66KiB] Sc·[0.25 0.00]
16:53:40.459551 db@janitor F·4 G·0
16:53:40.459551 db@open done T·19.7158ms
16:53:41.451901 db@close closing
16:53:41.452419 db@close done T·517.1µs
=============== Apr 24, 2024 (CST) ===============
16:54:13.763685 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
16:54:13.764685 version@stat F·[1 1] S·136KiB[69KiB 66KiB] Sc·[0.25 0.00]
16:54:13.764685 db@open opening
16:54:13.764685 journal@recovery F·1
16:54:13.764685 journal@recovery recovering @16
16:54:13.768693 memdb@flush created L0@18 N·18 S·64KiB "blo..\x17>\x16,v103":"blo..n\x01\x04,d97"
16:54:13.769685 version@stat F·[2 1] S·200KiB[133KiB 66KiB] Sc·[0.50 0.00]
16:54:13.780687 db@janitor F·5 G·0
16:54:13.780687 db@open done T·16.0024ms
16:54:13.872235 db@close closing
16:54:13.872747 db@close done T·512µs
=============== Apr 24, 2024 (CST) ===============
17:02:38.948709 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
17:02:38.948709 version@stat F·[2 1] S·200KiB[133KiB 66KiB] Sc·[0.50 0.00]
17:02:38.948709 db@open opening
17:02:38.948709 journal@recovery F·1
17:02:38.949706 journal@recovery recovering @19
17:02:38.953708 memdb@flush created L0@21 N·16 S·68KiB "blo..\x17>\x16,d107":"blo..n\x01\x03,d114"
17:02:38.954701 version@stat F·[3 1] S·269KiB[202KiB 66KiB] Sc·[0.75 0.00]
17:02:38.966383 db@janitor F·6 G·0
17:02:38.966383 db@open done T·17.6743ms
17:02:39.839266 db@close closing
17:02:39.840346 db@close done T·1.0809ms
=============== Apr 24, 2024 (CST) ===============
17:03:47.548607 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
17:03:47.549611 version@stat F·[3 1] S·269KiB[202KiB 66KiB] Sc·[0.75 0.00]
17:03:47.549611 db@open opening
17:03:47.549611 journal@recovery F·1
17:03:47.550605 journal@recovery recovering @22
17:03:47.554605 memdb@flush created L0@24 N·16 S·68KiB "blo..\n\x1f\",v137":"blo..n\x01\x03,d131"
17:03:47.555606 version@stat F·[4 1] S·338KiB[271KiB 66KiB] Sc·[1.00 0.00]
17:03:47.568002 db@janitor F·7 G·0
17:03:47.568002 db@open done T·18.3915ms
17:03:47.568507 table@compaction L0·4 -> L1·1 S·338KiB Q·140
17:03:47.575714 table@build created L1@27 N·8 S·68KiB "blo..\n\x1f\",v137":"blo..n\x01\x03,v138"
17:03:47.575714 version@stat F·[0 1] S·68KiB[0B 68KiB] Sc·[0.00 0.00]
17:03:47.581257 table@compaction committed F-4 S-269KiB Ke·0 D·68 T·12.6705ms
17:03:47.581763 table@remove removed @24
17:03:47.581763 table@remove removed @21
17:03:47.581763 table@remove removed @18
17:03:47.581763 table@remove removed @15
17:03:47.581763 table@remove removed @14
17:03:47.659984 db@close closing
17:03:47.659984 db@close done T·0s

Binary file not shown.

Binary file not shown.

View File

@ -98,5 +98,5 @@ func (os *OrderServer) Start() error {
pb.RegisterChaincodeSupportServer(server.Server, os)
return server.Start()
}

View File

@ -104,3 +104,41 @@ func CheckAuth(ctx context.Context) (username string) {
// 返回从JWT令牌中提取的用户名
return clientClaims.Username
}
// 用于验证token
func Check(ctx context.Context) bool {
// 从上下文中获取JWT令牌字符串
tokenStr, err := getTokenFromContext(ctx)
if err != nil {
panic("get token from context error")
}
// 定义用于解析JWT令牌的自定义声明结构体
var clientClaims Claims
// 解析JWT令牌并将声明解析到自定义声明结构体中
token, err := jwt.ParseWithClaims(tokenStr, &clientClaims, func(token *jwt.Token) (interface{}, error) {
// 检查JWT令牌的算法是否为HS256如果不是则抛出错误
if token.Header["alg"] != "HS256" {
panic("ErrInvalidAlgorithm")
}
// 返回用于验证签名的密钥,这里是一个固定的密钥 "verysecret"
return []byte("verysecret"), nil
})
fmt.Println(token)
if err != nil {
return false
}
// 检查JWT令牌是否有效如果无效则抛出错误
if !token.Valid {
return false
}
if clientClaims.Username != "Wuxinyu" {
return false
}
return true
}

View File

@ -17,6 +17,8 @@ type RequestServer struct {
pb.UnimplementedPingServer
}
var key string = "0123456789abcdef"
func (s *RequestServer) Login(ctx context.Context, in *pb.LoginRequest) (*pb.LoginReply, error) {
//实现aes解密
// 解密字符串
@ -50,12 +52,6 @@ func (s *RequestServer) SayHello(ctx context.Context, in *pb.PingMessage) (*pb.P
return &pb.PingMessage{Greeting: msg}, nil
}
// 使用AES进行加解密
// 定义要加密的字符串和密钥
var (
key string = "0123456789abcdef"
)
func encrypt(plainText string, key string) (string, error) {
keyBytes := []byte(key)

View File

@ -50,6 +50,19 @@ func NewServer(address string) (*Server, error) {
return nil, err
}
//普通方法一元拦截器grpc.UnaryInterceptor
/*interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
if !is_ahtu {
handler(ctx, req)
is_ahtu = true
}
if Check(ctx) {
handler(ctx, req)
}
return
}
*/
var serverOpts []grpc.ServerOption
serverKeepAliveParameters := keepalive.ServerParameters{
@ -69,6 +82,7 @@ func NewServer(address string) (*Server, error) {
serverOpts = append(serverOpts, grpc.ConnectionTimeout(connectionTimeout))
//serverOpts = append(serverOpts, grpc.UnaryInterceptor(interceptor))
// create a gRPC server object
grpcServer := grpc.NewServer(serverOpts...)
request_server := &RequestServer{}

View File

@ -5,7 +5,7 @@ import (
"fmt"
"schain/config"
"schain/peer/ledger"
"schain/peer/shim/internal"
"schain/peer/token"
pb "schain/proto"
"strings"
"sync/atomic"
@ -99,7 +99,7 @@ func (cs *ChaincodeServer) GetBlockInfo(ctx context.Context, e *pb.Empty) (*pb.B
log.Debug("get BlockchainInfo fail", err)
}
for BlockNum != info.Height {
info, err = Blockchain.GetBlockchainInfo()
info, _ = Blockchain.GetBlockchainInfo()
}
atomic.AddUint64(&BlockNum, 1)
return info, nil
@ -133,12 +133,17 @@ func (cs *ChaincodeServer) Start() error {
var err error
tlsCfg, err := internal.LoadTLSConfig()
/*tlsCfg, err := internal.LoadTLSConfig()
if err != nil {
return err
}
server, err := internal.NewServer(cs.Address, tlsCfg)
if err != nil {
return err
}*/
server, err := token.NewServer(cs.Address)
if err != nil {
return err
}

View File

@ -5,7 +5,7 @@ import (
"fmt"
"io"
"schain/config"
"schain/peer/shim/internal"
"schain/peer/token"
pb "schain/proto"
"time"
@ -18,17 +18,18 @@ func userChaincodeStreamGetter(address string) (pb.ChaincodeSupportClient, error
return nil, errors.New("flag 'peer.address' must be set")
}
conf, err := internal.LoadConfig()
/*conf, err := internal.LoadConfig()
if err != nil {
return nil, err
}*/
//此处address为peer address
conn, err := token.NewClient(address)
if err != nil {
return nil, err
}
conn, err := internal.NewClientConn(address, conf)
if err != nil {
return nil, err
}
return internal.NewRegisterClient(conn)
return token.NewRegisterClient(conn)
}
type peerStreamGetter func(address string) (pb.ChaincodeSupportClient, error)

144
peer/token/authtoken.go Normal file
View File

@ -0,0 +1,144 @@
package token
import (
"context"
"fmt"
"time"
"github.com/dgrijalva/jwt-go"
"google.golang.org/grpc/metadata"
)
// 创建token
func CreateToken(userName string) (tokenString string) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"iss": "grpc-token",
"aud": "grpc-token",
"nbf": time.Now().Unix(),
"exp": time.Now().Add(time.Hour).Unix(),
"sub": "user",
"username": userName,
"timestamp": time.Now().String(),
})
//根据key值签名token
tokenString, err := token.SignedString([]byte("verysecret"))
if err != nil {
panic(err)
}
return tokenString
}
// AuthTokenn 自定义认证
type AuthToken struct {
Token string
}
// 实现了PerRPCCredentials接口获取payload
func (c AuthToken) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{
"authorization": c.Token,
}, nil
}
func (c AuthToken) RequireTransportSecurity() bool {
return false
}
// Claims defines the struct containing the token claims.
type Claims struct {
jwt.StandardClaims
// 添加自定义字段
Username string `json:"username"`
Timestamp string `json:"timestamp"`
}
// Step1. 从 context 的 metadata 中,取出 token
func getTokenFromContext(ctx context.Context) (string, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return "", fmt.Errorf("ErrNoMetadataInContext")
}
// md 的类型是 type MD map[string][]string
token, ok := md["authorization"]
if !ok || len(token) == 0 {
return "", fmt.Errorf("ErrNoAuthorizationInMetadata")
}
// 因此token 是一个字符串数组,只用了 token[0]
return token[0], nil
}
func CheckAuth(ctx context.Context) (username string) {
// 从上下文中获取JWT令牌字符串
tokenStr, err := getTokenFromContext(ctx)
if err != nil {
panic("get token from context error") // 如果获取令牌出错,则抛出错误
}
// 定义用于解析JWT令牌的自定义声明结构体
var clientClaims Claims
// 解析JWT令牌并将声明解析到自定义声明结构体中
token, err := jwt.ParseWithClaims(tokenStr, &clientClaims, func(token *jwt.Token) (interface{}, error) {
// 检查JWT令牌的算法是否为HS256如果不是则抛出错误
if token.Header["alg"] != "HS256" {
panic("ErrInvalidAlgorithm")
}
// 返回用于验证签名的密钥,这里是一个固定的密钥 "verysecret"
return []byte("verysecret"), nil
})
fmt.Println(token)
if err != nil {
panic("jwt parse error") // 如果解析JWT出错则抛出错误
}
// 检查JWT令牌是否有效如果无效则抛出错误
if !token.Valid {
panic("ErrInvalidToken")
}
// 返回从JWT令牌中提取的用户名
return clientClaims.Username
}
// 用于验证token
func Check(ctx context.Context) bool {
// 从上下文中获取JWT令牌字符串
tokenStr, err := getTokenFromContext(ctx)
if err != nil {
panic("get token from context error")
}
// 定义用于解析JWT令牌的自定义声明结构体
var clientClaims Claims
// 解析JWT令牌并将声明解析到自定义声明结构体中
token, err := jwt.ParseWithClaims(tokenStr, &clientClaims, func(token *jwt.Token) (interface{}, error) {
// 检查JWT令牌的算法是否为HS256如果不是则抛出错误
if token.Header["alg"] != "HS256" {
panic("ErrInvalidAlgorithm")
}
// 返回用于验证签名的密钥,这里是一个固定的密钥 "verysecret"
return []byte("verysecret"), nil
})
fmt.Println(token)
if err != nil {
return false
}
// 检查JWT令牌是否有效如果无效则抛出错误
if !token.Valid {
return false
}
if clientClaims.Username != "Wuxinyu" {
return false
}
return true
}

102
peer/token/client.go Normal file
View File

@ -0,0 +1,102 @@
package token
import (
"context"
"fmt"
"log"
"time"
pb "schain/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/keepalive"
)
const (
dialTimeout = 10 * time.Second
maxRecvMessageSize = 100 * 1024 * 1024 // 100 MiB
maxSendMessageSize = 100 * 1024 * 1024 // 100 MiB
)
// 建立与grpc服务器的连接
func NewClient(address string) (*grpc.ClientConn, error) {
var conn *grpc.ClientConn
//Keepalive 时间、超时时间和允许无流的连接
kaOpts := keepalive.ClientParameters{
Time: 1 * time.Minute,
Timeout: 20 * time.Second,
PermitWithoutStream: true,
}
//gRPC 连接选项
dialOpts := []grpc.DialOption{
grpc.WithKeepaliveParams(kaOpts),
grpc.WithBlock(),
grpc.FailOnNonTempDialError(true),
grpc.WithDefaultCallOptions(
grpc.MaxCallRecvMsgSize(maxRecvMessageSize),
grpc.MaxCallSendMsgSize(maxSendMessageSize),
),
}
//取消证书认证
dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
//ctx, cancel := context.WithTimeout(context.Background(), dialTimeout)
//defer cancel()
conn, err := grpc.Dial(address, dialOpts...)
//conn, err := grpc.DialContext(ctx, address, dialOpts...)
if err != nil {
log.Fatalf("did not connect: %s", err)
}
//调用服务器上的 Login RPC 方法
client := pb.NewPingClient(conn)
//对username和password进行aes加密
usr, err := encrypt("Wuxinyu", key)
if err != nil {
panic("encrypt error")
}
pwd, err := encrypt("123456", key)
if err != nil {
panic("encrypt error")
}
loginReply, err := client.Login(context.Background(), &pb.LoginRequest{Username: usr, Password: pwd})
if err != nil {
log.Fatalf("Error when calling SayHello: %s", err)
panic("wrong")
}
fmt.Println("Login Reply:", loginReply)
conn.Close()
//Call SayHello,第二次连接
requestToken := new(AuthToken)
requestToken.Token = loginReply.Token
//创建一个超时的上下文连接
ctx, cancel := context.WithTimeout(context.Background(), dialTimeout)
defer cancel()
dialOpts = append(dialOpts, grpc.WithPerRPCCredentials(requestToken))
conn, err = grpc.DialContext(ctx, address, dialOpts...)
if err != nil {
log.Fatalf("did not connect: %s", err)
}
client = pb.NewPingClient(conn)
helloreply, err := client.SayHello(context.Background(), &pb.PingMessage{Greeting: "foo"})
if err != nil {
log.Fatalf("Error when calling SayHello: %s", err)
panic("connect error")
}
log.Printf("Response from server: %s", helloreply.Greeting)
//通过验证,返回客户端连接
return conn, err
}
func NewRegisterClient(conn *grpc.ClientConn) (pb.ChaincodeSupportClient, error) {
return pb.NewChaincodeSupportClient(conn), nil
}

112
peer/token/handler.go Normal file
View File

@ -0,0 +1,112 @@
package token
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
pb "schain/proto"
"golang.org/x/net/context"
)
// 用于注册grpc服务
type RequestServer struct {
pb.UnimplementedPingServer
}
var key string = "0123456789abcdef"
func (s *RequestServer) Login(ctx context.Context, in *pb.LoginRequest) (*pb.LoginReply, error) {
//实现aes解密
// 解密字符串
de_name, err := decrypt(in.Username, key)
if err != nil {
panic("Decryption error")
}
de_password, err := decrypt(in.Password, key)
if err != nil {
panic("Decryption error")
}
fmt.Println("Loginrequest: ", de_name)
if de_name == "Wuxinyu" && de_password == "123456" {
tokenString := CreateToken(in.Username)
return &pb.LoginReply{Status: "200", Token: tokenString}, nil
} else {
return &pb.LoginReply{Status: "403", Token: ""}, nil
}
}
// SayHello 生成对 Ping 请求的响应
func (s *RequestServer) SayHello(ctx context.Context, in *pb.PingMessage) (*pb.PingMessage, error) {
//生成响应消息
msg := "bar"
// 从上下文中检查用户认证信息
userName := CheckAuth(ctx)
//将用户名添加到消息中
msg += " " + userName
return &pb.PingMessage{Greeting: msg}, nil
}
func encrypt(plainText string, key string) (string, error) {
keyBytes := []byte(key)
block, err := aes.NewCipher(keyBytes)
if err != nil {
return "", err
}
// 创建一个加密器
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
// 创建一个随机的 nonce长度必须与加密块大小相同
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return "", err
}
// 使用 nonce 加密数据
ciphertext := gcm.Seal(nonce, nonce, []byte(plainText), nil)
return base64.StdEncoding.EncodeToString(ciphertext), nil
}
func decrypt(ciphertext string, key string) (string, error) {
decodedCiphertext, err := base64.StdEncoding.DecodeString(ciphertext)
if err != nil {
return "", err
}
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}
// 创建一个解密器
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", err
}
// 从密文中提取 nonce
nonceSize := gcm.NonceSize()
if len(decodedCiphertext) < nonceSize {
return "", fmt.Errorf("ciphertext too short")
}
nonce := decodedCiphertext[:nonceSize]
ciphertextBytes := decodedCiphertext[nonceSize:]
// 解密数据
plaintext, err := gcm.Open(nil, nonce, ciphertextBytes, nil)
if err != nil {
return "", err
}
return string(plaintext), nil
}

93
peer/token/server.go Normal file
View File

@ -0,0 +1,93 @@
package token
import (
"errors"
"net"
pb "schain/proto"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/keepalive"
)
const (
//服务器在处理任务或执行操作时至少需要等待1分钟的时间间隔
serverMinInterval = time.Duration(1) * time.Minute
//5秒连接超时
connectionTimeout = 5 * time.Second
)
type Server struct {
Listener net.Listener
Server *grpc.Server
}
func (s *Server) Start() error {
if s.Listener == nil {
return errors.New("nil listener")
}
if s.Server == nil {
return errors.New("nil server")
}
return s.Server.Serve(s.Listener)
}
func (s *Server) Stop() {
if s.Server != nil {
s.Server.Stop()
}
}
func NewServer(address string) (*Server, error) {
if address == "" {
return nil, errors.New("server listen address not provided")
}
listener, err := net.Listen("tcp", address)
if err != nil {
return nil, err
}
//普通方法一元拦截器grpc.UnaryInterceptor
/*interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
if !is_ahtu {
handler(ctx, req)
is_ahtu = true
}
if Check(ctx) {
handler(ctx, req)
}
return
}
*/
var serverOpts []grpc.ServerOption
serverKeepAliveParameters := keepalive.ServerParameters{
Time: 1 * time.Minute,
Timeout: 20 * time.Second,
}
serverOpts = append(serverOpts, grpc.KeepaliveParams(serverKeepAliveParameters))
serverOpts = append(serverOpts, grpc.MaxSendMsgSize(maxSendMessageSize))
serverOpts = append(serverOpts, grpc.MaxRecvMsgSize(maxRecvMessageSize))
kep := keepalive.EnforcementPolicy{
MinTime: serverMinInterval,
PermitWithoutStream: true,
}
serverOpts = append(serverOpts, grpc.KeepaliveEnforcementPolicy(kep))
serverOpts = append(serverOpts, grpc.ConnectionTimeout(connectionTimeout))
//serverOpts = append(serverOpts, grpc.UnaryInterceptor(interceptor))
// create a gRPC server object
grpcServer := grpc.NewServer(serverOpts...)
request_server := &RequestServer{}
pb.RegisterPingServer(grpcServer, request_server)
return &Server{Listener: listener, Server: grpcServer}, err
}