fix:调整新的中继协议中的上报签名逻辑

This commit is contained in:
liyi 2024-11-30 15:39:06 +08:00
parent c240f089c7
commit a92ae906ef
6 changed files with 215 additions and 109 deletions

View File

@ -234,28 +234,20 @@ class _StarLockLoginPageState extends State<StarLockLoginPage> {
}
: null)),
SubmitBtn(
btnName: '发送上线请求',
btnName: '初始化星图服务',
onClick: () async {
//
await StartChartManage().clientRegister();
//
await StartChartManage().relayQuery();
// 线
await StartChartManage().onlineRelayService();
await StartChartManage().init();
},
),
SubmitBtn(
btnName: '启动心跳包',
btnName: '发送回声测试消息',
onClick: () {
StartChartManage().sendHeartbeatMessage();
},
),
SubmitBtn(
btnName: '结束心跳包',
onClick: () {
StartChartManage().stopHeartbeat();
StartChartManage().sendEchoMessage(
ToPeerId: '3phX8Ng2cZHz5NtP8xAf6nYy2z1BYytoejgjoHrWMGhH');
},
),
SizedBox(height: 50.w),
Row(
mainAxisAlignment: MainAxisAlignment.center,

View File

@ -45,7 +45,7 @@ class StartChartApi extends BaseProvider {
}
// --
Future<void> reportInformation({
Future<Response> reportInformation({
required ReportInformationData reportInformationData,
}) async {
final response = await post(
@ -54,10 +54,11 @@ class StartChartApi extends BaseProvider {
isUnShowLoading: true,
isUserBaseUrl: false,
);
return response;
}
// --
Future<void> analyzeInformationOtherEnd({
Future<Response> analyzeInformationOtherEnd({
required String peerId,
}) async {
final response = await get(
@ -65,5 +66,6 @@ class StartChartApi extends BaseProvider {
isUnShowLoading: true,
isUserBaseUrl: false,
);
return response;
}
}

View File

@ -1,3 +1,4 @@
import 'package:star_lock/talk/startChart/constant/message_type_constant.dart';
import 'package:star_lock/talk/startChart/constant/payload_type_constant.dart';
import 'package:star_lock/talk/startChart/constant/protocol_flag_constant.dart';
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
@ -7,10 +8,16 @@ class MessageCommand {
static List<int> goOnlineRelay() {
String serializedBytesString = ScpMessage(
ProtocolFlag: ProtocolFlagConstant.scp01,
MessageType: PayloadTypeConstant.goOnline,
MessageType: MessageTypeConstant.Req,
MessageId: 1,
SpTotal: 0,
SpIndex: 0,
FromPeerId: 'ToPeerId',
ToPeerId: 'ToPeerId',
Payload: 'hello',
PayloadCRC: 55230,
PayloadLength: 5,
PayloadType: PayloadTypeConstant.goOnline,
).serialize();
return _hexToBytes(serializedBytesString);
}
@ -21,8 +28,8 @@ class MessageCommand {
required String FromPeerId,
}) {
ScpMessage message = ScpMessage(
ProtocolFlag: ProtocolFlagConstant.scp01,
MessageType: PayloadTypeConstant.echoTest,
ProtocolFlag: ProtocolFlagConstant.scp01,
MessageType: MessageTypeConstant.Req,
MessageId: 1,
SpTotal: 0,
SpIndex: 0,
@ -31,7 +38,7 @@ class MessageCommand {
Payload: 'hello',
PayloadCRC: 55230,
PayloadLength: 5,
PayloadType: 1,
PayloadType: PayloadTypeConstant.echoTest,
);
String serializedBytesString = message.serialize();
@ -41,17 +48,17 @@ class MessageCommand {
//
static List<int> heartbeatMessage() {
ScpMessage message = ScpMessage(
ProtocolFlag: ProtocolFlagConstant.scp01,
MessageType: PayloadTypeConstant.heartbeat,
ProtocolFlag: ProtocolFlagConstant.scp01,
MessageType: MessageTypeConstant.Req,
MessageId: 1,
SpTotal: 0,
SpIndex: 0,
// FromPeerId: FromPeerId,
// ToPeerId: ToPeerId,
// Payload: 'hello',
// PayloadCRC: 55230,
// PayloadLength: 5,
// PayloadType: 1,
FromPeerId: 'FromPeerId',
ToPeerId: 'ToPeerId',
Payload: 'hello',
PayloadCRC: 55230,
PayloadLength: 5,
PayloadType: PayloadTypeConstant.heartbeat,
);
String serializedBytesString = message.serialize();

View File

@ -0,0 +1,23 @@
class MessageTypeConstant {
// Req , , , 使,
// Resp, Req, ,
// Resp后才可以从缓存区域删除Req
static const int Req = 1;
// Resp , Req消息
// , , req的超时时间为1秒, 1,.
// ,使Req/Resp模式,, req告诉发起处任务已完成.
static const int Resp = 2;
// RealTimeData , , ,,
// 线, Dos攻击
// 1(Req), /,.
// , , , 线.
static const int RealTimeData = 3;
// InvalidReq Req/Resp模型中的error RespHTTP协议的500服务器错误payload里面是一个utf8的字符串表明错误信息
// 1.01.1APP终端收到了关闭电源指令()
//
//
static const int InvalidReq = 4;
}

View File

@ -58,6 +58,14 @@ class ScpMessage {
'PayloadLength': PayloadLength,
'Payload': Payload,
};
}
@override
String toString() {
return 'ScpMessage{ProtocolFlag: $ProtocolFlag, MessageType: $MessageType, MessageId: $MessageId, SpTotal: $SpTotal, SpIndex: $SpIndex, FromPeerId: $FromPeerId, ToPeerId: $ToPeerId, PayloadType: $PayloadType, PayloadCRC: $PayloadCRC, PayloadLength: $PayloadLength, Payload: $Payload}';
}
String serialize() {
@ -133,11 +141,100 @@ class ScpMessage {
// 16
final bytesToHexString = bytesToHex(bytes);
return bytesToHexString;
}
//
static ScpMessage deserialize(List<int> bytes) {
final message = ScpMessage();
int offset = 0;
// ProtocolFlag (4 bytes)
if (bytes.length - offset >= 4) {
message.ProtocolFlag = utf8.decode(bytes.sublist(offset, offset + 4));
offset += 4;
}
// MessageType (1 byte)
if (bytes.length - offset >= 1) {
message.MessageType = bytes[offset];
offset += 1;
}
// MessageId (2 bytes, little-endian)
if (bytes.length - offset >= 2) {
message.MessageId = (bytes[offset + 1] << 8) | bytes[offset];
offset += 2;
}
// SpTotal (1 byte)
if (bytes.length - offset >= 1) {
message.SpTotal = bytes[offset];
offset += 1;
}
// SpIndex (1 byte)
if (bytes.length - offset >= 1) {
message.SpIndex = bytes[offset];
offset += 1;
}
// FromPeerId (44)
if (bytes.length - offset >= 44) {
message.FromPeerId = utf8.decode(bytes.sublist(offset, offset + 44));
offset += 44;
}
// ToPeerId (44)
if (bytes.length - offset >= 44) {
message.ToPeerId = utf8.decode(bytes.sublist(offset, offset + 44));
offset += 44;
}
// PayloadType (2 bytes, little-endian)
if (bytes.length - offset >= 2) {
message.PayloadType = (bytes[offset + 1] << 8) | bytes[offset];
offset += 2;
}
// PayloadCRC (2 bytes, little-endian)
if (bytes.length - offset >= 2) {
message.PayloadCRC = (bytes[offset + 1] << 8) | bytes[offset];
offset += 2;
}
// PayloadLength (4 bytes, big-endian)
if (bytes.length - offset >= 4) {
message.PayloadLength = (bytes[offset] |
(bytes[offset + 1] << 8) |
(bytes[offset + 2] << 16) |
(bytes[offset + 3] << 24));
offset += 4;
}
// Payload ()
if (message.PayloadLength != null &&
bytes.length - offset >= message.PayloadLength!) {
message.Payload =
utf8.decode(bytes.sublist(offset, offset + message.PayloadLength!));
offset += message.PayloadLength!;
}
return message;
}
static String bytesToHex(List<int> bytes) {
return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join('');
}
// 16
static List<int> hexToBytes(String hexString) {
final bytes = <int>[];
for (int i = 0; i < hexString.length; i += 2) {
final hexByte = hexString.substring(i, i + 2);
bytes.add(int.parse(hexByte, radix: 16));
}
return bytes;
}
}

View File

@ -5,6 +5,8 @@ import 'dart:typed_data';
import 'package:pointycastle/asn1/asn1_parser.dart';
import 'package:pointycastle/asn1/primitives/asn1_integer.dart';
import 'package:pointycastle/asn1/primitives/asn1_sequence.dart';
import 'package:pointycastle/asymmetric/api.dart';
import 'package:pointycastle/digests/sha256.dart';
import 'package:star_lock/app_settings/app_settings.dart';
import 'package:star_lock/flavors.dart';
import 'package:star_lock/network/start_chart_api.dart';
@ -13,6 +15,7 @@ import 'package:star_lock/talk/startChart/constant/ip_constant.dart';
import 'package:star_lock/talk/startChart/constant/listen_addr_type_constant.dart';
import 'package:star_lock/talk/startChart/entity/relay_info_entity.dart';
import 'package:star_lock/talk/startChart/entity/report_information_data.dart';
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
import 'package:star_lock/talk/startChart/entity/star_chart_register_node_entity.dart';
import 'package:star_lock/tools/deviceInfo_utils.dart';
import 'package:star_lock/tools/storage.dart';
@ -43,6 +46,7 @@ class StartChartManage {
late String remoteHost = ''; // ()
late int remotePort = 0; // ()
final int localPort = 62289; //
String localPublicHost = ''; // ip地址
int heartbeatIntervalTime = 1; // s
Timer? _heartBeatTimer; //
@ -50,27 +54,47 @@ class StartChartManage {
String ToPeerId = ''; // ID
String FromPeerId = ''; // ID
bool _isLoginSuccessfulToStartChart = false; //
//
Future<void> init() async {
//
await _clientRegister();
//
await _relayQuery();
//
await reportInformation();
// udp服务
await _onlineRelayService();
//
_sendHeartbeatMessage();
// 线
await _sendOnlineMessage();
}
///
Future<void> clientRegister() async {
//
final StarChartRegisterNodeEntity? starChartRegisterNodeInfo =
await Storage.getStarChartRegisterNodeInfo();
if (starChartRegisterNodeInfo == null) {
_log(text: '开始注册客户端');
final StarChartRegisterNodeEntity requestStarChartRegisterNode =
await _requestStarChartRegisterNode();
_saveStarChartRegisterNodeToStorage(requestStarChartRegisterNode);
} else {
final entity = await Storage.getStarChartRegisterNodeInfo();
_log(text: '获取到星图注册节点信息:$entity');
}
Future<void> _clientRegister() async {
_log(text: '开始注册客户端');
final StarChartRegisterNodeEntity requestStarChartRegisterNode =
await _requestStarChartRegisterNode();
await _saveStarChartRegisterNodeToStorage(requestStarChartRegisterNode);
_log(text: '获取到星图注册节点信息:$requestStarChartRegisterNode');
}
//
Future<void> relayQuery() async {
Future<void> _relayQuery() async {
final RelayInfoEntity relayInfoEntity =
await StartChartApi.to.relayQueryInfo();
_saveRelayInfoEntityToStorage(relayInfoEntity);
if (relayInfoEntity.client_addr != null) {
localPublicHost = relayInfoEntity.client_addr!;
}
if (relayInfoEntity.relay_list?.length != 0) {
final data = relayInfoEntity.relay_list?[0];
@ -78,7 +102,7 @@ class StartChartManage {
final parseUdpUrl = _parseUdpUrl(data?.listenAddr ?? '');
remoteHost = parseUdpUrl['host'] ?? '';
remotePort = parseUdpUrl['port'] ?? '';
_log(text: '中继信息:${data}');
_log(text: '中继信息----》${data}');
}
}
@ -88,9 +112,8 @@ class StartChartManage {
}
}
// 线
Future<void> onlineRelayService() async {
await relayQuery();
// udp
Future<void> _onlineRelayService() async {
var addressIListenFrom = InternetAddress.anyIPv4;
RawDatagramSocket.bind(addressIListenFrom, localPort)
.then((RawDatagramSocket socket) {
@ -101,14 +124,6 @@ class StartChartManage {
///
_onReceiveData(_udpSocket!);
// 线
//_sendOnlineMessage();
//
//_sendEchoMessage();
//
reportInformation();
}).catchError((error) {
_log(text: 'Failed to bind UDP socket: $error');
});
@ -121,6 +136,10 @@ class StartChartManage {
Datagram? dg = socket.receive();
try {
_log(text: '收到消息---> 长度:${dg?.data?.length}, 数据:${dg?.data}');
if (dg?.data != null) {
final deserialize = ScpMessage.deserialize(dg!.data);
_log(text: 'Udp收到结构体数据---》$deserialize');
}
} catch (e) {
_log(text: '❌ Udp ----> $e');
}
@ -133,29 +152,33 @@ class StartChartManage {
_log(text: '上报信息至发现服务');
//
ReportInformationData data = await _makeReportInformationData();
await StartChartApi.to.reportInformation(
final response = await StartChartApi.to.reportInformation(
reportInformationData: data,
);
if (response.statusCode == 200) {
// TODO
_log(text: '星图登录成功');
}
}
// 线
void _sendOnlineMessage() {
Future<void> _sendOnlineMessage() async {
// 线
final message = MessageCommand.goOnlineRelay();
_sendMessage(message: message);
await _sendMessage(message: message);
}
//
void _sendEchoMessage() {
void sendEchoMessage({required String ToPeerId}) async {
final message = MessageCommand.echoMessage(
ToPeerId: ToPeerId,
FromPeerId: FromPeerId,
);
_sendMessage(message: message);
await _sendMessage(message: message);
}
//
void sendHeartbeatMessage() {
void _sendHeartbeatMessage() {
if (_heartBeatTimerRunning) {
_log(text: '心跳已经开始了. 请勿重复发送心跳包消息');
return;
@ -164,9 +187,9 @@ class StartChartManage {
Duration(
seconds: heartbeatIntervalTime,
),
(Timer timer) {
(Timer timer) async {
final List<int> message = MessageCommand.heartbeatMessage();
_sendMessage(message: message);
await _sendMessage(message: message);
},
);
_heartBeatTimerRunning = true;
@ -181,9 +204,14 @@ class StartChartManage {
}
//
void _sendMessage({required List<int> message}) {
Future<void> _sendMessage({required List<int> message}) async {
_log(text: '发送给中继的消息体:${message},序列化之后的数据:【${bytesToHex(message)}');
_udpSocket!.send(message, InternetAddress(remoteHost), remotePort);
var result = await _udpSocket?.send(
message, InternetAddress(remoteHost), remotePort);
if (result != message.length) {
AppLog.log('❌Udp ----> send data error $result ${message.length}');
_udpSocket = null;
}
}
//
@ -334,7 +362,6 @@ class StartChartManage {
return {'host': ip, 'port': port};
}
}
throw FormatException('无法解析 URL 格式: $url');
}
@ -424,48 +451,6 @@ class StartChartManage {
return signer.generateSignature(Uint8List.fromList(data)).bytes;
}
// RSA
// RSAPrivateKey parseRSAPrivateKey1(Uint8List bytes) {
// // PKCS#1 DER
// ASN1Parser parser = ASN1Parser(bytes);
// ASN1Sequence seq = parser.nextObject() as ASN1Sequence;
// if (seq.elements == null || seq.elements!.length < 9) {
// throw ArgumentError("Invalid RSA private key");
// }
//
// //
// ASN1Integer version = seq.elements![0] as ASN1Integer;
// ASN1Integer modulus = seq.elements![1] as ASN1Integer;
// // ASN1Integer publicExponent = seq.elements![2] as ASN1Integer;
// ASN1Integer privateExponent = seq.elements![3] as ASN1Integer;
// ASN1Integer p = seq.elements![2] as ASN1Integer;
// ASN1Integer q = seq.elements![4] as ASN1Integer;
// ASN1Integer dP = seq.elements![5] as ASN1Integer;
// ASN1Integer dQ = seq.elements![6] as ASN1Integer;
// ASN1Integer qInv = seq.elements![7] as ASN1Integer;
//
// // ASN1Integer BigInt
// BigInt modulusValue = _convertToBigInt(modulus);
// // BigInt publicExponentValue = _convertToBigInt(publicExponent);
// BigInt privateExponentValue = _convertToBigInt(privateExponent);
// BigInt pValue = _convertToBigInt(p);
// BigInt qValue = _convertToBigInt(q);
// BigInt dPValue = _convertToBigInt(dP);
// BigInt dQPValue = _convertToBigInt(dQ);
// BigInt qInvQPValue = _convertToBigInt(qInv);
//
// // RSAPrivateKey
// return RSAPrivateKey(modulusValue, privateExponentValue, pValue, qValue);
// }
//
// // ASN1Integer BigInt
// BigInt _convertToBigInt(ASN1Integer integer) {
// // ASN1Integer
// Uint8List bytes = integer.valueBytes!;
// // BigInt
// return BigInt.parse(hex.encode(bytes), radix: 16);
// }
Future<String> getPublicKey() async {
//
final StarChartRegisterNodeEntity? starChartRegisterNodeInfo =