SMP handshake - validate key hash and protocol version

This commit is contained in:
Evgeny Poberezkin 2021-10-26 21:38:15 +01:00
parent e8fe5632f4
commit 41681aaa6b
6 changed files with 54 additions and 5 deletions

View File

@ -0,0 +1 @@
void main() {}

View File

@ -142,3 +142,13 @@ Uint8List encodeInt16(int n) {
ByteData.sublistView(data).setInt16(0, n);
return data;
}
extension EqualUint8List on Uint8List {
bool equal(Uint8List b) {
if (length != b.length) return false;
for (int i = 0; i < length; i++) {
if (this[i] != b[i]) return false;
}
return true;
}
}

View File

@ -13,6 +13,7 @@ final charUpperA = cc('A');
final charUpperZ = cc('Z');
final charPlus = cc('+');
final charSlash = cc('/');
final charDot = cc('.');
class Parser {
final Uint8List _s;
@ -70,6 +71,14 @@ class Parser {
return true;
});
// takes the passed char
bool? char(int c) => _run(() {
if (_s[_pos] == c) {
_pos++;
return true;
}
});
// takes space
bool? space() => _run(() {
if (_s[_pos] == charSpace) {

View File

@ -1,8 +1,10 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:pointycastle/asymmetric/api.dart';
import 'package:pointycastle/digests/sha256.dart';
import 'buffer.dart';
import 'crypto.dart';
import 'parser.dart';
import 'rsa_keys.dart';
abstract class Transport {
@ -51,7 +53,7 @@ class ServerHandshake {
typedef SMPVersion = List<int>;
// SMPVersion _currentSMPVersion = const [0, 4, 1, 0];
SMPVersion _currentSMPVersion = const [0, 4, 1, 0];
const int _serverHeaderSize = 8;
const int _binaryRsaTransport = 0;
const int _transportBlockSize = 4096;
@ -96,7 +98,8 @@ class SMPTransportClient {
}
static void validateKeyHash_2(Uint8List rawKey, Uint8List keyHash) {
// todo
if (keyHash.equal(SHA256Digest().process(rawKey))) return;
throw Exception('smp handshake error: bad key hash');
}
static ServerHeader parseServerHeader(Uint8List a) {
@ -129,10 +132,33 @@ class SMPTransportClient {
_parseSMPVersion(await _readEncrypted());
static SMPVersion _parseSMPVersion(Uint8List block) {
return [];
final p = Parser(block);
final SMPVersion version = [0, 0, 0, 0];
void setVer(int i, int? v) {
if (v == null || p.fail) {
throw Exception('smp handshake error: bad version format');
}
version[i] = v;
}
for (var i = 0; i < 3; i++) {
final v = p.decimal();
p.char(charDot);
setVer(i, v);
}
final v = p.decimal();
p.space();
setVer(3, v);
return version;
}
static void _checkVersion(SMPVersion version) {}
static void _checkVersion(SMPVersion srvVersion) {
final s0 = srvVersion[0];
final c0 = _currentSMPVersion[0];
if (s0 > c0 || (s0 == c0 && srvVersion[1] > _currentSMPVersion[1])) {
throw Exception('smp handshake error: incompatible server version');
}
}
Future<Uint8List> _readEncrypted() async {
final block = await _conn.read(blockSize);

View File

@ -1,5 +1,6 @@
// import 'dart:io';
import 'package:simplexmq/simplexmq.dart';
import 'package:simplexmq/src/buffer.dart';
import 'package:simplexmq_io/simplexmq_io.dart';
import 'package:test/test.dart';
@ -9,7 +10,9 @@ void main() {
'establish connection (expects SMP server on localhost:5223)',
() async {
final conn = await SocketTransport.connect('localhost', 5223);
final smp = await SMPTransportClient.connect(conn);
final smp = await SMPTransportClient.connect(conn,
keyHash: decode64(
encodeAscii('pH7bg7B6vB3uJ1poKmClTAqr7yYWnAtapnIDN7ypKxU=')));
expect(smp is SMPTransportClient, true);
},
skip: 'requires SMP server on port 5223',