unwrap static method

K4LocalKey unwrap(
  1. String wrappedKey,
  2. K4LocalKey wrappingKey
)

Implementation

static K4LocalKey unwrap(String wrappedKey, K4LocalKey wrappingKey) {
  if (!wrappedKey.startsWith(PaserkKey.k4LocalWrapPiePrefix)) {
    throw ArgumentError('Invalid k4.local-wrap format');
  }

  final payload = Uint8List.fromList(
    SafeBase64.decode(
      wrappedKey.substring(PaserkKey.k4LocalWrapPiePrefix.length),
    ),
  );

  if (payload.length < tagLength + nonceLength + K4LocalKey.keyLength) {
    throw ArgumentError('Invalid wrapped key length');
  }

  final tag = payload.sublist(0, tagLength);
  final nonce = payload.sublist(tagLength, tagLength + nonceLength);
  final ciphertext = payload.sublist(tagLength + nonceLength, payload.length);

  final authKey = _deriveAuthKey(wrappingKey.rawBytes, nonce);
  final expectedTag = _calculateTag(nonce, ciphertext, authKey);
  if (!_constantTimeEquals(tag, expectedTag)) {
    throw ArgumentError('Invalid authentication tag');
  }

  final derived = _deriveEncryptionMaterial(wrappingKey.rawBytes, nonce);
  final encryptionKey = derived.sublist(0, 32);
  final xchachaNonce = derived.sublist(32);

  final cipher = XChaCha20();
  cipher.init(
    false,
    ParametersWithIV<KeyParameter>(
      KeyParameter(Uint8List.fromList(encryptionKey)),
      Uint8List.fromList(xchachaNonce),
    ),
  );
  final decrypted = cipher.process(ciphertext);

  if (decrypted.length != K4LocalKey.keyLength) {
    throw ArgumentError('Decrypted key has invalid length');
  }

  return K4LocalKey(decrypted);
}