getPrivateKey function

Future<PrivateKey?> getPrivateKey({
  1. DataStorage? storage,
})

Get a Private Key using the specified storage strategy. If storage is not specified, it uses the LocalDataStorage class.

Implementation

Future<PrivateKey?> getPrivateKey({DataStorage? storage}) async {
  if (_cachedPrivateKey != null) {
    return _cachedPrivateKey;
  }

  storage ??= LocalDataStorage.INSTANCE;

  var keyPath = 'dsa_key:${window.location.pathname}';
  String? keyLockPath = 'dsa_key_lock:${window.location.pathname}';
  var randomToken =
      '${DateTime.now().millisecondsSinceEpoch}'
      ' ${DSRandom.instance.nextUint16()}'
      ' ${DSRandom.instance.nextUint16()}';

  var hasKeyPath = false;

  if (storage is SynchronousDataStorage) {
    hasKeyPath = (storage as SynchronousDataStorage).hasSync(keyPath);
  } else {
    hasKeyPath = await storage.has(keyPath);
  }

  if (hasKeyPath) {
    if (storage is SynchronousDataStorage) {
      (storage as SynchronousDataStorage).storeSync(keyLockPath, randomToken);
    } else {
      await storage.store(keyLockPath, randomToken);
    }

    await Future<void>.delayed(const Duration(milliseconds: 20));
    String existingToken;
    String existingKey;

    if (storage is SynchronousDataStorage) {
      existingToken = (storage as SynchronousDataStorage).getSync(keyLockPath);
      existingKey = (storage as SynchronousDataStorage).getSync(keyPath);
    } else {
      existingToken = await storage.get(keyLockPath);
      existingKey = await storage.get(keyPath);
    }

    if (existingToken == randomToken) {
      if (storage is LocalDataStorage) {
        _startStorageLock(keyLockPath, randomToken);
      }
      _cachedPrivateKey = PrivateKey.loadFromString(existingKey);
      return _cachedPrivateKey;
    } else {
      // use temp key, don't lock it;
      keyLockPath = null;
    }
  }

  _cachedPrivateKey = await PrivateKey.generate();

  if (keyLockPath != null) {
    if (storage is SynchronousDataStorage) {
      (storage as SynchronousDataStorage).storeSync(
        keyPath,
        _cachedPrivateKey!.saveToString(),
      );
      (storage as SynchronousDataStorage).storeSync(keyLockPath, randomToken);
    } else {
      await storage.store(keyPath, _cachedPrivateKey!.saveToString());
      await storage.store(keyLockPath, randomToken);
    }

    if (storage is LocalDataStorage) {
      _startStorageLock(keyLockPath, randomToken);
    }
  }

  return _cachedPrivateKey;
}