connect method
Establishes an encrypted session between the dApp and wallet endpoints.
This method should run in a synchronized block and can only be called once.
Implementation
@override
Future<Session> connect({
final Duration? timeLimit,
final Uri? walletUriBase,
}) async {
// Create a new association keypair.
final AssociationKeypair associationKeypair = await EcdsaPrivateKey.generateKey(
EllipticCurve.p256,
);
// Encode the X9.62 public key as a `base-64 URL`.
final Uint8List associationRawKey = await associationKeypair.publicKey.exportRawKey();
final AssociationToken associationToken = base64Url.encode(associationRawKey);
// Creates the wallet uri.
final Uri walletUri = association.walletUri(
associationToken,
uriPrefix: walletUriBase,
);
// Setup the current scenario.
final Duration? timeout = timeLimit ?? this.timeLimit;
await initialize(_client, walletUri, timeLimit: timeout);
// Create a new session keypair.
final SessionKeypair sessionKeypair = await EcdhPrivateKey.generateKey(EllipticCurve.p256);
// The hashing algorithm.
final Hash hash = Hash.sha256;
// Send a `hello_req` message and receive the keypoint response.
final Uint8List sessionRawKey = await sessionKeypair.publicKey.exportRawKey();
final Uint8List signature = await associationKeypair.privateKey.signBytes(sessionRawKey, hash);
final JsonRpcClientConfig config = JsonRpcClientConfig(timeLimit: timeout);
// NOTE: The current websocket implementation ([JsonRpcWebsocketClient]) sends data as a
// byte-array ([Uint8List]), otherwise [sessionRawKey + signature] would need to be sent using
// Uint8List.fromList(sessionRawKey + signature) to work on web.
final List<int> keypoint = await _client.handshake(sessionRawKey + signature, config: config);
// Derive the shared secret.
const int sharedSecretLength = SessionState.sharedSecretBitLength;
final int aesGcmSeckeyLength = SessionState.aesGcmSeckeyBitLength;
final EcdhPublicKey pubkey = await EcdhPublicKey.importRawKey(keypoint, EllipticCurve.p256);
final Uint8List sharedSecret = await sessionKeypair.privateKey.deriveBits(sharedSecretLength, pubkey);
final HkdfSecretKey seckey = await HkdfSecretKey.importRawKey(sharedSecret);
final Uint8List sharedSeckeyBuffer = await seckey.deriveBits(aesGcmSeckeyLength, hash, associationRawKey, const []);
final SharedSeckey sharedSeckey = await AesGcmSecretKey.importRawKey(sharedSeckeyBuffer);
// Store the shared secret to encrypt future requests/responses.
_sessionState.encrypt(sharedSeckey);
// Return the JSON RPC API.
return session(_client);
}