connect method

  1. @override
Future<Session> connect({
  1. Duration? timeLimit,
  2. Uri? walletUriBase,
})
override

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);
}