From dfc5dc433fc248e2b2097ab2c6a9f0ec113b786c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AD=8F=E5=B0=91=E9=98=B3?= <786612630@qq.com> Date: Sat, 12 Aug 2023 18:32:49 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E8=AF=95=E6=B7=BB=E5=8A=A0=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/blue/io_protocol/io_addUser.dart | 143 ++++++++++++++++-- .../blue/io_protocol/io_getPrivateKey.dart | 26 ++-- .../lib/blue/io_protocol/io_getPublicKey.dart | 10 +- star_lock/lib/blue/io_tool/io_tool.dart | 54 ++++--- star_lock/lib/blue/reciver_data.dart | 15 +- star_lock/lib/blue/sm4Encipher/sm4.dart | 8 +- .../lib/mine/mine/starLockMine_state.dart | 6 +- .../lib/network/request_interceptor.dart | 2 +- star_lock/lib/tools/storage.dart | 117 +++++++++++--- 9 files changed, 297 insertions(+), 84 deletions(-) diff --git a/star_lock/lib/blue/io_protocol/io_addUser.dart b/star_lock/lib/blue/io_protocol/io_addUser.dart index 17b1fa2f..88b757f2 100644 --- a/star_lock/lib/blue/io_protocol/io_addUser.dart +++ b/star_lock/lib/blue/io_protocol/io_addUser.dart @@ -1,13 +1,16 @@ +import 'dart:convert'; + import '../io_tool/io_tool.dart'; +import '../sm4Encipher/sm4.dart'; import 'io_reply.dart'; import 'io_sender.dart'; import 'io_type.dart'; +import 'package:crypto/crypto.dart' as crypto; //TODO:添加用户 class AddUserCommand extends SenderProtocol { - int? cmdID; String? lockID; String? authUserID; String? keyID; @@ -18,11 +21,10 @@ class AddUserCommand extends SenderProtocol { int? expireDate; int? role; String? password; - int? token; - int? authCodeLen; - String? authCode; + int? needAuthor; + List? userPperationToken; + List? publicKeyData; AddUserCommand({ - this.cmdID, this.lockID, this.authUserID, this.keyID, @@ -33,20 +35,133 @@ class AddUserCommand extends SenderProtocol { this.expireDate, this.role, this.password, - this.token, - this.authCodeLen, - this.authCode, + this.needAuthor, + this.userPperationToken, + this.publicKeyData }) : super(CommandType.addUser); @override List messageDetail() { List data = []; - // data.add(0x21); - // int d = direction!.toInt(); - // data.addAll(intToByte2ListHigh(d)); - // data.add(0x22); - // int s = speed!.toInt(); - // data.add(s); + List ebcData = []; + + // 指令类型 + int type = commandType!.typeValue; + double typeDouble = type / 256; + int type1 = typeDouble.toInt(); + int type2 = type % 256; + data.add(type1); + data.add(type2); + + // 锁id 40 + int lockIDLength = utf8.encode(lockID!).length; + data.addAll(utf8.encode(lockID!)); + data = getFixedLengthList(data, 40 - lockIDLength); + + //authUserID 20 + int authUserIDLength = utf8.encode(authUserID!).length; + data.addAll(utf8.encode(authUserID!)); + data = getFixedLengthList(data, 20 - authUserIDLength); + + //KeyID 40 + int keyIDLength = utf8.encode(keyID!).length; + data.addAll(utf8.encode(keyID!)); + data = getFixedLengthList(data, 40 - keyIDLength); + + //userID 要接受钥匙的用户的useid 20 + int userIDLength = utf8.encode(authUserID!).length; + data.addAll(utf8.encode(authUserID!)); + data = getFixedLengthList(data, 20 - authUserIDLength); + + // openModel + data.add(openMode!); + + // keyType + data.add(keyType!); + + int? d1, d2; + if(role == 255){ + d1 = 0;//Date.parse(new Date()) / 1000; + d2 = 0xffffffff;//d1 + 86440; + }else{ + d1 = startDate; + d2 = expireDate; + } + + // StartDate 4 + data.add((d1! & 0xff000000) >> 24); + data.add((d1 & 0xff0000) >> 16); + data.add((d1 & 0xff00) >> 8); + data.add((d1 & 0xff)); + + // expireDate 4 + data.add((d2! & 0xff000000) >> 24); + data.add((d2 & 0xff0000) >> 16); + data.add((d2 & 0xff00) >> 8); + data.add((d2 & 0xff)); + + // role 长度1 用户角色,0:普通用户,1:管理员,0xff:超级管理员 + data.add(role!); + + //password 超级管理员领锁时需验证该密码 20 + int passwordLength = utf8.encode(password!).length; + data.addAll(utf8.encode(password!)); + data = getFixedLengthList(data, 20 - passwordLength); + + if(needAuthor == 0){ + // 当token失效或者第一次发送的时候token为0 + //Token 4 + data.addAll([0, 0, 0, 0]); + + //AuthCodeLen 1 + data.add(0); + } else { + // token 长度4 首次请求 Token 填 0,如果锁需要鉴权 操作者身份,则会分配动态口令并在应答消息中返回,二次请求时带上。 + data.addAll(userPperationToken!); + + List authCodeData = []; + + //KeyID + authCodeData.addAll(utf8.encode(keyID!)); + + //authUserID + authCodeData.addAll(utf8.encode(authUserID!)); + + //token 4 + authCodeData.addAll(userPperationToken!); + + // String pubKey = ""; + // Storage.getData("bluePublicKey").then((res) => { + // pubKey = res + // }); + // var pubKey = "ovOvAHuL5+dBCw7L3Qt7IQ=="; + // print("pubKey:$pubKey"); + // List pubKeyData = base64.decode(pubKey.toString()); + // print("pubKeyData:$pubKeyData"); + authCodeData.addAll(publicKeyData!); + + // 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode + var authCode = crypto.md5.convert(authCodeData); + // print("authCodeData:$authCodeData \nauthCode:$authCode \nauthCodeBytes:${authCode.bytes}"); + + data.add(authCode.bytes.length); + data.addAll(authCode.bytes); + } + + if ((data.length % 16) != 0) { + int add = (16 - data.length % 16); + for (int i = 0; i < add; i++) { + data.add(0); + } + } + print("SM4Data:$data"); + // 拿到数据之后通过LockId进行SM4 ECB加密 key:544d485f633335373034383064613864 + String key = SM4.createHexKey(key: 'TMH_c3570480da8d'); + ebcData = SM4.encrypt(data, key: key, mode: SM4CryptoMode.ECB); + ebcData.removeRange(ebcData.length - 16, ebcData.length); + // ebcData = utf8.encode(getSM4Str(data, "TMH_c3570480da8d")); + print("ebcData:$ebcData"); + return data; } } diff --git a/star_lock/lib/blue/io_protocol/io_getPrivateKey.dart b/star_lock/lib/blue/io_protocol/io_getPrivateKey.dart index 7e6d35b6..e627b56b 100644 --- a/star_lock/lib/blue/io_protocol/io_getPrivateKey.dart +++ b/star_lock/lib/blue/io_protocol/io_getPrivateKey.dart @@ -2,14 +2,12 @@ import 'dart:convert'; import 'package:star_lock/blue/sm4Encipher/sm4.dart'; -import '../../tools/storage.dart'; import '../io_tool/io_tool.dart'; import 'io_reply.dart'; import 'io_sender.dart'; import 'io_type.dart'; -import 'package:crypto/crypto.dart' as a; -import 'package:convert/convert.dart'; +import 'package:crypto/crypto.dart' as crypto; class GetPrivateKeyCommand extends SenderProtocol { String? lockID; @@ -99,7 +97,7 @@ class GetPrivateKeyCommand extends SenderProtocol { authCodeData.addAll(publicKeyData!); // 把KeyID、authUserID、时间戳、公钥通过md5加密之后就是authCode - var authCode = a.md5.convert(authCodeData); + var authCode = crypto.md5.convert(authCodeData); // print("authCodeData:$authCodeData \nauthCode:$authCode \nauthCodeBytes:${authCode.bytes}"); data.add(authCode.bytes.length); @@ -126,22 +124,30 @@ class GetPrivateKeyCommand extends SenderProtocol { class GetPrivateKeyReply extends Reply { GetPrivateKeyReply.parseData(CommandType commandType, List dataDetail) : super.parseData(commandType, dataDetail) { - print('获取私钥'); - switch(dataDetail[0]){ + var getData = dataDetail.sublist(2); + // print("getData:$getData"); + switch(getData[0]){ case 0x00: //成功 - + print('获取私钥成功'); + getData.removeAt(0); + List commKey = getData.sublist(0, 16); + List signKey = getData.sublist(16); + print("commKey:$commKey signKey:$signKey"); break; case 0x07: - //无权限 + //无权限 + print('获取私钥无权限'); break; case 0x0f: - //用户已存在 + //用户已存在 + print('获取私钥:用户已存在'); break; default: - //失败 + //失败 + print('获取私钥失败'); break; } diff --git a/star_lock/lib/blue/io_protocol/io_getPublicKey.dart b/star_lock/lib/blue/io_protocol/io_getPublicKey.dart index 1a248a8c..0831a925 100644 --- a/star_lock/lib/blue/io_protocol/io_getPublicKey.dart +++ b/star_lock/lib/blue/io_protocol/io_getPublicKey.dart @@ -26,15 +26,15 @@ class GetPublicKeyCommand extends SenderProtocol { int type2 = type%256; data.add(type1); data.add(type2); - print("type:$type"); - print("type1:$type1"); - print("type2:$type2"); + // print("type:$type"); + // print("type1:$type1"); + // print("type2:$type2"); print("lockID:${lockID!} lockID.utf8.encode${utf8.encode(lockID!)}"); int length = utf8.encode(lockID!).length; data.addAll(utf8.encode(lockID!)); data = getFixedLengthList(data, 40 - length); - print("dataaaaaa:$data"); + // print("dataaaaaa:$data"); return data; } } @@ -50,7 +50,7 @@ class GetPublicKeyReply extends Reply { String stringEncoded = base64.encode(tokenData); print('获取公钥成功 publickey:$stringEncoded'); // 储存公钥 - Storage.setData("bluePublicKey", stringEncoded); + // Storage.setData("bluePublicKey", stringEncoded); IoSenderManage.getPrivateKey("TMH_c3570480da8d", "1", "1", 1, tokenData, 1); break; case 0x07: diff --git a/star_lock/lib/blue/io_tool/io_tool.dart b/star_lock/lib/blue/io_tool/io_tool.dart index 3d633952..0d91c114 100644 --- a/star_lock/lib/blue/io_tool/io_tool.dart +++ b/star_lock/lib/blue/io_tool/io_tool.dart @@ -4,28 +4,44 @@ import 'dart:typed_data'; import 'package:crypto/crypto.dart'; import 'package:flutter/services.dart'; import 'package:encrypt/encrypt.dart' as ddd; -// import 'package:sm_crypto/sm_crypto.dart'; -// String getSM4Str(Listdata, String key) { -// String dataStr = radixString(data); -// String iv = SM4.createHexKey(key: key); +List changeIntListToStringList(List list){ + List strList = []; + for(int i = 0; i changeStringListToIntList(List list){ + List intList = []; + for(int i = 0; i= 48 && hexDigit <= 57) { + val += (hexDigit - 48) * (1 << (4 * (len - 1 - i))); + } else if (hexDigit >= 65 && hexDigit <= 70) { + // A..F + val += (hexDigit - 55) * (1 << (4 * (len - 1 - i))); + } else if (hexDigit >= 97 && hexDigit <= 102) { + // a..f + val += (hexDigit - 87) * (1 << (4 * (len - 1 - i))); + } else { + throw new FormatException("Invalid hexadecimal value"); + } + } + return val; +} String md5Crypto(List data) { final dig = md5.convert(data); diff --git a/star_lock/lib/blue/reciver_data.dart b/star_lock/lib/blue/reciver_data.dart index 7187a488..d22fc40e 100644 --- a/star_lock/lib/blue/reciver_data.dart +++ b/star_lock/lib/blue/reciver_data.dart @@ -22,7 +22,7 @@ class CommandReciverManager { if(data_size < 13){ return; } - print("appDataReceiveData:$data"); + // print("appDataReceiveData:$data"); if((data[0] == 0xEF)&&(data[1] == 0x01)&&(data[2] == 0xEE)&&(data[3] == 0x02)&&(data[4] == 0x11)){ var tmpType = (data[7] & 0x0f);// 包标识 print("temType:$tmpType"); @@ -36,19 +36,24 @@ class CommandReciverManager { // for (var i = 0; i < oriLen ; i++) { // oriDataList.add(data[12 + i]); // } - oriDataList = data.sublist(12, 12 + oriLen); + oriDataList = data.sublist(12, 12 + dataLen); print("不加密 oriDataList:$oriDataList"); break; case 1: //AES128 break; case 2: - //SM4(事先约定密钥) + // SM4(事先约定密钥) + // 获取的加密数组 + var getDataList = data.sublist(12, 12 + dataLen); String key = SM4.createHexKey(key: 'TMH_c3570480da8d'); - oriDataList = SM4.decrypt(data, key: key, mode: SM4CryptoMode.ECB); + // 解密 + oriDataList = SM4.decrypt(getDataList, key: key, mode: SM4CryptoMode.ECB); + oriDataList = oriDataList.sublist(0, oriLen); print("SM4 oriDataList:$oriDataList"); break; - case 3: //SM4(设备指定密钥) + case 3: + //SM4(设备指定密钥) // for (var i = 0; i < dataLen ; i++) { // dataView[i] = uint8Recv[12 + i]; // } diff --git a/star_lock/lib/blue/sm4Encipher/sm4.dart b/star_lock/lib/blue/sm4Encipher/sm4.dart index 8cdc9f76..810c8217 100644 --- a/star_lock/lib/blue/sm4Encipher/sm4.dart +++ b/star_lock/lib/blue/sm4Encipher/sm4.dart @@ -411,9 +411,11 @@ class SM4 { } return paddedList; } else { - final lastByte = input.last; - final cutLen = input.length - lastByte; - return input.sublist(0, cutLen); + // final lastByte = input.last; + // final cutLen = input.length - lastByte; + // print("object input.length:${input.length} lastByte:$lastByte input:$input cutLen:$cutLen"); + // return input.sublist(0, cutLen); + return input; } } diff --git a/star_lock/lib/mine/mine/starLockMine_state.dart b/star_lock/lib/mine/mine/starLockMine_state.dart index c29faa5e..8f0d4d3a 100644 --- a/star_lock/lib/mine/mine/starLockMine_state.dart +++ b/star_lock/lib/mine/mine/starLockMine_state.dart @@ -14,13 +14,13 @@ class StarLockMineState { ///本地存储 登录信息 void saveLoginData(LoginEntity data) async { print("saveLoginData:${data.data!.mobile}"); - await Storage.setData('userLoginData',jsonEncode(data)); + await Storage.setString('userLoginData',jsonEncode(data)); loginData.value=data; } ///初始化本地数据 void initLoginData() async { - final data = await Storage.getData('userLoginData'); + final data = await Storage.getString('userLoginData'); print("getLoginData:$data"); if(data != null && data.isNotEmpty){ loginData.value = LoginEntity.fromJson(jsonDecode(data)); @@ -29,7 +29,7 @@ class StarLockMineState { ///退出登录 void logOut() async { - await Storage.setData('userLoginData',''); + await Storage.setString('userLoginData',''); loginData.value = LoginEntity(); } diff --git a/star_lock/lib/network/request_interceptor.dart b/star_lock/lib/network/request_interceptor.dart index 65e11a4f..69f411ff 100644 --- a/star_lock/lib/network/request_interceptor.dart +++ b/star_lock/lib/network/request_interceptor.dart @@ -17,7 +17,7 @@ FutureOr requestInterceptor(Request request) async { // request.headers['token'] = StoreService.to.userToken!; // print("11111${StoreService.to.userToken}"); String? xToken = ''; - final data = await Storage.getData('userLoginData'); + final data = await Storage.getString('userLoginData'); if(data != null && data.isNotEmpty){ xToken = LoginEntity.fromJson(jsonDecode(data)).data!.accessToken; } diff --git a/star_lock/lib/tools/storage.dart b/star_lock/lib/tools/storage.dart index 1c91c7d4..e0c5b5e0 100644 --- a/star_lock/lib/tools/storage.dart +++ b/star_lock/lib/tools/storage.dart @@ -4,33 +4,102 @@ import 'package:shared_preferences/shared_preferences.dart'; class Storage{ - ///存数据 - static Future setData(key, value) async { + + // ///存数据 + // static Future setData(key, value) async { + // SharedPreferences sp = await SharedPreferences.getInstance(); + // if (value is int) { + // await sp.setInt(key, value); + // } else if (value is bool) { + // await sp.setBool(key, value); + // } else if (value is double) { + // await sp.setDouble(key, value); + // } else if (value is String) { + // await sp.setString(key, value); + // } else if (value is List) { + // await sp.setStringList(key, value); + // } + // } + // + // ///取数据 + // /// + // static Future getData(key) async { + // SharedPreferences sp = await SharedPreferences.getInstance(); + // switch(T){ + // case int: return (sp.getInt(key) ?? 0) as T; + // case bool: return (sp.getBool(key) ?? false) as T; + // case double: return (sp.getDouble(key) ?? 0.0) as T; + // case String: return (sp.getString(key) ?? '') as T; + // case List: return (sp.getStringList(key) ?? []) as T; + // default: return null; + // } + // } + + // int + static Future setInt(key,value) async{ SharedPreferences sp = await SharedPreferences.getInstance(); - if (value is int) { - await sp.setInt(key, value); - } else if (value is bool) { - await sp.setBool(key, value); - } else if (value is double) { - await sp.setDouble(key, value); - } else if (value is String) { - await sp.setString(key, value); - } else if (value is List) { - await sp.setStringList(key, value); - } + sp.setInt(key, value); } - ///取数据 - /// - static Future getData(key) async { + static Future getInt(key) async{ SharedPreferences sp = await SharedPreferences.getInstance(); - switch(T){ - case int: return (sp.getInt(key) ?? 0) as T; - case bool: return (sp.getBool(key) ?? false) as T; - case double: return (sp.getDouble(key) ?? 0.0) as T; - case String: return (sp.getString(key) ?? '') as T; - case List: return (sp.getStringList(key) ?? []) as T; - default: return null; - } + return sp.getInt(key); } + + // bool + static Future setBool(key,value) async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + sp.setBool(key, value); + } + + static Future getBool(key) async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + return sp.getBool(key); + } + + // double + static Future setDouble(key,value) async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + sp.setDouble(key, value); + } + + static Future getDouble(key) async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + return sp.getDouble(key); + } + + // string + static Future setString(key,value) async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + sp.setString(key, value); + } + + static Future getString(key) async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + return sp.getString(key); + } + + // 字符串数组 + static Future setStringList(key,value) async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + sp.setStringList(key, value); + } + + static Future?> getStringList(key) async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + return sp.getStringList(key); + } + + // 移除数据 + static Future removeData(key) async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + sp.remove(key); + } + + // 移除所有的键值对 + static Future clearAll() async{ + SharedPreferences sp = await SharedPreferences.getInstance(); + sp.clear(); + } + } \ No newline at end of file