secureInbound method
Secures an inbound connection
Implementation
@override
Future<SecuredConnection> secureInbound(TransportConn connection) async {
if (_isDisposed) throw NoiseProtocolException('Protocol has been disposed');
try {
final staticKey = await crypto.X25519().newKeyPair();
final pattern = await NoiseXXPattern.create(false, staticKey);
await pattern.readMessage(await connection.read(32)); // <- e
await connection.write(await pattern.writeMessage(Uint8List(0))); // -> e, ee, s, es
await pattern.readMessage(await connection.read(48)); // <- s, se
// Noise XX handshake complete. Exchange libp2p handshake payload.
// ADDED LOGGING
_log.finer('NoiseSecurity.secureInbound: Handshake complete. Pattern keys:');
_log.finer(' - pattern.sendKey.hashCode: ${pattern.sendKey.hashCode}, pattern.sendKey.bytes: ${await pattern.sendKey.extractBytes()}');
_log.finer(' - pattern.recvKey.hashCode: ${pattern.recvKey.hashCode}, pattern.recvKey.bytes: ${await pattern.recvKey.extractBytes()}');
final tempSecuredConn = SecuredConnection(
connection,
pattern.sendKey, // Responder's send is initiator's recv
pattern.recvKey, // Responder's recv is initiator's send
securityProtocolId: _protocolString,
);
// 1. Receive and process initiator's payload
final initiatorEncryptedPayloadBytes = await _readLibp2pHandshakePayload(tempSecuredConn);
final initiatorPayload = noise_pb.NoiseHandshakePayload.fromBuffer(initiatorEncryptedPayloadBytes);
if (!initiatorPayload.hasIdentityKey()) throw NoiseProtocolException("Initiator payload missing identity key");
// Assuming Ed25519 key
final remoteLibp2pPublicKey = ed25519_keys.Ed25519PublicKey.unmarshal(Uint8List.fromList(initiatorPayload.identityKey));
if (!initiatorPayload.hasIdentitySig()) throw NoiseProtocolException("Initiator payload missing signature");
// Initiator's signature is over responder's static X25519 key
final responderStaticNoiseKey = await pattern.getStaticPublicKey();
final sigVerified = await remoteLibp2pPublicKey.verify(
responderStaticNoiseKey, Uint8List.fromList(initiatorPayload.identitySig));
if (!sigVerified) throw NoiseProtocolException("Failed to verify initiator's signature");
// 2. Prepare and send responder's payload
final responderPayload = noise_pb.NoiseHandshakePayload();
responderPayload.identityKey = await _identityKey.publicKey.marshal();
// Responder signs initiator's X25519 static key (which is pattern.remoteStaticKey from responder's PoV)
if (pattern.remoteStaticKey == null) throw NoiseProtocolException("Initiator's remote static key is null during inbound secure");
final signature = await _identityKey.privateKey.sign(pattern.remoteStaticKey!);
responderPayload.identitySig = signature;
await _writeEncryptedPayload(tempSecuredConn, responderPayload.writeToBuffer());
final remotePeerId = await PeerId.fromPublicKey(remoteLibp2pPublicKey);
// ADDED LOGGING
_log.finer('NoiseSecurity.secureInbound: Libp2p handshake payload processed. Finalizing SecuredConnection with pattern keys:');
_log.finer(' - pattern.sendKey.hashCode: ${pattern.sendKey.hashCode}, pattern.sendKey.bytes: ${await pattern.sendKey.extractBytes()}');
_log.finer(' - pattern.recvKey.hashCode: ${pattern.recvKey.hashCode}, pattern.recvKey.bytes: ${await pattern.recvKey.extractBytes()}');
return SecuredConnection(
connection,
pattern.sendKey,
pattern.recvKey,
establishedRemotePeer: remotePeerId,
establishedRemotePublicKey: remoteLibp2pPublicKey,
securityProtocolId: _protocolString,
);
} catch (e) {
await connection.close();
if (e is NoiseProtocolException) rethrow;
throw NoiseProtocolException('Failed to secure inbound connection', e);
}
}