seal static method

Future<K4Seal> seal(
  1. K4LocalKey key,
  2. K4PublicKey wrappingKey
)

Implementation

static Future<K4Seal> seal(K4LocalKey key, K4PublicKey wrappingKey) async {
  if (key.rawBytes.length != K4LocalKey.keyLength) {
    throw ArgumentError(
      'Key must be exactly ${K4LocalKey.keyLength} bytes',
    );
  }

  final xpk = _ed25519PublicToX25519(wrappingKey.rawBytes);
  final headerBytes = utf8.encode(PaserkKey.k4SealPrefix);

  final x25519 = X25519();
  final ephemeralKeyPair = await x25519.newKeyPair();
  final ephemeralPublic = await ephemeralKeyPair.extractPublicKey();
  final epkBytes = Uint8List.fromList(ephemeralPublic.bytes);

  final sharedSecret = await x25519.sharedSecretKey(
    keyPair: ephemeralKeyPair,
    remotePublicKey: SimplePublicKey(xpk, type: KeyPairType.x25519),
  );
  final xk = Uint8List.fromList(await sharedSecret.extractBytes());

  final encKey = _derivePkeKey(0x01, headerBytes, xk, epkBytes, xpk);
  final authKey = _derivePkeKey(0x02, headerBytes, xk, epkBytes, xpk);
  final nonce = _deriveNonce(epkBytes, xpk);

  final encrypted = _encrypt(encKey, nonce, key.rawBytes);
  final tag = _computeSealTag(headerBytes, epkBytes, encrypted, authKey);

  final payload =
      Uint8List(tagLength + ephemeralPublicKeyLength + encrypted.length)
        ..setAll(0, tag)
        ..setAll(tagLength, epkBytes)
        ..setAll(tagLength + ephemeralPublicKeyLength, encrypted);

  return K4Seal(payload);
}